views:

3298

answers:

4

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
+3  A: 

That's the job that GNU's automake/autoconf are designed to solve. You might want to investigate them.

Alternatively you can set environment variables on your different platforms and make you Makefile conditional against them.

Douglas Leeder
+14  A: 

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.

Example

UNAME := $(shell uname)

ifeq ($(UNAME), Linux)
# do something Linux-y
endif
ifeq ($(UNAME), Solaris)
# do something Solaris-y
endif
dbrown0708
The UNAME := $(shell uname) command fails when I try it.
samoz
Just to be explicit, that line goes in your Makefile.I just tried that construct in Makefiles in Cygwin and OSX, and it worked as expected.Something to try:Type uname on your command line. That'll tell you the value for that OS. OSX will likely be "Darwin".
dbrown0708
The GnuWin32 project has both uname and Gnu make available as native Windows applications, making this technique portable to MingW at a command prompt as well as Cygwin on Windows.
RBerteig
It fails on my Solaris machine when it's inside the makefile.The uname command is available on that system.
samoz
Did it work in OSX or Linux? Is it possible you're not running GNU make but some other variant? If you aren't using GNU, it might be worth installing that version on your Solaris box since OSX and Linux will be running GNU.
dbrown0708
FYI, uname on Solaris (tested on 9 and 10) reports SunOS
basszero
+2  A: 

The git makefile contains numerous examples of how to manage without autoconf/automake, yet still work on a multitude of unixy platforms.

JesperE
A: 

Note that Makefiles are extremely sensitive to spacing. Here's an example of a Makefile that runs an extra command on OSX and which works on OSX and Linux. Overall, though, autoconf/automake is the way to go for anything at all non-trivial.

UNAME := $(shell uname -s)
CPP = g++
CPPFLAGS = -pthread -ansi -Wall -Werror -pedantic -O0 -g3 -I /nexopia/include
LDFLAGS = -pthread -L/nexopia/lib -lboost_system

HEADERS = data_structures.h http_client.h load.h lock.h search.h server.h thread.h utility.h
OBJECTS = http_client.o load.o lock.o search.o server.o thread.o utility.o vor.o

all: vor

clean:
    rm -f $(OBJECTS) vor

vor: $(OBJECTS)
    $(CPP) $(LDFLAGS) -o vor $(OBJECTS)
ifeq ($(UNAME),Darwin)
    # Set the boost library location
    install_name_tool -change libboost_system.dylib /nexopia/lib/libboost_system.dylib vor
endif

%.o: %.cpp $(HEADERS) Makefile
    $(CPP) $(CPPFLAGS) -c $
ChrisInEdmonton