2009-06-10 10 views
1

Étant donné un projet C qui doit prendre en charge plusieurs environnements, comment est-ce que j'utilise le préprocesseur pour appliquer exactement qu'un environnement est défini?Comment appliquer exactement une définition?

Je peux déjà faire:

 
    #if defined PROJA 
    (blah blah blah) 
    #elif defined PROJB 
    (etc) 
    #else 
    #error "No project defined" 
    #endif 

Tout ce qui fait, bien que, me dire si 0 projets sont définis. Si une âme utile définit à la fois le projet A et le projet B, le préprocesseur n'assumera que le projet A. Cependant, le comportement correct, de mon point de vue, est de marquer une erreur.

Accordé, avec seulement 2 projets définis ce problème est trivial. Comment puis-je le résoudre avec 200?

+3

avec 200 un hack préprocesseur serait la douleur absolue de maintenir, alors vous devez plutôt faire le makesystem prendre soin de ce –

Répondre

2

ont peut-être des fichiers différents

include_proja.h 
include_projc.h 

puis utilisez votre Makefile ou quoi que pour inclure le bon fichier. Vous pouvez ensuite générer 200 fichiers distincts avec le code et inclure les bons au moment de la compilation.

Ce genre de chose est ce que les systèmes de construction sont pour. Si vous faites quelque chose de bizarre avec des macros ... trouvez un meilleur moyen en dehors du code source.

Chaque fichier peut faire (Excusez la verbosité ici)

#define A_PROJECT_INCLUDE_WAS_INCLUDED 

Et puis faire

#ifndef A_PROJECT_INCLUDE_WAS_INCLUDED 
    #error "No project include" 
#endif 

Mais certains symboles manquants va casser de toute façon, selon toute vraisemblance.

Bonne chance

+1

« Ce genre de chose est ce que construire des systèmes sont pour. Si vous faites quelque chose de bizarre comme ça avec les macros ... trouver un meilleur moyen en dehors du code source. " Vous avez totalement raison. – JXG

3

quelque chose comme ceci:

#if defined PROJA 
    #ifdef HAVE_PROJ 
    #error 
    #endif 

    #define HAVE_PROJ 
#endif 

#if defined PROJB 
    #ifdef HAVE_PROJ 
    #error 
    #endif 

    #define HAVE_PROJ 
#endif 

#ifndef HAVE_PROJ 
    #error No project selected (you need to define PROJA, PROJB, or ...) 
#endif 
+0

Je pense que cela deviendra sombre rapidement et n'est pas vraiment quelque chose qui devrait être fait dans les macros à mon humble avis. –

0

Le problème avec ifs imbriqués est que vous finirez avec n^2 tests différents pour les projets n.

Vous avez juste besoin d'une expression qui donnera une erreur de compilation dans ce cas. Peut-être:

#ifdef PROJA 
#define PROJA-TEST " 
#else 
#define PROJA-TEST "" 
#endif 

et ainsi de suite pour B, C, etc.

Puis:

const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST " "More than one project is defined!"; 

EDIT: ... Bien sûr, ce que les tests qu'un nombre impair de projets sont définis .Mais cela devrait fonctionner:

#ifdef PROJA 
#define PROJA-TEST (
#endif 

et ainsi de suite, puis

const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST "More than one project is defined!"); 
+1

Ma première pensée a été, "Ouais, c'est comme ça que je le ferais aussi." Mon deuxième était, "Alors c'est pourquoi personne n'aime plus le C?" –

+0

Exactement. Le préprocesseur est sacrément mauvais. –

-1

vous pouvez peut-être faire quelque chose comme:

#if PROJ==A 
(blah blah blah) 
#elif PROJ==B 
(etc) 
#else 
#error "No project defined" 
#endif 
2

Essayez cette

#define ENV_UNKNOWN 0 
#define ENV_MACOSX 1 
#define ENV_LINUX 2 
#define ENV_WIN32 3 
/* and so on */ 


#ifndef ENVIRONMENT 
/* no environment given, default to something (perhaps) */ 
#define ENVIRONMENT ENV_UNKNOWN 
#endif 

/* and now the environment specific parts */ 
#if (ENVIRONMENT == ENV_MACOSX) 
#include "macosx_port.h" 
#endif 

#if (ENVIRONMENT == ENV_LINUX) 
#include "linux_port.h" 
#endif 

#if (ENVIRONMENT == ENV_WIN32) 
#include "win32_port.h" 
#endif 

#if (ENVIRONMENT == ENV_UNKNOWN) 
#error You have to specify the ENVIRONMENT. 
#endif 

Maintenant vous pouvez spécifiez l'environnement que vous voulez compiler sur la ligne de commande, comme ceci:

cc -DENVIRONMENT=2 ... 

Une autre façon est d'inclure/relier différents modules de votre système de construction en fonction de l'environnement que vous compilez pour.

2
#if defined PROJA 
bool one_project_defined = true; 
#endif 

#if defined PROJB 
bool one_project_defined = true; 
#endif 

#if defined PROJC 
bool one_project_defined = true; 
#endif 

#if defined PROJD 
bool one_project_defined = true; 
#endif 

one_project_defined; // Won't compile in wrong builds 
+1

C'est court et simple. Cela me frappe cependant comme une sorte de hacky. – Brian

+0

Jusqu'à ce qu'une coopérative utile fasse des travaux de maintenance et pense: «Hé, cette variable n'est plus utilisée ...» – David

Questions connexes