2010-06-08 4 views
1

Dans xcode, lors de la compilation d'applications avec gcc, je souhaite lancer des erreurs de compilation si NSZombieEnabled est activé pour une distribution, ce qui m'assure que la compilation échoue et que je gagne ne fais pas accidentellement quelque chose de stupide.Comment lancer manuellement une erreur de compilation dans GCC et Xcode

J'ai fait un peu de googling, mais je n'arrivais pas à comprendre comment faire pour que le compilateur soit libéré si une certaine condition était remplie. Cela doit sûrement être facile, est-ce que je ne le trouve pas?

Répondre

11

Utilisation the #error directive:

#if SHOULD_FAIL 
#error "bad compiler!" 
#endif 

int main() 
{ 
    return 0; 
} 
 
$ gcc a.c -DSHOULD_FAIL=0 # passes fine 
$ gcc a.c -DSHOULD_FAIL=1 
a.c:2:2: error: #error "bad compiler!" 

Depuis NSZombieEnabled est une variable d'environnement, vous aurez besoin de faire quelque chose d'intelligent dans votre script de compilation pour définir votre macro zéro ou un.

Strictement parlant, la directive #error se produit dans le préprocesseur C, pas gcc. Mais cela ne devrait pas avoir d'importance dans le cas que vous avez décrit.

+0

Ce semble dur ... ne peut pas sembler trouver un moyen – coneybeare

+0

@coneybeare: NSZombieEnabled est une variable d'environnement que vous définissez à ** temps d'exécution **. Vous n'avez pas besoin de vous en préoccuper au moment de la compilation. Cette technique est cependant utile si vous avez des macros de débogage à la compilation. – JeremyP

+0

+1 notez que vous pouvez également faire '#warning Ceci est un avertissement' pour émettre un avertissement au lieu d'une erreur. –

1

NSZombieEnabled est un drapeau de l'environnement et, à ma connaissance, ne devrait pas affecter le binaire résultant (bien que cela peut affecter la vitesse de la compilation.)

0

Une autre chose intéressante que vous pouvez faire est de manipuler la sortie de votre build scénario. Si vous utilisez un script de génération personnalisée dans le cadre de votre processus de construction, vous pouvez faire quelque chose comme:

echo "error: this build step failed!" 

Ou:

echo "warning: this build step could be potentially faulty" 

Ceux-ci produisent des erreurs ou des avertissements (respectivement) qui montrera dans la fenêtre des résultats de construction. Je l'ai utilisé quelques fois, et c'est vraiment utile.

1

Un assertion de temps complique() - a.k.a. affirmation statique - peut être utile. Voici le mien, dérivé principalement de http://www.pixelbeat.org/programming/gcc/static_assert.html:

/*----------------------------------------------------------------------------- 
* Compile-time ASSERT(). Similar to the BOOST_STATIC_ASSERT(). And the C++0x 
* static_assert(), which also has a parameter for a useless error message 
* (see correction!). Our ASSERT() can be placed anywhere in the code, except: 
* 
* o In a twice-included header file, without a #ifndef...#endif wrapper. 
* o In the middle of a structure definition (or enum definition). 
* o In C89 or C90, after a statement. But you can wrap it in braces! 
* 
* If you want stick something in the middle of a structure definition 
* you'll need to use the ugly, three-line construct #if...#error...#endif. 
* And if you do do this, the pre-processor has a much more limited idea of 
* what a "constant expression" is. 
* 
* This is a refinement of ideas from the web (www.pixebeat.org is good). It 
* is shorter than BOOST. And, I believe, is better than Linus Torvald's 
* suggestion for an improved BUILD_BUG_ON(). And the do{...}while(0) wrapper 
* you commonly see is totally inapplicable here: it limits permissible 
* locations. 
* 
* The web has many suggestions using arrays with a negative index. But with 
* GCC, most of these do not detect a NON-CONSTANT arg (which is easy enough 
* to do in error), except for the attractive 'extern int foo[expression]', 
* which also gives an 'unused variable' warning (which might be fixable via 
* (void)foo). GCC 4.3 apparently has a built-in static_assert(). Update: 
* typedef int array[expression] seems also to be good. 
*/ 
#define CONCAT_TOKENS(a, b) a ## b 
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b) 
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)} 

Mais je corrige mon avis sur le message 'inutile' en C++ 0x:

/*----------------------------------------------------------------------------- 
* Correction!: The message in static_assert() isn't quite useless, and we've 
* added it to ASSERTM(). This is needed for the case where two different 
* header files happen by chance to have two ASSERT()'s on the same line, or 
* likewise for a source file and a header file. 
* 
* We could also handle this via __COUNTER__, but this isn't supported by 
* the SGI compiler (and is uglier). And we can't use __FILE__, because it 
* doesn't usually expand to a valid C token (e.g. it has a dot c or dot h). 
*/ 
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)} 

Quelques exemples:

/*----------------------------------------------------------------------------- 
* Example: 
*/ 
ASSERTM (sizeof (int16) == 2, my_global_header_h); 
ASSERTM (sizeof (ord32) == 4, my_global_header_h); 
ASSERTM (sizeof (int64) == 8, my_global_header_h); 

/*----------------------------------------------------------------------------- 
* Equally good, I believe, is the following variant, but it is slightly 
* longer (and not used by us at the present time): 
*/ 
#define ASSERTt(e) typedef int EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__)[1-2*!(e)]