Programming
makefile os-agnostic os-detection
Updated Fri, 30 Sep 2022 19:31:22 GMT

OS detecting makefile


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



Solution

There are many good answers here already, but I wanted to share a more complete example that both:

  • doesn't assume uname exists on Windows
  • also detects the processor

The CCFLAGS defined here aren't necessarily recommended or ideal; they're just what the project to which I was adding OS/CPU auto-detection happened to be using.

ifeq ($(OS),Windows_NT)
    CCFLAGS += -D WIN32
    ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
        CCFLAGS += -D AMD64
    else
        ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
            CCFLAGS += -D AMD64
        endif
        ifeq ($(PROCESSOR_ARCHITECTURE),x86)
            CCFLAGS += -D IA32
        endif
    endif
else
    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Linux)
        CCFLAGS += -D LINUX
    endif
    ifeq ($(UNAME_S),Darwin)
        CCFLAGS += -D OSX
    endif
    UNAME_P := $(shell uname -p)
    ifeq ($(UNAME_P),x86_64)
        CCFLAGS += -D AMD64
    endif
    ifneq ($(filter %86,$(UNAME_P)),)
        CCFLAGS += -D IA32
    endif
    ifneq ($(filter arm%,$(UNAME_P)),)
        CCFLAGS += -D ARM
    endif
endif




Comments (5)

  • +9 – Sadly the PROCESSOR_ARCHITECTURE envvar seems to be virtualized depending on whether the process is 32-bit or 64-bit. So if your make is 32-bit and you're trying to build a 64-bit application, it will fail. Using it in combination with PROCESSOR_ARCHITEW6432 worked for me (see this, and that) — Nov 29, 2013 at 12:59  
  • +5 – Would be nice if the make team add a couple of magic variables with os and arch, probably too much trouble. — Aug 25, 2014 at 15:00  
  • +6 – @JanusTroelsen: it shouldn't matter whether OS is set on non-Windows systems. Make treats unset the same as empty, which will cause a jump to the uname-based block. You just need to add a FreeBSD check there. — Oct 02, 2015 at 16:53  
  • +3 – this breaks on osx too. /bin/sh: -c: line 0: syntax error near unexpected token ,Windows_NT' /bin/sh: -c: line 0: ifeq (,Windows_NT)' make: *** [os] Error 2 — Dec 02, 2016 at 07:58  
  • +3if,else and endif MUST NOT be indented (in my experiments). I also only got this to work outside of the target blocks — May 15, 2018 at 07:52