Rutynowo pracuję na kilku różnych komputerach i kilku różnych systemach operacyjnych, którymi są Mac OS X, Linux lub Solaris. W przypadku projektu, nad którym pracuję, pobieram kod ze zdalnego repozytorium git.
Lubię pracować nad moimi projektami, niezależnie od tego, w którym terminalu jestem. Do tej pory znalazłem sposoby obejścia zmian w systemie operacyjnym, zmieniając plik makefile przy każdej zmianie komputera. Jest to jednak uciążliwe i powoduje wiele bólów głowy.
Jak mogę zmodyfikować mój plik makefile, aby wykrywał używany system operacyjny i odpowiednio modyfikował składnię?
Oto plik 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 wydaje się zwirtualizowane w zależności od tego, czy proces jest 32-bitowy czy 64-bitowy. Jeśli więc maszmake
wersję 32-bitową i próbujesz zbudować aplikację 64-bitową, zakończy się ona niepowodzeniem. Używanie go w połączeniu zPROCESSOR_ARCHITEW6432
działało dla mnie (patrz to i tamto )make
zespół dodał kilka magicznych zmiennych z os i arch, prawdopodobnie zbyt duży problem.OS
jest ustawiony w systemach innych niż Windows. Spraw, aby przysmaki były takie same jak puste, co spowoduje przeskok douname
bloku opartego na podstawie. Wystarczy dodać tam kontrolę FreeBSD./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: line 0:ifeq (,Windows_NT)' make: *** [os] Error 2
Polecenie uname ( http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html ) bez parametrów powinno podać nazwę systemu operacyjnego. Użyłbym tego, a następnie stworzyłem warunki warunkowe na podstawie wartości zwracanej.
Przykład
źródło
Wykryj system operacyjny za pomocą dwóch prostych sztuczek:
OS
uname
polecenieLub bezpieczniejszy sposób, jeśli nie w systemie Windows i
uname
niedostępny:Ken Jackson proponuje interesującą alternatywę, jeśli chcesz rozróżnić Cygwin / MinGW / MSYS / Windows. Zobacz jego odpowiedź, która wygląda tak:
Następnie możesz wybrać odpowiednie rzeczy w zależności od
detected_OS
:Uwagi:
Polecenie
uname
jest takie samo,uname -s
ponieważ opcja-s
(--kernel-name
) jest domyślna. Zobacz, dlaczegouname -s
jest lepszy niżuname -o
.Zastosowanie
OS
(zamiastuname
) upraszcza algorytm identyfikacji. Nadal możesz używać wyłącznieuname
, ale musisz radzić sobie zif/else
blokami, aby sprawdzić wszystkie odmiany MinGW, Cygwin itp.Zmienna środowiskowa
OS
jest zawsze ustawiona"Windows_NT"
na różne wersje systemu Windows (patrz%OS%
zmienna środowiskowa na Wikipedii ).Alternatywą
OS
jest zmienna środowiskowaMSVC
(sprawdza obecność MS Visual Studio , patrz przykład przy użyciu Visual C ++ ).Poniżej podaję pełny przykład użycia
make
igcc
budowy wspólnej biblioteki:*.so
lub w*.dll
zależności od platformy. Przykład jest możliwie najprostszy, aby był bardziej zrozumiały.Aby zainstalować
make
igcc
na Windowsie zobacz Cygwin lub MinGW .Mój przykład opiera się na pięciu plikach
Przypomnienie:
Makefile
jest wcięte przy użyciu tabulacji . Uwaga podczas wklejania kopii poniżej przykładowych plików.Dwa
Makefile
pliki1.
lib/Makefile
2)
app/Makefile
Aby dowiedzieć się więcej, przeczytaj dokumentację zmiennych automatycznych wskazaną przez cfi .
Kod źródłowy
-
lib/hello.h
-
lib/hello.c
-
app/main.c
Kompilacja
Napraw kopiuj-wklej
Makefile
(zamień wiodące spacje na jedną tabelę).make
Komenda jest taka sama na obu platformach. Podane dane wyjściowe dotyczą systemów uniksopodobnych:Bieg
Aplikacja musi wiedzieć, gdzie jest biblioteka współdzielona.
W systemie Windows prostym rozwiązaniem jest skopiowanie biblioteki, w której znajduje się aplikacja:
W systemach uniksopodobnych możesz użyć
LD_LIBRARY_PATH
zmiennej środowiskowej:Uruchom polecenie w systemie Windows:
Uruchom polecenie w systemach operacyjnych uniksopodobnych:
źródło
uname
nie jest to Linux. Podam tylko przykład, którego możesz nie potrzebować, ale może to pomóc komuś, kto szuka (w Internecie) sposobu na wdrożenieMakefile
obu platform ;-) Co powinienem zmienić w swojej odpowiedzi? Na zdrowielib/Makefile
przykład,target
stosuje się do.so
vs.dll
. Równoległy Przykładem tegoapp/makefile
byłoby użyteczne dlaempty string
vs.exe
stosunku do aplikacji pliku. Na przykład zwykle nie widzęapp.exe
w systemach operacyjnych typu Unix. ;-)Niedawno eksperymentowałem, aby odpowiedzieć na to pytanie, które sobie zadawałem. Oto moje wnioski:
Ponieważ w systemie Windows nie możesz być pewien, że
uname
polecenie jest dostępne, możesz użyćgcc -dumpmachine
. Spowoduje to wyświetlenie celu kompilatora.Może być również problem z używaniem,
uname
jeśli chcesz wykonać kompilację krzyżową.Oto przykładowa lista możliwych wyników
gcc -dumpmachine
:Możesz sprawdzić wynik w pliku makefile w następujący sposób:
Działa to dla mnie dobrze, ale nie jestem pewien, czy jest to niezawodny sposób na uzyskanie typu systemu. Przynajmniej jest niezawodny w MinGW i to wszystko, czego potrzebuję, ponieważ nie wymaga posiadania
uname
polecenia lub pakietu MSYS w systemie Windows.Podsumowując,
uname
daje ci system, na którym kompilujesz, igcc -dumpmachine
system, na którym kompilujesz.źródło
uname
pochodziMinGW
? Niemniej jednak dodatkowa uwaga dotycząca kompilacji krzyżowej jest świetna.$(shell $(CC) -dumpmachine)
. W systemie OS X Sierra polecenie -dumpmachine działa w systemie Clang.x86_64-apple-darwin16.6.0
i działa, niezależnie od tegogcc
, jak go nazwieszcc
, czy teżclang
- ale niecl
Plik makit git zawiera wiele przykładów zarządzania bez autoconf / automake, ale wciąż działa na wielu platformach unixy.
źródło
if (!usesAutotools(git)) aversionTo(autotools) = justified;
wyjaśnię też, że to tylko narzędzia, którym jestem niechętny. Jestem pewien, że ludzie z Autotools to mili ludzie.Aktualizacja: Teraz uważam tę odpowiedź za nieaktualną. W dalszej części opublikowałem nowe idealne rozwiązanie.
Jeśli plik makefile może działać w systemie Windows innym niż Cygwin,
uname
może nie być dostępny. To niezręczne, ale jest to potencjalne rozwiązanie. Musisz najpierw sprawdzić, czy Cygwin go wyklucza, ponieważ ma on takżePATH
zmienną środowiskową WINDOWS .źródło
uname
z normalnego terminala cmd, daje mi MINGW. Chodzi mi o to, że nadal mamuname
bez korzystania z Cygwin. Mam też git bash, ale nie próbowałem na nim odmówić (teraz jestem w Linuksie). Czy możesz mi powiedzieć, jak te dwa elementy mogą zostać włączone do twojego kodu?uname
nie można go uruchomić, zrozumielibyśmy, że jesteśmy w systemie Windows?Takie zadanie automake / autoconf GNU ma rozwiązać. Możesz je zbadać.
Alternatywnie możesz ustawić zmienne środowiskowe na różnych platformach i uzależnić Makefile od nich.
źródło
make
robić to, co chcę. Czy teraz chcę również przejść do automake / autoconf? - NIE Co można zrobić w pliku makefile, z pewnością należy to zrobić w pliku makefile, choćby po to, aby nie miałem kilku punktów zatrzymania za każdym razem, gdy chcę zmienić kompilację i link.W końcu znalazłem idealne rozwiązanie, które rozwiązuje ten problem dla mnie.
Zmienna UNAME jest ustawiona na Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (lub prawdopodobnie Solaris, Darwin, OpenBSD, AIX, HP-UX) lub Nieznany. Następnie można go porównać w pozostałej części pliku Makefile, aby oddzielić zmienne i polecenia wrażliwe na system operacyjny.
Kluczem jest to, że system Windows używa średników do oddzielania ścieżek w zmiennej PATH, podczas gdy wszyscy inni używają dwukropków. (Możliwe jest utworzenie katalogu Linux z nazwą „;” i dodanie go do PATH, co by to zepsuło, ale kto by zrobiłby coś takiego?) Wydaje się, że jest to najmniej ryzykowna metoda wykrywania rodzimego systemu Windows, ponieważ nie potrzebuje wywołania powłoki. Ścieżka Cygwin i MSYS PATH używają dwukropków, dlatego wymaga się od nich nazwy uname .
Zauważ, że zmienna środowiskowa systemu operacyjnego może być używana do wykrywania systemu Windows, ale nie do rozróżniania między Cygwin a rodzimym systemem Windows. Testowanie echa cytatów działa, ale wymaga wywołania powłoki.
Niestety, Cygwin dodaje informacje wyjściowe do uname , więc dodałem wywołania „patsubst”, aby zmienić je na „Cygwin”. Ponadto, uname dla MSYS faktycznie ma trzy możliwe wyjścia, zaczynając od MSYS lub MINGW, ale używam również patsubst, aby przekształcić wszystko w tylko „MSYS”.
Jeśli ważne jest rozróżnienie między rodzimymi systemami Windows z i bez pliku uname.exe na ścieżce, można użyć tej linii zamiast prostego przypisania:
Oczywiście we wszystkich przypadkach wymagana jest marka GNU lub inna marka, która obsługuje używane funkcje.
źródło
Zetknąłem się dzisiaj z tym problemem i potrzebowałem go w systemie Solaris, więc oto standardowy sposób na to, aby to zrobić (coś bardzo zbliżonego) do POSIX.
źródło
Oto proste rozwiązanie, które sprawdza, czy jesteś w środowisku Windows lub posixowym (Linux / Unix / Cygwin / Mac):
Wykorzystuje fakt, że echo istnieje zarówno w środowisku podobnym do POSIX-a, jak i Windows, oraz że w Windows powłoka nie filtruje cudzysłowów.
źródło
$PATH
może odnosić się do innegoecho
(mój robi ...)-mwindows
flagę lub wybrać pomiędzy.dll
lub.so
byłoby to niepowodzeniem.Zauważ, że Makefile są wyjątkowo wrażliwe na odstępy. Oto przykład pliku Makefile, który uruchamia dodatkowe polecenie w OS X i działa w OS X i Linux. Ogólnie rzecz biorąc, autoconf / automake to sposób na wszystko, co nie jest trywialne.
źródło
Innym sposobem na to jest użycie skryptu „config”. Jeśli korzystasz już z pliku makefile, możesz użyć kombinacji uname i sed, aby wszystko działało. Najpierw w swoim skrypcie wykonaj:
Następnie, aby umieścić to w swoim Makefile, zacznij od Makefile.in, który powinien mieć coś takiego
w tym.
Użyj następującego polecenia sed w skrypcie konfiguracyjnym po
UNAME=uname
bicie.Teraz twój plik makefile powinien był zostać
UNAME
zdefiniowany zgodnie z potrzebami. Jeśli pozostały tylko instrukcje / elif / else!źródło
Miałem przypadek, w którym musiałem wykryć różnicę między dwiema wersjami Fedory, aby dostosować opcje wiersza polecenia dla inkscape:
- w Fedorze 31 domyślnym inkscape jest 1.0beta, który używa
--export-file
- w Fedorze <31 domyślnym inkscape jest 0,92, który wykorzystuje
--export-pdf
Mój plik Makefile zawiera następujące elementy
Działa to, ponieważ
/etc/os-release
zawiera linięwięc polecenie powłoki w pliku Makefile zwraca ciąg znaków
VERSION_ID=<value>
, a następnie polecenie eval działa na to, aby ustawić zmienną MakefileVERSION_ID
. Można to oczywiście poprawić w innych systemach operacyjnych, w zależności od sposobu przechowywania metadanych. Zauważ, że w Fedorze nie ma domyślnej zmiennej środowiskowej, która podaje wersję systemu operacyjnego, w przeciwnym razie użyłbym tego!źródło