Ich arbeite routinemäßig auf mehreren verschiedenen Computern und verschiedenen Betriebssystemen, nämlich Mac OS X, Linux oder Solaris. Für das Projekt, an dem ich arbeite, ziehe ich meinen Code aus einem Remote-Git-Repository.
Ich möchte in der Lage sein, an meinen Projekten zu arbeiten, unabhängig davon, an welchem Terminal ich mich befinde. Bisher habe ich Wege gefunden, um die Betriebssystemänderungen zu umgehen, indem ich das Makefile jedes Mal ändere, wenn ich den Computer wechsle. Dies ist jedoch langwierig und verursacht eine Reihe von Kopfschmerzen.
Wie kann ich mein Makefile so ändern, dass es erkennt, welches Betriebssystem ich verwende, und die Syntax entsprechend ändert?
Hier ist das 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
scheint der envvar virtualisiert zu sein, je nachdem, ob der Prozess 32-Bit oder 64-Bit ist. Wenn Siemake
also 32-Bit sind und versuchen, eine 64-Bit-Anwendung zu erstellen, schlägt dies fehl. Die Verwendung in Kombination mitPROCESSOR_ARCHITEW6432
hat für mich funktioniert (siehe dies und das )make
Team ein paar magische Variablen mit OS und Arch hinzufügen würde, wahrscheinlich zu viel Mühe.OS
auf Nicht-Windows-Systemen eingestellt ist. Deaktivieren Sie Leckereien genauso wie leer, was zu einem Sprung zumuname
Block auf der Basis führt. Sie müssen dort nur einen FreeBSD-Check hinzufügen./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: Zeile 0:ifeq (,Windows_NT)' make: *** [os] Error 2
Der Befehl uname ( http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html ) ohne Parameter sollte Ihnen den Namen des Betriebssystems mitteilen. Ich würde das verwenden und dann Bedingungen basierend auf dem Rückgabewert erstellen.
Beispiel
quelle
Erkennen Sie das Betriebssystem mit zwei einfachen Tricks:
OS
uname
BefehlOder sicherer, wenn nicht unter Windows und
uname
nicht verfügbar:Ken Jackson schlägt eine interessante Alternative vor, wenn Sie Cygwin / MinGW / MSYS / Windows unterscheiden möchten. Sehen Sie seine Antwort , die so aussieht:
Dann können Sie die relevanten Dinge auswählen, abhängig von
detected_OS
:Anmerkungen:
Der Befehl
uname
ist der gleiche wie,uname -s
da option-s
(--kernel-name
) die Standardeinstellung ist. Sehen Sie, warumuname -s
ist besser alsuname -o
.Die Verwendung von
OS
(anstelle vonuname
) vereinfacht den Identifikationsalgorithmus. Sie können immer noch ausschließlich verwendenuname
, müssen sich jedoch mitif/else
Blöcken befassen , um alle Variationen von MinGW, Cygwin usw. zu überprüfen.Die Umgebungsvariable
OS
ist in"Windows_NT"
verschiedenen Windows-Versionen immer auf eingestellt (siehe%OS%
Umgebungsvariable auf Wikipedia ).Eine Alternative dazu
OS
ist die UmgebungsvariableMSVC
(sie überprüft das Vorhandensein von MS Visual Studio , siehe Beispiel mit Visual C ++ ).Im Folgenden gebe ich ein vollständiges Beispiel für die Verwendung
make
undgcc
Erstellung einer gemeinsam genutzten Bibliothek:*.so
oder*.dll
je nach Plattform. Das Beispiel ist so einfach wie möglich, um verständlicher zu sein.Informationen zur Installation
make
undgcc
unter Windows finden Sie unter Cygwin oder MinGW .Mein Beispiel basiert auf fünf Dateien
Erinnerung:
Makefile
wird mithilfe einer Tabelle eingerückt . Vorsicht beim Einfügen unter Beispieldateien.Die zwei
Makefile
Dateien1.
lib/Makefile
2.
app/Makefile
Weitere Informationen finden Sie in der Dokumentation zu automatischen Variablen , auf die von cfi hingewiesen wird .
Der Quellcode
- -
lib/hello.h
- -
lib/hello.c
- -
app/main.c
Der Build
Korrigieren Sie das Kopieren und Einfügen von
Makefile
(ersetzen Sie führende Leerzeichen durch eine Tabelle).Der
make
Befehl ist auf beiden Plattformen gleich. Die angegebene Ausgabe erfolgt unter Unix-ähnlichen Betriebssystemen:Der Lauf
Die Anwendung muss wissen, wo sich die gemeinsam genutzte Bibliothek befindet.
Unter Windows besteht eine einfache Lösung darin, die Bibliothek zu kopieren, in der sich die Anwendung befindet:
Unter Unix-ähnlichen Betriebssystemen können Sie die
LD_LIBRARY_PATH
Umgebungsvariable verwenden:Führen Sie den Befehl unter Windows aus:
Führen Sie den Befehl unter Unix-ähnlichen Betriebssystemen aus:
quelle
uname
nicht Linux. Ich gebe nur ein Beispiel, das Sie möglicherweise nicht benötigen, aber dies kann jemandem helfen, der (im Web) nach einer Möglichkeit sucht, eineMakefile
für beide Plattformen zu implementieren ;-) Was soll ich in meiner Antwort ändern? Prostlib/Makefile
Beispieltarget
wird für.so
vs verwendet.dll
. Ein paralleles Beispiel für dieapp/makefile
wäre nützlich für denempty string
vs-.exe
Vergleich für den App-Dateinamen. Zum Beispiel sehe ich normalerweise nichtapp.exe
auf Unix-ähnlichen Betriebssystemen. ;-)Ich habe kürzlich experimentiert, um diese Frage zu beantworten, die ich mir gestellt habe. Hier sind meine Schlussfolgerungen:
Da Sie in Windows nicht sicher sein können, ob der
uname
Befehl verfügbar ist, können Sie ihn verwendengcc -dumpmachine
. Dadurch wird das Compilerziel angezeigt.Möglicherweise liegt auch ein Problem bei der Verwendung vor,
uname
wenn Sie eine Cross-Kompilierung durchführen möchten.Hier ist eine Beispielliste möglicher Ausgaben von
gcc -dumpmachine
:Sie können das Ergebnis im Makefile folgendermaßen überprüfen:
Es hat bei mir gut funktioniert, aber ich bin mir nicht sicher, ob es ein zuverlässiger Weg ist, den Systemtyp zu ermitteln. Zumindest ist MinGW zuverlässig und das ist alles, was ich brauche, da der
uname
Befehl oder das MSYS- Paket in Windows nicht erforderlich sind .Zusammenfassend
uname
gibt es Ihnen das System, auf dem Sie kompilieren, undgcc -dumpmachine
das System für das Sie kompilieren.quelle
uname
mitMinGW
? Trotzdem ist der zusätzliche Hinweis zur Cross-Compilation großartig.$(shell $(CC) -dumpmachine)
. Ab OS X Sierra funktioniert der Befehl -dumpmachine unter Clang.x86_64-apple-darwin16.6.0
und das funktioniert , ob Sie es nennengcc
,cc
oderclang
aber nichtcl
Das Git-Makefile enthält zahlreiche Beispiele für die Verwaltung ohne Autoconf / Automake und funktioniert dennoch auf einer Vielzahl von Unixy-Plattformen.
quelle
if (!usesAutotools(git)) aversionTo(autotools) = justified;
Ich werde auch klarstellen, dass es nur die Werkzeuge sind, denen ich abgeneigt bin. Ich bin sicher, die Autotools-Leute sind nette Leute.Update: Ich halte diese Antwort jetzt für veraltet. Ich habe weiter unten eine neue perfekte Lösung veröffentlicht.
Wenn Ihr Makefile möglicherweise unter Nicht-Cygwin-Windows ausgeführt wird, ist es
uname
möglicherweise nicht verfügbar. Das ist umständlich, aber dies ist eine mögliche Lösung. Sie müssen zuerst nach Cygwin suchen, um dies auszuschließen, da diePATH
Umgebungsvariable auch WINDOWS enthält .quelle
uname
einem normalen Cmd-Terminal habe, erhalte ich MINGW. Was ich meine ist, ich habe immer nochuname
ohne Cygwin. Ich habe auch Git Bash, aber ich habe nicht versucht, Uname darauf zu machen (im Moment bin ich in Linux). Können Sie mir sagen, wie diese beiden in Ihren Code aufgenommen werden können?uname
nicht ausgeführt werden kann, würden wir verstehen, dass wir uns in Windows befinden?Das ist der Job, den GNUs Automake / Autoconf macht lösen soll. Vielleicht möchten Sie sie untersuchen.
Alternativ können Sie Umgebungsvariablen auf Ihren verschiedenen Plattformen festlegen und Makefile davon abhängig machen.
quelle
make
was ich will. Möchte ich jetzt auch in automake / autoconf einsteigen? - NEIN. Was im Makefile getan werden kann , sollte auf jeden Fall im Makefile getan werden, schon allein deshalb, damit ich nicht jedes Mal mehrere Zwischenstopps habe, wenn ich compile & link ändern möchte.Ich habe endlich die perfekte Lösung gefunden, die dieses Problem für mich löst.
Die UNAME-Variable ist auf Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (oder vermutlich Solaris, Darwin, OpenBSD, AIX, HP-UX) oder Unbekannt eingestellt. Es kann dann im Rest des Makefiles verglichen werden, um alle betriebssystemsensitiven Variablen und Befehle zu trennen.
Der Schlüssel ist, dass Windows Semikolons verwendet, um Pfade in der PATH-Variablen zu trennen, während alle anderen Doppelpunkte verwenden. (Es ist möglich, ein Linux-Verzeichnis mit einem ';' im Namen zu erstellen und es PATH hinzuzufügen, was dies beschädigen würde, aber wer würde so etwas tun?) Dies scheint die am wenigsten riskante Methode zu sein, um natives Windows zu erkennen, weil es benötigt keinen Shell-Aufruf. Cygwin und MSYS PATH verwenden Doppelpunkte, die so uname sind für sie aufgerufen wird.
Beachten Sie, dass die Umgebungsvariable des Betriebssystems zum Erkennen von Windows verwendet werden kann, jedoch nicht zum Unterscheiden zwischen Cygwin und nativem Windows. Das Testen auf das Echo von Anführungszeichen funktioniert, erfordert jedoch einen Shell-Aufruf.
Leider fügt Cygwin der Ausgabe von uname einige Versionsinformationen hinzu, daher habe ich die Aufrufe 'patsubst' hinzugefügt, um sie in 'Cygwin' zu ändern. Außerdem hat uname für MSYS tatsächlich drei mögliche Ausgaben, beginnend mit MSYS oder MINGW, aber ich verwende auch patsubst, um alle nur in 'MSYS' umzuwandeln.
Wenn es wichtig ist, zwischen nativen Windows-Systemen mit und ohne uname.exe im Pfad zu unterscheiden, kann diese Zeile anstelle der einfachen Zuweisung verwendet werden:
Natürlich ist in allen Fällen GNU make erforderlich oder ein anderes make, das die verwendeten Funktionen unterstützt.
quelle
Ich bin heute auf dieses Problem gestoßen und brauchte es unter Solaris. Hier ist eine POSIX-Standardmethode, um dies zu tun (etwas sehr Nahes).
quelle
Hier ist eine einfache Lösung, die überprüft, ob Sie sich in einer Windows- oder posix-ähnlichen Umgebung (Linux / Unix / Cygwin / Mac) befinden:
Es nutzt die Tatsache, dass Echo sowohl in posix-ähnlichen als auch in Windows-Umgebungen vorhanden ist und dass die Shell in Windows die Anführungszeichen nicht filtert.
quelle
$PATH
möglicherweise um einen anderen handeltecho
(-mwindows
Flag setzen oder zwischen einem.dll
oder.so
wählen möchte, schlägt dies fehl.Beachten Sie, dass Makefiles sehr empfindlich auf Abstände reagieren. Hier ist ein Beispiel für ein Makefile, das unter OS X einen zusätzlichen Befehl ausführt und unter OS X und Linux funktioniert. Insgesamt ist autoconf / automake jedoch der richtige Weg, um alles zu erreichen, was nicht trivial ist.
quelle
Eine andere Möglichkeit, dies zu tun, ist die Verwendung eines "configure" -Skripts. Wenn Sie bereits eine mit Ihrem Makefile verwenden, können Sie eine Kombination aus uname und sed verwenden, um die Dinge zum Laufen zu bringen. Führen Sie in Ihrem Skript zunächst Folgendes aus:
Um dies in Ihr Makefile aufzunehmen, beginnen Sie mit Makefile.in, das so etwas wie haben sollte
drin.
Verwenden Sie nach dem
UNAME=uname
Bit den folgenden Befehl sed in Ihrem Konfigurationsskript .Jetzt sollte Ihr Makefile
UNAME
wie gewünscht definiert sein. Wenn / elif / else-Anweisungen alles sind, was übrig bleibt!quelle
Ich hatte einen Fall, in dem ich den Unterschied zwischen zwei Fedora-Versionen feststellen musste, um die Befehlszeilenoptionen für inkscape zu optimieren:
- In Fedora 31 ist die Standard-Inkscape 1.0beta, die verwendet wird
--export-file
- in Fedora <31 ist die Standard-Inkscape 0,92 die verwendet
--export-pdf
Mein Makefile enthält Folgendes
Dies funktioniert, weil es
/etc/os-release
eine Zeile enthältDer Shell-Befehl im Makefile gibt also die Zeichenfolge zurück
VERSION_ID=<value>
, und der Befehl eval wirkt darauf, um die Makefile-Variable festzulegenVERSION_ID
. Dies kann natürlich für andere Betriebssysteme angepasst werden, je nachdem, wie die Metadaten gespeichert sind. Beachten Sie, dass es in Fedora keine Standardumgebungsvariable gibt, die die Betriebssystemversion angibt, sonst hätte ich das verwendet!quelle