Je travaille régulièrement sur plusieurs ordinateurs différents et plusieurs systèmes d'exploitation différents, qui sont Mac OS X, Linux ou Solaris. Pour le projet sur lequel je travaille, je tire mon code d'un dépôt git distant.
J'aime pouvoir travailler sur mes projets quel que soit le terminal où je suis. Jusqu'à présent, j'ai trouvé des moyens de contourner les modifications du système d'exploitation en changeant le makefile chaque fois que je change d'ordinateurs. Cependant, cela est fastidieux et provoque un tas de maux de tête.
Comment puis-je modifier mon makefile afin 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: assembler
assembler: y.tab.o lex.yy.o
$(CC) -o assembler y.tab.o lex.yy.o -ll -l y
assembler.o: assembler.c
$(cc) -o assembler.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 assembler *.o *.tmp *.debug *.acts
PROCESSOR_ARCHITECTURE
envvar semble être virtualisé selon que le processus est 32 bits ou 64 bits. Donc, si vous avezmake
32 bits et que vous essayez de créer une application 64 bits, cela échouera. L'utiliser en combinaison avec aPROCESSOR_ARCHITEW6432
fonctionné pour moi (voir ceci et cela )make
équipe ajoutait quelques variables magiques avec os et arch, probablement trop de problèmes.OS
soit défini sur des systèmes non Windows. Rendre les friandises non réglées comme vides, ce qui provoquera un saut dans leuname
bloc basé. Il vous suffit d'y ajouter un chèque FreeBSD./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: ligne 0:ifeq (,Windows_NT)' make: *** [os] Error 2
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 conditions en fonction de la valeur de retour.
Exemple
la source
Détectez le système d'exploitation à l'aide de deux astuces simples:
OS
uname
commandeOu un moyen plus sûr, sinon sous Windows et
uname
indisponible:Ken Jackson propose une alternative intéressante si vous souhaitez distinguer Cygwin / MinGW / MSYS / Windows. Voir sa réponse qui ressemble à ça:
Ensuite, vous pouvez sélectionner les éléments pertinents en fonction de
detected_OS
:Remarques:
La commande
uname
est la même queuname -s
parce que l'option-s
(--kernel-name
) est la valeur par défaut. Voyez pourquoiuname -s
c'est mieux queuname -o
.L'utilisation de
OS
(au lieu deuname
) simplifie l'algorithme d'identification. Vous pouvez toujours utiliser uniquementuname
, mais vous devez gérer lesif/else
blocs pour vérifier toutes les variations de MinGW, Cygwin, etc.La variable d'environnement
OS
est toujours définie"Windows_NT"
sur différentes versions de Windows (voir%OS%
variable d'environnement sur Wikipedia ).Une alternative à
OS
est la variable d'environnementMSVC
(elle vérifie la présence de MS Visual Studio , voir l' exemple utilisant Visual C ++ ).Ci-dessous, je fournis un exemple complet en utilisant
make
etgcc
pour construire une bibliothèque partagée:*.so
ou en*.dll
fonction de la plateforme. L'exemple est aussi simple que possible pour être plus compréhensible.Pour installer
make
etgcc
sur Windows, voir Cygwin ou MinGW .Mon exemple est basé sur cinq fichiers
Rappel:
Makefile
est mis en retrait à l'aide de la tabulation . Attention lors du copier-coller sous les exemples de fichiers.Les deux
Makefile
fichiers1.
lib/Makefile
2.
app/Makefile
Pour en savoir plus, lisez la documentation sur les variables automatiques comme indiqué par cfi .
Le code source
-
lib/hello.h
-
lib/hello.c
-
app/main.c
La construction
Corrigez le copier-coller de
Makefile
(remplacez les espaces de tête par une tabulation).La
make
commande est la même sur les deux plateformes. La sortie donnée est sur des OS de type Unix:La course
L'application nécessite de savoir où se trouve la bibliothèque partagée.
Sous Windows, une solution simple consiste à copier la bibliothèque où se trouve l'application:
Sur les OS de type Unix, vous pouvez utiliser la
LD_LIBRARY_PATH
variable d'environnement:Exécutez la commande sous Windows:
Exécutez la commande sur les systèmes d'exploitation de type Unix:
la source
uname
n'est pas Linux. Je donne juste un exemple dont vous n'avez peut-être pas besoin, mais cela peut aider quelqu'un à chercher (sur le Web) un moyen d'implémenter unMakefile
pour les deux plates-formes ;-) Que dois-je changer dans ma réponse? Vivelib/Makefile
exemple,target
est utilisé pour.so
vs.dll
. Un exemple parallèle pour leapp/makefile
serait utile pour la comparaisonempty string
vs.exe
pour le nom de fichier de l'application. Par exemple, je ne vois généralement pasapp.exe
sur les systèmes d'exploitation de type Unix. ;-)J'expérimentais récemment pour répondre à cette question que je me posais. Voici mes conclusions:
Étant donné que dans Windows, vous ne pouvez pas être sûr que la
uname
commande est disponible, vous pouvez utilisergcc -dumpmachine
. Cela affichera la cible du compilateur.Il peut également y avoir un problème lors de l'utilisation
uname
si vous souhaitez effectuer une compilation croisée.Voici un exemple de liste de sortie possible de
gcc -dumpmachine
:Vous pouvez vérifier le résultat dans le makefile comme ceci:
Cela a bien fonctionné pour moi, mais je ne suis pas sûr que ce soit un moyen fiable d'obtenir le type de système. Au moins, il est fiable à propos de MinGW et c'est tout ce dont j'ai besoin car il ne nécessite pas d'avoir la
uname
commande ou le package MSYS dans Windows.Pour résumer,
uname
vous donne le système sur lequel vous compilez etgcc -dumpmachine
vous donne le système pour lequel vous compilez.la source
uname
vient pas deMinGW
toute façon? Néanmoins, la note supplémentaire concernant la compilation croisée est excellente.$(shell $(CC) -dumpmachine)
. Depuis OS X Sierra, la commande -dumpmachine fonctionne sur Clang.x86_64-apple-darwin16.6.0
et que les travaux castrés vous l' appelezgcc
,cc
ouclang
, mais pascl
Le makefile git contient de nombreux exemples de gestion sans autoconf / automake, tout en fonctionnant sur une multitude de plates-formes unixy.
la source
if (!usesAutotools(git)) aversionTo(autotools) = justified;
je préciserai également que ce ne sont que les outils auxquels je suis opposé. Je suis sûr que les gens Autotools sont des gens sympas.Mise à jour: je considère maintenant cette réponse comme obsolète. J'ai posté une nouvelle solution parfaite plus bas.
Si votre makefile s'exécute sur des fenêtres non Cygwin,
uname
peut ne pas être disponible. C'est gênant, mais c'est une solution potentielle. Vous devez d'abord vérifier Cygwin pour l'exclure, car il a aussi WINDOWS dans saPATH
variable d'environnement.la source
uname
j'émets à partir d'un terminal cmd normal, cela me donne MINGW. Ce que je veux dire, c'est que j'ai toujoursuname
sans utiliser Cygwin. J'ai aussi git bash, mais je n'ai pas essayé uname (en ce moment je suis sous Linux). Pouvez-vous me dire comment ces deux peuvent être incorporés dans votre code?uname
elle ne pouvait pas être exécutée, nous comprendrions que nous sommes dans Windows?C'est le travail que l' automake / autoconf de GNU est conçu pour résoudre. Vous voudrez peut-être les enquêter.
Alternativement, vous pouvez définir des variables d'environnement sur vos différentes plates-formes et rendre votre Makefile conditionnel par rapport à celles-ci.
la source
make
à faire ce que je veux. Est-ce que je veux maintenant entrer aussi dans automake / autoconf? - NON. Ce qui peut être fait dans le makefile, devrait certainement être fait dans le makefile, ne serait-ce que pour ne pas avoir plusieurs points d'arrêt à chaque fois que je souhaite modifier la compilation et le lien.J'ai finalement trouvé la solution parfaite qui résout ce problème pour moi.
La variable UNAME est définie sur Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (ou probablement Solaris, Darwin, OpenBSD, AIX, HP-UX) ou Unknown. Il peut ensuite être comparé dans le reste du Makefile pour séparer toutes les variables et commandes sensibles au système d'exploitation.
La clé est que Windows utilise des points-virgules pour séparer les chemins dans la variable PATH tandis que tout le monde utilise des deux-points. (Il est possible de créer un répertoire Linux avec un ';' dans le nom et de l'ajouter à PATH, ce qui casserait cela, mais qui ferait une telle chose?) Cela semble être la méthode la moins risquée pour détecter Windows natif car il n'a pas besoin d'un appel shell. Le Cygwin et MSYS PATH utilisent des deux-points, donc uname est appelé pour eux.
Notez que la variable d'environnement OS peut être utilisée pour détecter Windows, mais pas pour faire la distinction entre Cygwin et Windows natif. Le test de l'écho des citations fonctionne, mais il nécessite un appel shell.
Malheureusement, Cygwin ajoute des informations de version à la sortie de uname , j'ai donc ajouté les appels «patsubst» pour le changer en «Cygwin». De plus, uname for MSYS a en fait trois sorties possibles commençant par MSYS ou MINGW, mais j'utilise aussi patsubst pour tout transformer en juste 'MSYS'.
S'il est important de distinguer les systèmes Windows natifs avec et sans uname.exe sur le chemin, cette ligne peut être utilisée à la place de l'affectation simple:
Bien sûr, dans tous les cas, GNU make est requis, ou une autre marque qui prend en charge les fonctions utilisées.
la source
J'ai rencontré ce problème aujourd'hui et j'en avais besoin sur Solaris alors voici une façon standard POSIX de faire (quelque chose de très proche) cela.
la source
Voici une solution simple qui vérifie si vous êtes dans un environnement Windows ou de type posix (Linux / Unix / Cygwin / Mac):
Il profite du fait que l'écho existe à la fois dans les environnements de type posix et Windows, et que dans Windows, le shell ne filtre pas les guillemets.
la source
$PATH
pourrait faire référence à un autreecho
(le mien le fait ...)-mwindows
indicateur ou choisir entre un.dll
ou.so
, cela échouera.Notez que les Makefiles sont extrêmement sensibles à l'espacement. Voici un exemple de Makefile qui exécute une commande supplémentaire sur OS X et qui fonctionne sur OS X et Linux. Dans l'ensemble, cependant, autoconf / automake est la voie à suivre pour tout ce qui n'est pas trivial.
la source
Une autre façon de procéder consiste à utiliser un script "configure". Si vous en utilisez déjà un avec votre makefile, vous pouvez utiliser une combinaison de uname et sed pour faire avancer les choses. Tout d'abord, dans votre script, faites:
Ensuite, afin de mettre cela dans votre Makefile, commencez avec Makefile.in qui devrait avoir quelque chose comme
en elle.
Utilisez la commande sed suivante dans votre script de configuration après le
UNAME=uname
bit.Maintenant, votre makefile devrait avoir
UNAME
défini comme vous le souhaitez. Si les instructions / elif / else sont tout ce qui reste!la source
J'ai eu un cas où j'ai dû détecter la différence entre deux versions de Fedora, pour modifier les options de ligne de commande pour inkscape:
- dans Fedora 31, l'inkscape par défaut est 1.0beta qui utilise
--export-file
- dans Fedora <31, l'inkscape par défaut est 0.92 qui utilise
--export-pdf
Mon Makefile contient les éléments suivants
Cela fonctionne car
/etc/os-release
contient une lignede sorte que la commande shell dans le Makefile renvoie la chaîne
VERSION_ID=<value>
, puis la commande eval agit sur cela pour définir la variable MakefileVERSION_ID
. Cela peut évidemment être modifié pour d'autres systèmes d'exploitation en fonction de la façon dont les métadonnées sont stockées. Notez que dans Fedora, il n'y a pas de variable d'environnement par défaut qui donne la version du système d'exploitation, sinon j'aurais utilisé ça!la source