İşletim sistemini iki basit numara kullanarak tespit edin:
- İlk olarak çevre değişkeni
OS
- Sonra
uname
komut
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
detected_OS := Windows
else
detected_OS := $(shell uname) # same as "uname -s"
endif
Veya Windows'da uname
yoksa ve kullanılamıyorsa daha güvenli bir yol :
ifeq ($(OS),Windows_NT)
detected_OS := Windows
else
detected_OS := $(shell sh -c 'uname 2>/dev/null || echo Unknown')
endif
Cygwin / MinGW / MSYS / Windows'ı ayırt etmek istiyorsanız Ken Jackson ilginç bir alternatif öneriyor. Şuna benzeyen cevabını görün :
ifeq '$(findstring ;,$(PATH))' ';'
detected_OS := Windows
else
detected_OS := $(shell uname 2>/dev/null || echo Unknown)
detected_OS := $(patsubst CYGWIN%,Cygwin,$(detected_OS))
detected_OS := $(patsubst MSYS%,MSYS,$(detected_OS))
detected_OS := $(patsubst MINGW%,MSYS,$(detected_OS))
endif
Ardından aşağıdakilere bağlı olarak ilgili şeyleri seçebilirsiniz detected_OS
:
ifeq ($(detected_OS),Windows)
CFLAGS += -D WIN32
endif
ifeq ($(detected_OS),Darwin) # Mac OS X
CFLAGS += -D OSX
endif
ifeq ($(detected_OS),Linux)
CFLAGS += -D LINUX
endif
ifeq ($(detected_OS),GNU) # Debian GNU Hurd
CFLAGS += -D GNU_HURD
endif
ifeq ($(detected_OS),GNU/kFreeBSD) # Debian kFreeBSD
CFLAGS += -D GNU_kFreeBSD
endif
ifeq ($(detected_OS),FreeBSD)
CFLAGS += -D FreeBSD
endif
ifeq ($(detected_OS),NetBSD)
CFLAGS += -D NetBSD
endif
ifeq ($(detected_OS),DragonFly)
CFLAGS += -D DragonFly
endif
ifeq ($(detected_OS),Haiku)
CFLAGS += -D Haiku
endif
Notlar:
Komut uname
aynıdır, uname -s
çünkü option -s
( --kernel-name
) varsayılan değerdir. Neden uname -s
daha iyi olduğunuuname -o
görün .
Kullanımı OS
(yerine uname
) tanıma algoritması kolaylaştırır. Yine de yalnızca kullanabilirsiniz uname
, ancak if/else
tüm MinGW, Cygwin vb. Varyasyonlarını kontrol etmek için bloklarla uğraşmanız gerekir.
Ortam değişkeni OS
her zaman "Windows_NT"
farklı Windows sürümlerinde olarak ayarlanır ( %OS%
Wikipedia'daki ortam değişkenine bakın ).
Alternatifi OS
ortam değişkenidir MSVC
( MS Visual Studio'nun varlığını kontrol eder, Visual C ++ kullanarak örneğe bakın ).
Aşağıda make
ve kullanarak gcc
paylaşılan bir kütüphane oluşturmak için *.so
veya *.dll
platforma bağlı olarak tam bir örnek sunuyorum . Örnek, daha anlaşılır olması için mümkün olduğunca basittir.
Windows'a kurmak make
ve yüklemek için gcc
bkz. Cygwin veya MinGW .
Örneğim beş dosyaya dayanıyor
├── lib
│ └── Makefile
│ └── hello.h
│ └── hello.c
└── app
└── Makefile
└── main.c
Hatırlatma: tabloMakefile
kullanılarak girintilenir . Örnek dosyaların altına kopya yapıştırırken dikkat edin.
İki Makefile
dosya
1. lib/Makefile
ifeq ($(OS),Windows_NT)
uname_S := Windows
else
uname_S := $(shell uname -s)
endif
ifeq ($(uname_S), Windows)
target = hello.dll
endif
ifeq ($(uname_S), Linux)
target = libhello.so
endif
#ifeq ($(uname_S), .....) #See https://stackoverflow.com/a/27776822/938111
# target = .....
#endif
%.o: %.c
gcc -c $< -fPIC -o $@
# -c $< => $< is first file after ':' => Compile hello.c
# -fPIC => Position-Independent Code (required for shared lib)
# -o $@ => $@ is the target => Output file (-o) is hello.o
$(target): hello.o
gcc $^ -shared -o $@
# $^ => $^ expand to all prerequisites (after ':') => hello.o
# -shared => Generate shared library
# -o $@ => Output file (-o) is $@ (libhello.so or hello.dll)
2. app/Makefile
ifeq ($(OS),Windows_NT)
uname_S := Windows
else
uname_S := $(shell uname -s)
endif
ifeq ($(uname_S), Windows)
target = app.exe
endif
ifeq ($(uname_S), Linux)
target = app
endif
#ifeq ($(uname_S), .....) #See https://stackoverflow.com/a/27776822/938111
# target = .....
#endif
%.o: %.c
gcc -c $< -I ../lib -o $@
# -c $< => compile (-c) $< (first file after :) = main.c
# -I ../lib => search headers (*.h) in directory ../lib
# -o $@ => output file (-o) is $@ (target) = main.o
$(target): main.o
gcc $^ -L../lib -lhello -o $@
# $^ => $^ (all files after the :) = main.o (here only one file)
# -L../lib => look for libraries in directory ../lib
# -lhello => use shared library hello (libhello.so or hello.dll)
# -o $@ => output file (-o) is $@ (target) = "app.exe" or "app"
Daha fazla bilgi edinmek için cfi tarafından belirtilen Otomatik Değişkenler belgelerini okuyun .
Kaynak kodu
- lib/hello.h
#ifndef HELLO_H_
#define HELLO_H_
const char* hello();
#endif
- lib/hello.c
#include "hello.h"
const char* hello()
{
return "hello";
}
- app/main.c
#include "hello.h" //hello()
#include <stdio.h> //puts()
int main()
{
const char* str = hello();
puts(str);
}
Yapı
Kopyasını yapıştırın Makefile
(önde gelen boşlukları bir tablo ile değiştirin).
> sed 's/^ */\t/' -i */Makefile
make
Komut her iki platformda da aynıdır. Verilen çıktı Unix benzeri işletim sistemlerinde:
> make -C lib
make: Entering directory '/tmp/lib'
gcc -c hello.c -fPIC -o hello.o
# -c hello.c => hello.c is first file after ':' => Compile hello.c
# -fPIC => Position-Independent Code (required for shared lib)
# -o hello.o => hello.o is the target => Output file (-o) is hello.o
gcc hello.o -shared -o libhello.so
# hello.o => hello.o is the first after ':' => Link hello.o
# -shared => Generate shared library
# -o libhello.so => Output file (-o) is libhello.so (libhello.so or hello.dll)
make: Leaving directory '/tmp/lib'
> make -C app
make: Entering directory '/tmp/app'
gcc -c main.c -I ../lib -o main.o
# -c main.c => compile (-c) main.c (first file after :) = main.cpp
# -I ../lib => search headers (*.h) in directory ../lib
# -o main.o => output file (-o) is main.o (target) = main.o
gcc main.o -L../lib -lhello -o app
# main.o => main.o (all files after the :) = main.o (here only one file)
# -L../lib => look for libraries in directory ../lib
# -lhello => use shared library hello (libhello.so or hello.dll)
# -o app => output file (-o) is app.exe (target) = "app.exe" or "app"
make: Leaving directory '/tmp/app'
Koşmak
Uygulama, paylaşılan kitaplığın nerede olduğunu bilmeyi gerektirir.
Windows'ta basit bir çözüm, uygulamanın bulunduğu kütüphaneyi kopyalamaktır:
> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'
Unix benzeri işletim sistemlerinde, LD_LIBRARY_PATH
ortam değişkenini kullanabilirsiniz :
> export LD_LIBRARY_PATH=lib
Komutu Windows'ta çalıştırın:
> app/app.exe
hello
Komutu Unix benzeri işletim sistemlerinde çalıştırın:
> app/app
hello
PROCESSOR_ARCHITECTURE
envvar, işlemin 32 bit mi yoksa 64 bit mi olduğuna bağlı olarak sanallaştırılmış gibi görünüyor. Eğermake
32 bit ise ve 64 bit bir uygulama oluşturmaya çalışıyorsanız başarısız olur. İle birlikte onu kullanmaPROCESSOR_ARCHITEW6432
(bkz benim için çalıştı bu ve o )