281 votes

Détecter le makefile de l'OS

Je travaille régulièrement sur plusieurs ordinateurs différents et plusieurs systèmes d'exploitation différents, tels que Mac OS X, Linux ou Solaris. Pour le projet sur lequel je travaille, je récupère mon code depuis un dépôt git distant.

J'aime pouvoir travailler sur mes projets indépendamment du terminal que j'utilise. Jusqu'à présent, j'ai trouvé des moyens de contourner les changements de système d'exploitation en modifiant le makefile à chaque changement d'ordinateur. Cependant, cela est fastidieux et cause beaucoup de maux de tête.

Comment puis-je modifier mon makefile pour qu'il détecte le système d'exploitation que j'utilise et modifie la syntaxe en conséquence ?

Voici le makefile :

cc = gcc -g
CC = g++ -g
yacc=$(YACC)
lex=$(FLEX)

all: assembleur

assembler: y.tab.o lex.yy.o
        $(CC) -o assembleur y.tab.o lex.yy.o -ll -l y

assembler.o: assembler.c
        $(cc) -o assembleur.o assembler.c

y.tab.o: assem.y
        $(yacc) -d assem.y
        $(CC) -c y.tab.c

lex.yy.o: assem.l
        $(lex) assem.l
        $(cc) -c lex.yy.c

clean:
        rm -f lex.yy.c y.tab.c y.tab.h assembleur *.o *.tmp *.debug *.acts

317voto

Trevor Robinson Points 3657

Il y a déjà beaucoup de bonnes réponses ici, mais je voulais partager un exemple plus complet qui :

  • ne suppose pas que uname existe sur Windows
  • détecte également le processeur

Les CCFLAGS définis ici ne sont pas nécessairement recommandés ou idéaux ; ils sont simplement ce que le projet auquel j'ajoutais la détection automatique d'OS/CPU utilisait.

ifeq ($(OS),Windows_NT)
    CCFLAGS += -D WIN32
    ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
        CCFLAGS += -D AMD64
    else
        ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
            CCFLAGS += -D AMD64
        endif
        ifeq ($(PROCESSOR_ARCHITECTURE),x86)
            CCFLAGS += -D IA32
        endif
    endif
else
    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Linux)
        CCFLAGS += -D LINUX
    endif
    ifeq ($(UNAME_S),Darwin)
        CCFLAGS += -D OSX
    endif
    UNAME_P := $(shell uname -p)
    ifeq ($(UNAME_P),x86_64)
        CCFLAGS += -D AMD64
    endif
    ifneq ($(filter %86,$(UNAME_P)),)
        CCFLAGS += -D IA32
    endif
    ifneq ($(filter arm%,$(UNAME_P)),)
        CCFLAGS += -D ARM
    endif
endif

8 votes

Malheureusement, la variable d'environnement PROCESSOR_ARCHITECTURE semble être virtualisée en fonction que le processus soit en 32 bits ou 64 bits. Donc, si votre make est en 32 bits et que vous essayez de construire une application en 64 bits, cela échouera. L'utiliser en combinaison avec PROCESSOR_ARCHITEW6432 a fonctionné pour moi (voir ce lien, et ceci)

5 votes

Ce serait bien si l'équipe make ajoutait quelques variables magiques avec os et arch, probablement trop de tracas.

0 votes

Cela se casse sur FreeBSD, car $OS n'est pas défini. $OSTYPE peut cependant être freebsd10.1.

123voto

dbrown0708 Points 2080

La commande uname (http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html) sans paramètres devrait vous indiquer le nom du système d'exploitation. Je l'utiliserais, puis ferais des conditionnels basés sur la valeur de retour.

Exemple

UNAME := $(shell uname)

ifeq ($(UNAME), Linux)
# faire quelque chose de propre à Linux
endif
ifeq ($(UNAME), Solaris)
# faire quelque chose de propre à Solaris
endif

0 votes

Simplement pour être explicite, cette ligne va dans votre Makefile. J'ai juste essayé cette structure dans les Makefiles sous Cygwin et OSX, et cela a fonctionné comme prévu. Une chose à essayer : Tapez uname sur votre ligne de commande. Cela vous indiquera la valeur pour ce système d'exploitation. Sous OSX, cela sera probablement "Darwin".

0 votes

Le projet GnuWin32 propose à la fois uname et Gnu make comme applications Windows natives, rendant cette technique portable à MingW dans une invite de commande ainsi qu'à Cygwin sur Windows.

0 votes

Cela échoue sur ma machine Solaris lorsqu'il est dans le fichier makefile. La commande uname est disponible sur ce système.

20voto

