두 가지 간단한 트릭을 사용하여 운영 체제를 감지하십시오.
- 먼저 환경 변수
OS
- 그런 다음
uname
명령
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
또는 Windows에없고 uname
사용할 수없는 경우 더 안전한 방법 :
ifeq ($(OS),Windows_NT)
detected_OS := Windows
else
detected_OS := $(shell sh -c 'uname 2>/dev/null || echo Unknown')
endif
Cygwin / MinGW / MSYS / Windows를 구별하려면 Ken Jackson 이 흥미로운 대안을 제안합니다. 다음과 같은 답변 을 보십시오 .
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
그런 다음에 따라 관련 항목을 선택할 수 있습니다 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
노트:
옵션 ( )이 기본값 이므로 명령 uname
은 동일 합니다. 보다 나은 이유를 참조하십시오 .uname -s
-s
--kernel-name
uname -s
uname -o
OS
대신 ( uname
)을 사용 하면 식별 알고리즘이 간소화됩니다. 여전히 단독으로 사용할 수는 uname
있지만 if/else
모든 MinGW, Cygwin 등 변형을 확인하려면 블록을 처리해야합니다 .
환경 변수 OS
는 항상 "Windows_NT"
다른 Windows 버전으로 설정됩니다 ( %OS%
Wikipedia의 환경 변수 참조 ).
대안은 OS
환경 변수입니다 MSVC
( MS Visual Studio 의 존재를 확인합니다 ( Visual C ++ 사용 예제 참조 )).
내가 사용하는 완전한 예를 제공 아래 make
와 gcc
: 공유 라이브러리를 구축 *.so
또는 *.dll
플랫폼에 따라. 예제는 이해하기 쉽게 가능한 한 단순합니다.
Windows에 설치 make
하고 설치하려면 Cygwin 또는 MinGW를gcc
참조하십시오 .
내 예는 5 개의 파일을 기반으로합니다.
├── lib
│ └── Makefile
│ └── hello.h
│ └── hello.c
└── app
└── Makefile
└── main.c
알림 : tabulation을Makefile
사용하여 들여 씁니다 . 샘플 파일 아래에 복사하여 붙여 넣을 때주의하십시오.
두 Makefile
파일
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"
자세한 내용 은 cfi가 지적한 자동 변수 설명서 를 참조하십시오 .
소스 코드
- 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);
}
빌드
복사 붙여 넣기를 수정합니다 Makefile
(앞의 공백을 하나의 표로 대체).
> sed 's/^ */\t/' -i */Makefile
이 make
명령은 두 플랫폼에서 동일합니다. 주어진 출력은 유닉스 계열 OS에 있습니다.
> 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'
질주
응용 프로그램은 공유 라이브러리가 어디에 있는지 알아야합니다.
Windows에서 간단한 해결책은 애플리케이션이있는 라이브러리를 복사하는 것입니다.
> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'
유닉스 계열 OS에서는 LD_LIBRARY_PATH
환경 변수를 사용할 수 있습니다 .
> export LD_LIBRARY_PATH=lib
Windows에서 명령을 실행하십시오.
> app/app.exe
hello
유닉스 계열 OS에서 명령을 실행하십시오.
> app/app
hello
PROCESSOR_ARCHITECTURE
envvar는 프로세스가 32 비트인지 64 비트인지에 따라 가상화 된 것으로 보입니다. 따라서make
32 비트이고 64 비트 응용 프로그램을 만들려고하면 실패합니다.PROCESSOR_ARCHITEW6432
나를 위해 일한 것과 함께 사용 ( 이것 과 저것 참조 )