comment trouver la source de certaines macros

Il existe de nombreux emplacements pour définir une macro.Lorsque la macro est définie dans notre propre projet par nous, il est facile de trouver la position de définition correspondante. Mais quand j’essaie d’apprendre un projet Open Source célèbre, je suis souvent harcelé par la question: où trouver la source des macros, si je ne peux pas obtenir sa définition, je ne comprendrai pas certaines d’entre elles peut être deviné par leur nom). par exemple, une déclaration d’apache:

#if defined(__osf__) && defined(__alpha), #elif defined(__NSIG) 

quant à ma connaissance, je sais qu’il existe un lieu d’origine possible pour une macro:

  1. à partir de ce projet lui-même, dans un fichier source (c’est le plus facile, car on peut le trouver avec un outil)
  2. à partir d’un fichier d’en-tête d’une certaine 3ème lib, nous pouvons le grep
  3. à partir du fichier d’en-tête standard c / c ++ (où sont-ils dans linux?)
  4. depuis l’OS (où sont-ils sous Linux?)
  5. généré automatiquement par l’outil de configuration (c’est amer, je n’en ai aucune idée)
  6. à partir de l’outil de compilation comme gcc / g ++, ou dans le fichier makefile, nous pouvons définir une macro

J’ai une question à consulter:

  1. comment les différencier entre os défini et gcc / g ++ défini et configurer les macros générées par l’outil? ont-ils des caractéristiques respectives?
  2. comment trouver la source de ceux définis par os ou par C standard ou par compilateur? par exemple, utiliser grep ou find utilitaires
  3. qu’est-ce que cela signifie si une macro telle que __strange___ ne peut pas être trouvée en combinant la machine entière ( cd /;grep __strange___ -r )?

Merci d’avoir expliqué le principe et la méthode pour les distinguer et en trouver la source!

Un moyen simple et rapide de savoir où une macro a été définie consiste à redéfinir la macro et à vérifier le message Avertissement / Erreur du compilateur.

 #include  #define min(a,b) nonsense mintest.cpp(3) : warning C4005: 'min' : macro redefinition C:\Programme\Microsoft SDKs\Windows\v6.0A\include\windef.h(194) : see previous definition of 'min' 
  1. comment les différencier entre os défini et gcc / g ++ défini et configurer les macros générées par l’outil? ont-ils des caractéristiques respectives?

La grande majorité est définie quelque part dans un fichier d’en-tête. gcc -dN -E peut être utile ici. gcc -dN -E : Si vous utilisez cette approche, vous devez appeler gcc -dN -E avec les mêmes chemins d’inclusion, les mêmes options de ligne de commande -D , les mêmes variables d’environnement telles que CPATH , …, comme vous le faites lorsque vous comstackz votre source pour objecter des fichiers.

  1. comment trouver la source de ceux définis par os ou par C standard ou par compilateur? par exemple, utiliser grep ou trouver des utilitaires

RTFM. Lire le manuel bien.

  1. qu’est-ce que cela signifie si une macro telle que __strange__ ne peut pas être trouvée en combinant la machine entière (cd /;grep __strange___ -r) ?

Cela pourrait simplement signifier que ce symbole n’est pas défini sur votre ordinateur. Supposons que le code en question provient d’un paquet open source qui cible une charge de bateaux de différents systèmes, différents compilateurs, dont certains ne sont pas tout à fait conformes à la norme C ++. L’approche typique consiste à utiliser #ifdef __some_bizarre_os__ dans les parties clés du code. Ce symbole ne sera défini que sur les machines exécutant le système d’exploitation Bizarre – pas sur le vôtre.

Malheureusement, ce n’est pas le seul cas. Le symbole pourrait bien être défini même si votre grep ne peut le trouver nulle part. Le fichier makefile pourrait concaténer deux chaînes, -D__str et ange__ pour former un seul argument de ligne de commande pour le compilateur. L’option -D__strange__ pourrait se cacher dans l’une des variables d’environnement utilisées par le makefile. Les fichiers ~ / .tcshrc que certains projets exigent peuvent être extrêmement compliqués.

Mettre à jour
gcc -dM -E affiche les définitions des macros, mais pas où elles ont été définies. Une meilleure solution consiste à utiliser gcc -dN -E , puis à filtrer les lignes qui ne commencent pas par un # initial.

