RayeR
CZ, 26.03.2010, 01:14 |
Multiplatform makefile for gcc (Developers) |
Could someone give me an idea how to detect OS from makefile? I have some sources that I'm compiling with DJGPP, MinGW32 and Linux gcc. I need to link it with some OS specific libraries so I need to detect OS and use proper -l arguments and then just type "make" without different options. In C source I can simply use e.g. #ifdef __WIN32__ but make probably doesn't have something similar. It would need to call some other utility for OS detection but how this utility will run under all OSes? I can also got rough guess by testing specific environment variables e.g. "WINDIR". Or maybe grepping output of "gcc -v" (I have set proper path to compiler). But maybe it's bad idea and I should rather make 3 scripts maked, makew, makel which will call make with some args... --- DOS gives me freedom to unlimited HW access. |
Rugxulo
Usono, 26.03.2010, 03:56 (edited by Rugxulo, 26.03.2010, 19:39)
@ RayeR
|
Multiplatform makefile for gcc |
> Could someone give me an idea how to detect OS from makefile? I have some
> sources that I'm compiling with DJGPP, MinGW32 and Linux gcc. I need to
> link it with some OS specific libraries so I need to detect OS and use
> proper -l arguments and then just type "make" without different options.
> In C source I can simply use e.g. #ifdef __WIN32__ but make probably
> doesn't have something similar.
I suspected it did, but a quick check of make.info doesn't show anything. (Eli Z. probably knows, ask on comp.os.msdos.djgpp).
> It would need to call some other utility
> for OS detection but how this utility will run under all OSes?
"uname", most likely, although it's not always installed except on *nix and Cygwin.
ifeq ($(DJGPP),)
UNAME=uname
else
UNAME ?= $(foreach dir,$(subst ;, ,$(PATH)),$(wildcard $(dir)/uname$(EXE)))
ifeq ($(strip $(UNAME)),)
UNAME=$(wildcard uname$(EXE))
endif
endif
ifneq ($(strip $(UNAME)),)
empty=
space=$(empty) $(empty)
backslashspace=\$(space)
backslashlparen=\(
backslashrparen=\)
leftparen=(
rightparen=)
TARGET=$(shell $(UNAME) -srm)
OS_TARGET=$(subst $(rightparen),$(backslashrparen),$(subst (leftparen),$(backslashlparen),$(subst $(space),$(backslashspace),$(TARGET))))
endif
> I can also
> got rough guess by testing specific environment variables e.g. "WINDIR".
"windir" (case sensitive!) is a good choice. "DJGPP" is another good one. Not sure about detecting Cygwin uniquely, but you get the idea.
> Or maybe grepping output of "gcc -v" (I have set proper path to compiler).
> But maybe it's bad idea and I should rather make 3 scripts maked, makew,
> makel which will call make with some args...
No, you don't have to do that. (Although I think "gcc -dumpversion" is better, heh.) At least things like CBuild can detect OS for you. Not sure about CMake, Ant, Jam, etc.
EDIT: Almost forgot about this.
%OS%="Windows_NT" (or "DRDOS", "NWDOS", "OPENDOS")
(under GNU Bash) see %MACHTYPE% (i786-pc-msdosdjgpp), %OSTYPE% (msdosdjgpp)
MS-DOS 6.x on up (but not DR-DOS):
ver | find "XP"
if errorlevel 1 echo Windows XP *NOT* detected! --- Know your limits.h |
marcov
26.03.2010, 14:20
@ RayeR
|
Multiplatform makefile for gcc |
> Could someone give me an idea how to detect OS from makefile?
I don't know how GCC handles this, but the FPC (g)makefiles query the compiler, which can print host and target OS and CPU.
This also means that the makefile can autoconfigure crosscompiling. |
Rugxulo
Usono, 26.03.2010, 19:35
@ marcov
|
Multiplatform makefile for gcc |
> > Could someone give me an idea how to detect OS from makefile?
>
> I don't know how GCC handles this, but the FPC (g)makefiles query the
> compiler, which can print host and target OS and CPU.
>
> This also means that the makefile can autoconfigure crosscompiling.
"gcc -dumpmachine" is probably what you mean.
FYI, old DJGPP (GCC 2.6.3 and 2.7.2.3) says "go32" while everything since 2.8.1 says "djgpp".
P.S. marcov didn't mention, but *BSD doesn't come with GNU make by default, only its own (aka, pmake). I'm a lame coder, but even I did something like this (in "BSDmakefile"):
GCCVER != gcc -dumpversion
UNAME1 != uname -s
UNAME2 != uname -r
UNAME3 != uname -m
UNAME=$(UNAME1)\ $(UNAME2)\ $(UNAME3)
CPU=i686
.if ${GCCVER} == "3.3.3" || ${GCCVER} == "3.3.4" || ${GCCVER} == "3.3.5" || ${GCCVER} == "3.3.6"
MTUNE=-mcpu=$(CPU) -DMTUNE=\"$(CPU)\"
.else
MTUNE=-mtune=$(CPU) -DMTUNE=\"$(CPU)\"
.endif
OPTIMIZE=-O2 -fomit-frame-pointer
CXX=g++
CXXFLAGS=-s -static $(OPTIMIZE) $(MTUNE) -DOS_TARGET=\"$(UNAME)\"
--- Know your limits.h |
RayeR
CZ, 29.03.2010, 01:23
@ Rugxulo
|
Multiplatform makefile for gcc |
Thanks for all suggestions. After some thinking it seems that
gcc -dumpmachine
is the best choice for me. So I added following into my makefile:
CCSYSTEM = $(shell $(CC) -dumpmachine)
to get current compiler platform (path is set) and then decide target filename:
# Files
PROGNAME = SPIPGM
ifeq ($(findstring mingw32, $(CCSYSTEM)), mingw32)
PROGNAME = SPIPGMW
endif
ifeq ($(findstring cygwin, $(CCSYSTEM)), cygwin)
PROGNAME = SPIPGMW
endif
PROGEXT = EXE
ifeq ($(findstring linux, $(CCSYSTEM)), linux)
PROGEXT =
endif
BTW I wonder if make is too silly that don't know logical operators to be able to write
ifeq ($(findstring mingw32, $(CCSYSTEM)), mingw32) || ($(findstring cygwin, $(CCSYSTEM)), cygwin)
or even simpler if multiple substring search possible
infeq ($(findstring mingw32 cygwin ..., $(CCSYSTEM)), )
condition in one line but probably I missed that - not a make guru ;) --- DOS gives me freedom to unlimited HW access. |