2010-02-12 4 views
2

Un projet doit être compilé pour Windows, Linux et une cible intégrée. L'application présente des différences de comportement lors de l'exécution sur des cibles hôtes ou intégrées. Pour résumer mes besoins, voici le tableau:Détection de compilation Windows et * nix

Target    Compiler  Behavior 
    Windows    MSVC, gcc   A 
    Host Linux   gcc    A 
    Embedded Linux  cross pltf gcc B 

Je souhaite créer un Makefile qui reconnaîtrait le compilateur et les différences environnementales automatiquement (sans besoin de passer des paramètres/définit manuellement). Est-il possible de résoudre ce problème en utilisant simplement la compilation conditionnelle au niveau du fichier source C?
Je n'utilise pas automake jusqu'à maintenant. gcc

Répondre

6

Les autotools ont été faites pour résoudre ce problème. Un Makefile en lui-même ne peut pas le faire.

En ce qui concerne la compilation conditionnelle, il y a plusieurs macros disponibles que ces compilateurs définissent (par exemple _MSC_VER pour MSVC++, _WIN32 pour Windows et Linux et __linux__ pour). De même, gcc fournit assertions for handling different CPU targets.

Target   Compiler  Conditional 
Windows  MSVC++  #ifdef _MSC_VER 
Windows  gcc   #if defined(_WIN32) && defined(__GNUC__) 
Linux   gcc   #if defined(__linux__) && defined(__GNUC__) 
Platform (x86) gcc   #if #cpu(i386) 
Platform (arm) gcc   #if #cpu(arm) 

Cela devrait suffire à vos besoins.

+1

Autotools fonctionnera pour ce genre de chose, mais il peut être un très grand nombre de frais généraux pour quelques projets. –

+0

Je suis d'accord avec Matt. Impliquer Autotools pour un projet de ce type (et de la taille) que j'ai est un overhead. –

+0

Vous n'avez pas besoin d'utiliser Makefiles. Il y a d'autres options. –

0

définira

__linux__ 

lors de la compilation sur Linux. MSVC définit quelque chose de similaire - je ne sais pas quoi, mais je suis sûr que les docs vous diront

mais vous avez vraiment besoin d'apprendre à utiliser configure. C'est pour ça. C'est une douleur à apprendre mais très utile (automake, autoconf etc)

2

Ma réponse est: probablement. Cela dépend des différences entre vos environnements.

Je générerais une liste des macros prédéfinies par le préprocesseur dans gcc pour chacun de vos environnements. Tout ce que vous devez faire est de créer un fichier vide, dites foo.h, et exécutez la commande suivante: gcc -E -dM foo.h pour chaque environnement. Je rediriger la sortie vers un fichier différent pour chaque environnement.

Ensuite, comparez les macros prédéfinies et cherchez-en une qui correspond à la facture. Dans votre question, vous avez indiqué que l'environnement intégré a un comportement différent de celui des plateformes Windows et Host Linux. En supposant que vous utilisez une architecture de puce différente pour l'environnement intégré, il devrait y avoir une macro définie qui indique l'architecture. Par exemple, sur ma boîte Linux 64 bits, __x86_64__ est définie.

Une fois que vous avez cette information, utilisez cette macro comme valeur conditionnelle:

#ifdef MACRO_INDICATING_EMBEDDED 
// Behavior B 
#else 
// Behavior A 
#endif 
+1

Vous n'avez pas vraiment besoin d'un fichier fictif - vous pouvez simplement le faire comme ceci: '$ gcc -dM -E -

+0

Merci, @Paul. J'ai tout oublié de la lecture de l'entrée standard. Bien sûr,/dev/null ne fonctionnera pas sous Windows. –

0

Vous pouvez essayer une combinaison de macros prédéfinies pour operating systems et architectures; peut-être aussi intéressant: compiler ids.

Si vous ne voulez pas utiliser un système de compilation plus sophistiqué, vous pouvez analyser les arguments de la ligne de commande dans votre fichier makefile. Un exemple simple serait l'ajout de .exe aux noms exécutables sur Windows.Pour cela, j'ai le code comme celui-ci dans le makefile

ifeq ($(target),win32) 
    foo_binary := $(foo_binary).exe 
endif 

et lancez make via un fichier make.bat contenant

@make.exe target=win32 %*