Les macros définies par le compilateur gcc peuvent être révélées par

 gcc -dM -E ac 

En dehors de cela, ils proviennent tous de fichiers et de sources inclus.

Si vous ne trouvez pas la macro, cela signifie que la condition sera évaluée à false.

Vous pouvez également utiliser l’option -v, elle indique où se trouvent les répertoires d’inclusion par défaut.

Pour savoir de quel fichier provient la macro:

 gcc -E $your_comstack_options $your_c_file | \ egrep "^# " | grep -v '<'| cut -f 2 -d '"' | \ sort | uniq | while read line do grep -l $your_macro $line done 

Vous devez utiliser un IDE comme Eclipse où vous pouvez simplement cliquer avec le bouton droit de la souris sur la macro et cliquer sur Ouvrir la déclaration pour vous envoyer le fichier et la ligne où la macro est définie.

Parfois, certaines macros ne sont même pas définies dans les fichiers d’en-tête, car elles sont atsortingbuées comme indicateurs au compilateur gnu (exemple: -DMYMACRO).

Il semble que ces macros soient des constantes de compilation.

Il est recommandé d’utiliser ces macros pour indiquer au compilateur que cette partie du code doit être compilée et que cette partie du code ne doit pas être compilée.

Si vous ne parvenez pas à les rechercher dans l’espace de travail de votre projet, vous devez parcourir le stream du programme et décider quelle partie du code est requirejse par votre application et définir la macro correspondante.

Par exemple;

 #ifdef (_CASE1_) ... ... ... #elif (_CASE2_) ... ... ... #endif 

Dans l’exemple ci-dessus, si le code couvert par _CASE1_ est requirejs par votre application, vous devez définir _CASE1_ . par exemple #define _CASE1_

J’espère que ça aide…

Si vous étudiez un projet open source, je suppose que vous l’avez mis en place pour pouvoir le construire. Choisissez un fichier contenant la macro que vous recherchez et utilisez votre compilateur pour générer un fichier prétraité. L’option réelle dépend du compilateur que vous utilisez, c’est -E pour gcc, vous pouvez trouver plus d’informations ici .

Notez que vous devrez probablement utiliser le système de construction de votre projet pour comstackr votre fichier et voir les options nécessaires au bon fonctionnement du préprocesseur.

Une fois que vous avez votre fichier prétraité, recherchez simplement votre macro. Il existe des options de préprocesseur qui génèrent le chemin d’access de chaque fichier inclus.

UPDATE: Cette approche ne fonctionne évidemment pas, car votre macro est développée par le processeur. Donc, à moins que vous ne reconnaissiez sa forme élargie ou ses effets, cela ne servirait à rien.

Ce qui pourrait être un peu plus utile est d’obtenir du compilateur l’impression de la séquence exacte des fichiers inclus. Ceci est réalisé dans gcc avec l’option -H.

Je trouve généralement assez Vim pour cela: CTRL-W CTRL-I et [I sont mes préférés. (Ce sont toutes sortes d’identificateurs, et CTRL-W CTRL-D et [D sont réservés aux macros.) Vous pouvez taper :help include-search pour la liste complète des commandes disponibles.

Pour que cela fonctionne, votre option de path dans Vim doit être correctement configurée. Type :set path? pour voir votre réglage actuel. Exécutez gcc -v -E -x c++ - , recherchez #include <...> search starts here: .vimrc puis copiez les répertoires et ajoutez-les à votre path (dans votre .vimrc ). (Ce que je fais est d'extraire les répertoires et de les stocker dans une variable d'environnement dans .bash_profile , et de me référer à cela dans mon .vimrc , comme dans set path=$INCLUDE_PATH .) Vous devrez peut-être append des répertoires d'inclusion spécifiques au projet. votre path aussi.

Comme d’autres l’ont dit, gcc avec l’une des options -d devrait être utilisé pour savoir où la macro est définie . Ces options ne sont pas générées par gcc -v --help , elles doivent donc être lues à l’ aide du manuel , chapitre 3.11 , recherchez -dCHARS .

Enfin mes pas sont:

  1. Utilisez gcc ... -E -dD
  2. Trouvez la définition dans le fichier de sortie
  3. Recherche en arrière # (un hachage et un espace) pour révéler le fichier