tags:

views:

2508

answers:

9

I've looking to find a simple recommended "minimal" c++ makefile for linux which will use g++ to compile and link a single file and h file. Ideally the make file will not even have the physical file names in it and only have a .cpp to .o transform. What is the best way to generate such a makefile without diving into the horrors of autoconf?

The current dir contains, for example

t.cpp t.h

and I want a makefile for that to be created. I tried autoconf but its assuming .h is gcc instead of g++. Yes, while not a beginner, I am relearning from years ago best approaches to project manipulation and hence am looking for automated ways to create and maintain makefiles for small projects.

+9  A: 

If it is a single file, you can type

make t

And it will invoke

g++ t.cpp -o t

This doesn't even require a Makefile in the directory, although it will get confused if you have a t.cpp and a t.c and a t.java, etc etc.

Also a real Makefile:

SOURCES := t.cpp
# Objs are all the sources, with .cpp replaced by .o
OBJS := $(SOURCES:.cpp=.o)

all: t

# Compile the binary 't' by calling the compiler with cflags, lflags, and any libs (if defined) and the list of objects.
t: $(OBJS)
    $(CC) $(CFLAGS) -o t $(OBJS) $(LFLAGS) $(LIBS)

# Get a .o from a .cpp by calling compiler with cflags and includes (if defined)
.cpp.o:
    $(CC) $(CFLAGS) $(INCLUDES) -c $<
hazzen
this also doesn't create any dependencies.
David Nehme
This makefile is almost (but not quite) equivalent to "all : t" and letting the built-in rules take over...
Steve Jessop
But why do you have specific rule for t: ? It kind of defeats the point of having a cpp.o rule.
Richard Riley
The t rule generates, from the .o files, the binary by calling the linker. If I had four sources [abcd].cpp and a binary named t, the rule would link all four of those generated objects into one executable.
hazzen
+3  A: 

Have you looked at SCons?

Simple create a SConstruct file with the following:

Program("t.cpp")

Then type:

scons

Done!

grieve
Though I love fiddling with makefile (its a language unto itself). I think this is the best answer, but I think you need to expand this answer a bit to explain why using "SCons" is better than using Makefiles directly. I am convinced but there is not enough here to convice others.
Martin York
+3  A: 

Assuming no preconfigured system-wide make settings:

CXX = g++
CPPFLAGS =        # put pre-processor settings (-I, -D, etc) here
CXXFLAGS = -Wall  # put compiler settings here
LDFLAGS =         # put linker settings here

test: test.o
    $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) test.o

.cpp.o:
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<

test.cpp: test.h
Alnitak
Again this his a specific line for test. Why?
Richard Riley
because you always have to specify *what* the Makefile will actually build. With suitable global defs, you might just be able to say just "test:" in the file, but the file above is guaranteed to work regardless of any global rules or macros.
Alnitak
A: 

If your issues are because autoconf thinks the .h file is a c file, try renaming it to .hpp or .h++

Adam Tegen
A: 

Some good references on creating a basic Makefile

http://en.wikipedia.org/wiki/Make_(software)

http://mrbook.org/tutorials/make/

http://www.opussoftware.com/tutorial/TutMakefile.htm

http://www.hsrl.rutgers.edu/ug/make_help.html

The first couple in particular have minimal example Makefiles like you were describing. Hope that helps.

Jay
+4  A: 

Here is a generic makefile from my code snippets directory:

SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
BINS=$(SOURCES:.cpp=)

CFLAGS+=-MMD
CXXFLAGS+=-MMD

all: $(BINS)

.PHONY: clean

clean:
    $(RM) $(OBJECTS) $(DEPS) $(BINS)

-include $(DEPS)

As long as you have one .cpp source producing one binary, you don't need anything more. I have only used it with GNU make, and the dependency generation uses gcc syntax (also supported by icc). If you are using the SUN compilers, you need to change "-MMD" to "-xMMD".

florin
A: 

SConstruct with debug option:

env = Environment()

if ARGUMENTS.get('debug', 0):
    env.Append(CCFLAGS = ' -g')

env.Program( source = "template.cpp" )
Richard Riley
A: 

florin has a good starting point. I didn't like gnu autoconf so I started there and took the concept further and called it the MagicMakefile. I have 3 versions of it from simple to more complex:

Basically, it assumes you have a standard layout for the source files of your project and uses the wildcard function to create the makefile rules on the fly which are then eval'd, handling header file dependancies, cross compiling, unit tests, install, and packaging.

jeff koftinoff

jdkoftinoff
+1  A: 

Have you looked at OMake ?

OMakeroot

open build/C
DefineCommandVars()
.SUBDIRS: .

OMakefile

.DEFAULT: $(CXXProgram test, test)

Then on Linux or Windows, simply type:

omake

As a bonus, you automatically get:

  • parallel builds with the -j option (same as make).
  • MD5 checksums instead of timestamps (build becomes resilient to time synchronization failures).
  • Automatic and accurate C/C++ header dependencies.
  • Accurate inter-directory dependencies (something that recursive make does not offer).
  • Portability (1 build chain to rule them all, immune to path style issues).
  • A real programming language (better than GNU make).
bltxd
If OMake had better support for out-of-source builds and could generate Visual Studio project, it would be very close to perfect.
JesperE
We do out-of-source builds with OMake here. There are a few things to know but otherwise it works (0.9.8.5).
bltxd