OS detecting makefile
The uname command (http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html) with no parameters should tell you the operating system name. I'd use that, then make conditionals based on the return value.
UNAME := $(shell uname) ifeq ($(UNAME), Linux) # do something Linux-y endif ifeq ($(UNAME), Solaris) # do something Solaris-y endif
I routinely work on several different computers and several different operating systems, which are Mac OS X, Linux, or Solaris. For the project I'm working on, I pull my code from a remote git repository.
I like to be able to work on my projects regardless of which terminal I'm at. So far, I've found ways to get around the OS changes by changing the makefile every time I switch computers. However, this is tedious and causes a bunch of headaches.
How can I modify my makefile so that it detects which OS I'm using and modifies syntax accordingly?
Here is the 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
I ran into this problem today and I needed it on Solaris so here is a POSIX standard way to do (something very close to) this.
#Detect OS UNAME = `uname` # Build based on OS name DetectOS: -@make $(UNAME) # OS is Linux, use GCC Linux: program.c @SHELL_VARIABLE="-D_LINUX_STUFF_HERE_" rm -f program gcc $(SHELL_VARIABLE) -o program program.c # OS is Solaris, use c99 SunOS: program.c @SHELL_VARIABLE="-D_SOLARIS_STUFF_HERE_" rm -f program c99 $(SHELL_VARIABLE) -o program program.c
If your makefile may be running on non-cygwin Windows, uname may not be available. That's awkward, but this is a potential solution. You have to check for Cygwin first to rule it out, because it has WINDOWS in it's PATH too.
ifneq (,$(findstring /cygdrive/,$(PATH))) UNAME := Cygwin else ifneq (,$(findstring WINDOWS,$(PATH))) UNAME := Windows else UNAME := $(shell uname -s) endif endif
I was recently experimenting in order to answer to this question I was asking myself. Here are my conclusions :
Since in Windows, you can't be sure that the
uname command is available, you can use
gcc -dumpmachine. This will display the compiler target.
There may be also a problem when using
uname if you want to do some cross-compilation.
Here's a example list of possible output of
gcc -dumpmachine :
You can check the result in the makefile like this :
SYS := $(shell gcc -dumpmachine) ifneq (, $(findstring linux, $(SYS))) # Do linux things else ifneq(, $(findstring mingw, $(SYS))) # Do mingw things else ifneq(, $(findstring cygwin, $(SYS))) # Do cygwin things else # Do things for others endif
It worked well for me, but I'm not sure it's a reliable way of getting the system type. At least it's reliable about MinGW and that's all I need since it does not require to have the
uname command or MSYS package in Windows.
To sum up,
uname gives you the system on which you're compiling,
gcc -dumpmachine gives you the system for which you are compiling.
Hope it helped someone.
Another way to do this is by using a "configure" script. If you are already using one with your makefile, you can use a combination of uname and sed to get things to work out. First, in your script, do:
Then, in order to put this in your Makefile, start out with Makefile.in which should have something like
Use the following sed command in your configure script after the
sed -e "s|@@UNAME@@|$UNAME|" < Makefile.in > Makefile
Now your makefile should have
UNAME defined as desired. If/elif/else statements are all that's left!