Saya secara rutin bekerja pada beberapa komputer yang berbeda dan beberapa sistem operasi yang berbeda, yaitu Mac OS X, Linux, atau Solaris. Untuk proyek yang sedang saya kerjakan, saya menarik kode saya dari repositori git jarak jauh.
Saya ingin dapat mengerjakan proyek saya terlepas dari terminal mana saya berada. Sejauh ini, saya telah menemukan cara untuk mengatasi perubahan OS dengan mengubah makefile setiap kali saya mengganti komputer. Namun, ini membosankan dan menyebabkan banyak sakit kepala.
Bagaimana saya bisa memodifikasi makefile saya sehingga mendeteksi OS yang saya gunakan dan memodifikasi sintaksis yang sesuai?
Inilah 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 tampaknya tervirtualisasi tergantung pada apakah prosesnya 32-bit atau 64-bit. Jadi, jika Andamake
32-bit dan Anda mencoba membangun aplikasi 64-bit, itu akan gagal. Menggunakannya dalam kombinasi denganPROCESSOR_ARCHITEW6432
bekerja untuk saya (lihat ini , dan itu )make
tim menambahkan beberapa variabel ajaib dengan os dan lengkungan, mungkin terlalu banyak kesulitan.OS
diatur pada sistem non-Windows. Buat suguhan tidak disetel sama dengan kosong, yang akan menyebabkan lompatan keuname
blok berbasis. Anda hanya perlu menambahkan cek FreeBSD di sana./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: line 0:ifeq (,Windows_NT)' make: *** [os] Error 2
Perintah uname ( http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html ) tanpa parameter akan memberi tahu Anda nama sistem operasi. Saya akan menggunakannya, kemudian membuat persyaratan berdasarkan nilai pengembalian.
Contoh
sumber
Deteksi sistem operasi menggunakan dua trik sederhana:
OS
uname
perintahnyaAtau cara yang lebih aman, jika tidak pada Windows dan
uname
tidak tersedia:Ken Jackson mengusulkan alternatif yang menarik jika Anda ingin membedakan Cygwin / MinGW / MSYS / Windows. Lihat jawabannya yang terlihat seperti itu:
Kemudian Anda dapat memilih hal-hal yang relevan tergantung pada
detected_OS
:Catatan:
Perintah
uname
sama denganuname -s
karena opsi-s
(--kernel-name
) adalah default. Lihat mengapauname -s
lebih baik daripadauname -o
.Penggunaan
OS
(bukanuname
) menyederhanakan algoritma identifikasi. Anda masih dapat menggunakan semata-matauname
, tetapi Anda harus berurusan denganif/else
blok untuk memeriksa semua variasi MinGW, Cygwin, dll.Variabel lingkungan
OS
selalu disetel"Windows_NT"
pada versi Windows yang berbeda (lihat%OS%
variabel lingkungan di Wikipedia ).Alternatif
OS
adalah variabel lingkunganMSVC
(memeriksa keberadaan MS Visual Studio , lihat contoh menggunakan Visual C ++ ).Di bawah ini saya memberikan contoh lengkap menggunakan
make
dangcc
membangun perpustakaan bersama:*.so
atau*.dll
tergantung pada platform. Contohnya sesederhana mungkin untuk lebih dimengerti.Untuk menginstal
make
dangcc
pada Windows, lihat Cygwin atau MinGW .Contoh saya didasarkan pada lima file
Pengingat:
Makefile
indentasi menggunakan tabulasi . Perhatian saat menyalin-menempel di bawah file sampel.Kedua
Makefile
file tersebut1.
lib/Makefile
2.
app/Makefile
Untuk mempelajari lebih lanjut, baca dokumentasi Variabel Otomatis seperti yang ditunjukkan oleh cfi .
Kode sumber
-
lib/hello.h
-
lib/hello.c
-
app/main.c
Membangun
Perbaiki salin-tempel
Makefile
(ganti spasi terdepan dengan satu tabulasi).The
make
perintah yang sama pada kedua platform. Output yang diberikan adalah pada OS mirip Unix:Lari
Aplikasi ini perlu tahu di mana perpustakaan bersama.
Di Windows, solusi sederhana adalah menyalin pustaka tempat aplikasi tersebut:
Pada OS yang mirip Unix, Anda dapat menggunakan
LD_LIBRARY_PATH
variabel lingkungan:Jalankan perintah pada Windows:
Jalankan perintah pada OS yang mirip Unix:
sumber
uname
bukan Linux. Saya memberikan contoh yang mungkin tidak Anda butuhkan, tetapi ini dapat membantu seseorang mencari (di web) cara untuk menerapkanMakefile
untuk kedua platform ;-) Apa yang harus saya ubah dalam jawaban saya? Cheerslib/Makefile
contoh,target
digunakan untuk.so
vs.dll
. Contoh paralel untukapp/makefile
akan berguna untuk perbandinganempty string
vs.exe
untuk nama file aplikasi. Sebagai contoh, saya biasanya tidak melihatapp.exe
OS seperti Unix. ;-)Saya baru-baru ini bereksperimen untuk menjawab pertanyaan ini, saya bertanya pada diri sendiri. Inilah kesimpulan saya:
Karena di Windows, Anda tidak dapat memastikan bahwa
uname
perintah itu tersedia, Anda dapat menggunakannyagcc -dumpmachine
. Ini akan menampilkan target kompiler.Mungkin juga ada masalah ketika menggunakan
uname
jika Anda ingin melakukan kompilasi silang.Berikut adalah contoh daftar kemungkinan keluaran
gcc -dumpmachine
:Anda dapat memeriksa hasilnya di makefile seperti ini:
Ini bekerja dengan baik untuk saya, tetapi saya tidak yakin itu cara yang dapat diandalkan untuk mendapatkan tipe sistem. Setidaknya itu dapat diandalkan tentang MinGW dan itu saja yang saya butuhkan karena tidak perlu memiliki
uname
perintah atau paket MSYS di Windows.Singkatnya,
uname
memberikan Anda sistem di mana Anda kompilasi, dangcc -dumpmachine
memberikan Anda sistem untuk yang Anda kompilasi.sumber
uname
ikutMinGW
? Namun demikian, catatan tambahan tentang kompilasi silang sangat bagus.$(shell $(CC) -dumpmachine)
. Pada OS X Sierra, perintah -dumpmachine bekerja pada Dentang.x86_64-apple-darwin16.6.0
dan bahwa karya cuaca Anda menyebutnyagcc
,cc
atauclang
, tetapi tidakcl
The git makefile berisi banyak contoh bagaimana mengelola tanpa autoconf / automake, namun masih bekerja pada banyak platform unixy.
sumber
if (!usesAutotools(git)) aversionTo(autotools) = justified;
Saya akan mengklarifikasi juga bahwa hanya alat yang saya benci. Saya yakin orang Autotools adalah orang baik.Pembaruan: Saya sekarang menganggap jawaban ini sudah usang. Saya memposting solusi sempurna baru lebih jauh ke bawah.
Jika makefile Anda dapat berjalan di Windows non-Cygwin,
uname
mungkin tidak tersedia. Itu aneh, tapi ini solusi potensial. Anda harus memeriksa Cygwin terlebih dahulu untuk mengesampingkannya, karena memiliki WINDOWS dalamPATH
variabel lingkungannya juga.sumber
uname
dari terminal cmd normal itu memberi saya MINGW. Maksud saya adalah, saya masih punyauname
tanpa menggunakan Cygwin. Saya juga punya git bash, tapi saya belum mencoba yang belum terkenal (sekarang saya di Linux). Bisakah Anda memberi tahu saya bagaimana keduanya dapat dimasukkan ke dalam kode Anda?uname
tidak dapat dijalankan kita akan mengerti kita berada di Windows?Itulah pekerjaan yang dirancang untuk diselesaikan oleh automake / autoconf GNU . Anda mungkin ingin menyelidikinya.
Atau Anda dapat mengatur variabel lingkungan pada platform yang berbeda dan membuat Makefile bersyarat terhadapnya.
sumber
make
untuk melakukan apa yang saya inginkan. Apakah saya sekarang ingin masuk ke automake / autoconf juga? - TIDAK. Apa yang bisa dilakukan di makefile, tentu harus dilakukan di makefile, kalau saja supaya saya tidak memiliki beberapa poin perhentian setiap kali saya ingin mengubah kompilasi & tautan.Saya akhirnya menemukan solusi sempurna yang menyelesaikan masalah ini untuk saya.
Variabel UNAME diatur ke Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (atau mungkin Solaris, Darwin, OpenBSD, AIX, HP-UX), atau Tidak Diketahui. Itu kemudian dapat dibandingkan sepanjang sisa Makefile untuk memisahkan variabel dan perintah OS-sensitif.
Kuncinya adalah bahwa Windows menggunakan titik koma untuk memisahkan jalur dalam variabel PATH sedangkan orang lain menggunakan titik dua. (Dimungkinkan untuk membuat direktori Linux dengan tanda ';' di namanya dan menambahkannya ke PATH, yang akan memecahkan ini, tetapi siapa yang akan melakukan hal seperti itu?) Ini tampaknya menjadi metode yang paling tidak berisiko untuk mendeteksi Windows asli karena itu tidak perlu panggilan shell. The Cygwin dan MSYS PATH menggunakan titik dua begitu uname disebut bagi mereka.
Perhatikan bahwa variabel lingkungan OS dapat digunakan untuk mendeteksi Windows, tetapi tidak untuk membedakan antara Cygwin dan Windows asli. Pengujian untuk gema kutipan berhasil, tetapi membutuhkan panggilan shell.
Sayangnya, Cygwin menambahkan beberapa informasi versi ke output uname , jadi saya menambahkan panggilan 'patsubst' untuk mengubahnya hanya 'Cygwin'. Juga, uname untuk MSYS sebenarnya memiliki tiga kemungkinan keluaran dimulai dengan MSYS atau MINGW, tetapi saya juga menggunakan patsubst untuk mengubah semua menjadi hanya 'MSYS'.
Jika penting untuk membedakan antara sistem Windows asli dengan dan tanpa beberapa uname.exe di jalur, baris ini dapat digunakan sebagai pengganti penugasan sederhana:
Tentu saja dalam semua kasus GNU make diperlukan, atau make lain yang mendukung fungsi yang digunakan.
sumber
Saya mengalami masalah ini hari ini dan saya membutuhkannya di Solaris jadi di sini ada cara standar POSIX untuk melakukan (sesuatu yang sangat dekat dengan) ini.
sumber
Berikut adalah solusi sederhana yang memeriksa apakah Anda berada di lingkungan Windows atau posix-like (Linux / Unix / Cygwin / Mac):
Ini mengambil keuntungan dari kenyataan bahwa gema ada di kedua lingkungan seperti posix dan Windows, dan di Windows shell tidak menyaring tanda kutip.
sumber
$PATH
mungkin merujuk ke yang lainecho
(-mwindows
bendera atau memilih antara.dll
atau.so
, ini akan gagal.Perhatikan bahwa Makefiles sangat sensitif terhadap spasi. Berikut adalah contoh Makefile yang menjalankan perintah tambahan pada OS X dan yang berfungsi pada OS X dan Linux. Namun secara keseluruhan, autoconf / automake adalah cara untuk melakukan apa saja yang tidak sepele.
sumber
Cara lain untuk melakukan ini adalah dengan menggunakan skrip "configure". Jika Anda sudah menggunakan satu dengan makefile Anda, Anda bisa menggunakan kombinasi uname dan sed untuk menyelesaikannya. Pertama, dalam skrip Anda, lakukan:
Kemudian, untuk memasukkan ini ke dalam Makefile Anda, mulailah dengan Makefile.in yang seharusnya memiliki sesuatu seperti
di dalamnya.
Gunakan perintah sed berikut di skrip configure Anda setelah
UNAME=uname
bit.Sekarang makefile Anda harus
UNAME
didefinisikan sesuai keinginan. Jika hanya pernyataan / elif / else yang tersisa!sumber
Saya punya kasus di mana saya harus mendeteksi perbedaan antara dua versi Fedora, untuk mengubah opsi baris perintah untuk inkscape:
- di Fedora 31, inkscape default adalah 1.0beta yang menggunakan
--export-file
- di Fedora <31, inkscape default adalah 0,92 yang digunakan
--export-pdf
Makefile saya berisi yang berikut ini
Ini berfungsi karena
/etc/os-release
mengandung garisjadi perintah shell di Makefile mengembalikan string
VERSION_ID=<value>
, maka perintah eval bertindak atas ini untuk mengatur variabel MakefileVERSION_ID
. Ini jelas dapat diubah untuk OS lain tergantung bagaimana metadata disimpan. Perhatikan bahwa di Fedora tidak ada variabel lingkungan default yang memberikan versi OS, kalau tidak saya akan menggunakannya!sumber