phsym Points 884

J'ai récemment fait des expériences afin de répondre à cette question que je me posais. Voici mes conclusions:

Comme sous Windows, on ne peut pas être certain que la commande uname est disponible, on peut utiliser gcc -dumpmachine. Cela affichera la cible du compilateur.

Il peut également y avoir un problème lors de l'utilisation de uname si vous souhaitez effectuer une compilation croisée.

Voici une liste d'exemples possibles de sortie de gcc -dumpmachine:

  • mingw32
  • i686-pc-cygwin
  • x86_64-redhat-linux

Vous pouvez vérifier le résultat dans le fichier makefile comme ceci:

SYS := $(shell gcc -dumpmachine)
ifneq (, $(findstring linux, $(SYS)))
 # Faire des choses pour Linux
else ifneq(, $(findstring mingw, $(SYS)))
 # Faire des choses pour MinGW
else ifneq(, $(findstring cygwin, $(SYS)))
 # Faire des choses pour Cygwin
else
 # Faire des choses pour les autres
endif

Cela a bien fonctionné pour moi, mais je ne suis pas sûr que ce soit une façon fiable d'obtenir le type de système. Au moins, c'est fiable pour MinGW et c'est tout ce dont j'ai besoin car cela ne nécessite pas d'avoir la commande uname ou le paquet MSYS sous Windows.

En résumé, uname vous donne le système sur lequel vous compilez, et gcc -dumpmachine vous donne le système pour lequel vous compilez.

0 votes

C'est un bon point. Cependant, est-ce que uname est inclus dans MinGW de toute façon? Néanmoins, la note supplémentaire concernant la compilation croisée est très utile.

2 votes

@Shahbaz La configuration MinGW peut installer MSYS (qui contient uname), mais c'est optionnel. Il est toujours possible de trouver des systèmes avec uniquement les outils gcc MinGW.

1 votes

Cela ne fonctionne nulle part où Clang est le compilateur par défaut, comme sur OS X et FreeBSD.

17voto

JesperE Points 34356

Le fichier make de git contient de nombreux exemples de comment se passer d'autoconf/automake, tout en fonctionnant sur une multitude de plateformes unixy.

13 votes

Sachant que Git n'utilise pas Autofools me conforte dans mon aversion pour eux...

11 votes

"Autofools"? Était-ce une faute de frappe délibérée? :)

6 votes

C'était. Mais à réfléchir, je pense que j'aime encore mieux "Autostools". :D

11voto

Ken Jackson Points 71

Mise à jour : Je considère maintenant cette réponse comme obsolète. J'ai posté une nouvelle solution parfaite plus bas.

Si votre fichier makefile peut être exécuté sur un Windows non-Cygwin, uname peut ne pas être disponible. C'est embêtant, mais voici une solution potentielle. Vous devez d'abord vérifier si Cygwin est présent pour l'exclure, car il contient également WINDOWS dans sa variable d'environnement PATH.

ifneq (,$(findstring /cygdrive/,$(PATH)))
    UNAME := Cygwin
else
ifneq (,$(findstring WINDOWS,$(PATH)))
    UNAME := Windows
else
    UNAME := $(shell uname -s)
endif
endif

0 votes

C'est bon de le savoir! Pouvez-vous me dire une chose, cependant? Je n'utilise pas Cygwin, mais j'ai MinGW installé avec son chemin bin dans PATH. Si je saisis uname à partir d'un terminal cmd normal, cela me donne MINGW. Ce que je veux dire, c'est que j'ai toujours uname sans utiliser Cygwin. J'ai également git bash, mais je n'ai pas essayé uname dessus (en ce moment je suis sous Linux). Pouvez-vous me dire comment ces deux peuvent être intégrés dans votre code?

0 votes

Si vous êtes sûr que uname est disponible, c'est la meilleure solution. Mais dans mon environnement, tout le monde utilise Windows et peu de gens ont soit cygwin ou mingw installé, donc je n'ai aucune garantie que même quelque chose d'aussi standard que uname fonctionnera. Actuellement, je rencontre des difficultés avec le code ci-dessus exécutant make.exe dans un shell cmd. Windows est une plateforme très frustrante à travailler avec.

0 votes

Ce que je veux dire, c'est qu'avant de tester l'existence de WINDOWS dans le PATH, vous vous assurez de ne pas traiter avec cygwin, comment pouvez-vous vous assurer de ne pas traiter avec MinGW? Par exemple, est-il possible dans un Makefile de tester si une commande peut être exécutée, et si uname ne pouvait pas être exécuté, nous comprendrions que nous sommes sous Windows?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X