Makefile for compiling different "modules" which can include each other - c++

We have a project with a module structure like this:
- Project
- mod1
- mod1.cpp
- mod1.h
- main.cpp
- mod2
- mod2.cpp
- mod2.h
- main.cpp
- more modules
The main.cpp file in each module instantiates and tests that module. One module can include and use another module. So for example, module 1 can include module 2 and eventually other modules.
We want to create a makefile which compiles and includes the correct modules and main.cpp file. So if I write "make module2" the makefile would compile mod2.cpp, main.cpp (in module 2) and include mod2.h. If I write "make module1" the makefile would compile mod2.cpp, mod1.cpp main.cpp (in module 1) and include mod1.h and mod2.h.
My experience with makefiles is modest, and I've used several days on this without success.
Making it generic would be preferable so that adding a new module would not require major changes to the makefile.
The closest solution I got is this:
.PHONY: clean
FLAGS=-std=c++11 -g -I"$(SYSTEMC_PATH)/include" -I"$(SYSTEMC_PATH)" -L"$(SYSTEMC_PATH)/lib-linux64" -lsystemc $(addprefix -I, $(wildcard src/*))
SRCS_WITHOUT_MAIN= $(filter-out %main.cpp, $(shell find src -name '*.cpp'))
TARGET_OBJS=$(subst src, .build/obj, $(subst .cpp,.o,$(SRCS_WITHOUT_MAIN)))
all: $(filter-out unit_test, $(subst src/, ,$(wildcard src/*)))
.SECONDARY:
.build/obj/%.o: src/%.cpp
#mkdir -p $(shell dirname $#)
g++ $(FLAGS) $^ -c -o $#
clean:
#rm -r .build
%: $(TARGET_OBJS) .build/obj/%/main.o
#mkdir -p $(shell dirname .build/bin/$#)
g++ $(FLAGS) $^ -o .build/bin/$#
SRCS_WITHOUT_MAIN holds all the cpp files of all modules except the main files. TARGET_OBJS are the corresponding list of object files. The % target matches on, for example "mod1" which compiles all cpp files and main.cpp of mod1.
The problem is, occasionally we get segfaults while running after compiling, and we need to do a "make clean && make" for it to work again. One day I used 4 hours debugging my code just to find out the makefile is some kind of broken. Now everybody on the project uses "make clean && make" all the time in fear of going through the same as I did...
Does anyone know a clever way to do this? By the way: this is a SystemC project.

Here is a crude but effective makefile that will do the job:
CC=g++
vpath %.h mod1 mod2
module1: mod1.o mod2.o main1.o
$(CC) $^ -o $#
module2: mod2.o main2.o
$(CC) $^ -o $#
mod1.o: mod1/mod1.cpp mod1.h mod2.h
mod2.o: mod2/mod2.cpp mod1.h mod2.h
main1.o: mod1/main.cpp mod1.h mod2.h
main2.o: mod2/main.cpp mod1.h mod2.h
%.o:
$(CC) -c $< -o $#
Note:
It puts all object files (e.g. mod1.o) in the parent directory, which is where I presume the makefile is.
It names the two "main" object files "main1.o" and "main2.o". Having two files with the same name in the same codebase is just asking for trouble.
Further refinements are possible; this is designed for simplicity.

The strategy of using pattern rules to match names of modules which can depend upon each other may not be possible using GNU make. From the GNU make 3.82 manual (edition 0.71)
No single implicit rule can appear more than once in a chain. This
means that 'make' will not even consider such a ridiculous thing as
making 'foo' from 'foo.o.o' by running the linker twice. This
constraint has the added benefit of preventing any infinite loop in
the search for an implicit rule chain.
(I found some discussion of this here - things may be different in later versions.)
So if module3 depends on module2, and module2 depends on module1, if we run a pattern rule to build module3, we can't then use the same rule to build module2.
It is possible to get round this using static pattern rules, where the list of targets the rule is matched is specified. I've edited my answer to use these.
You could adapt the following to your problem. Each subdirectory has a number of "*.in" files, and when the subdirectory is built files with the corresponding "*.out" file is created. The modules themselves depend on each other: in this case, mod3 depends on mod2, which in turn depends on mod1. When e.g. the file "mod1/file.in" is updated, running "make mod3" causes mod1, mod2 and mod3 to be rebuilt.
MODULES=mod1 mod2 mod3
mod1_DEPS =
mod2_DEPS = mod1
mod3_DEPS = mod2
TARGET_OBJS=$(subst .in,.out,$(shell find $# -name '*.in'))
.PRECIOUS: %.out
%.out: %.in
touch $#
%.in:
.SECONDEXPANSION:
$(MODULES) : $$(TARGET_OBJS) $$($$#_DEPS)
#echo Building module $#
The .SECONDEXPANSION target and using $$ instead of $ allows access to the $# variable in the TARGET_OBJS macro.
To treat modules differently whether they are being built as programs or libraries, you could have two separate rules, which search for their sources differently:
MODULES=mod1 mod2 mod3
mod1_DEPS =
mod2_DEPS = mod1_AS_MODULE
mod3_DEPS = mod2_AS_MODULE
TARGET_OBJS=$(subst .in,.out,$(shell find $* -name '*.in'))
MODULE_TARGET_OBJS= $(filter-out main.out $(subst .in,.out,$(shell find $* -name '*.in')))
# (elided code as above example)
$(addsuffix _AS_MODULE, $(MODULES)) : %_AS_MODULE: $$(MODULE_TARGET_OBJS) $$(%_DEPS)
#echo Building module $#
$(addsuffix _AS_PROGRAM, $(MODULES)) : %_AS_PROGRAM: $$(TARGET_OBJS) $$(%_DEPS)
#echo Building program $#
This would be invoked as, say, "make mod3_AS_PROGRAM".

Related

How to create a Makefile for a C++ project with multiple directories?

I want to create a Makefile for a project with the following layout:
Source files (.cpp, potentially .c) in /src, with potential subdirectories
Header files (.h, .hpp...) in /inc, with potential subdirectories
Object files (.o) in /obj, with potential subdirectories
External libraries in /lib
Compiled program in /bin
So far, I've managed to write together this Makefile, but with some issues:
SRC_DIR := src
BIN_DIR := bin
LIB_DIR := lib
INC_DIR := inc
OBJ_DIR := obj
SRCEXTS := .c .C .cc .cpp .CPP .c++ .cxx .cp
HDREXTS := .h .H .hh .hpp .HPP .h++ .hxx .hp
TARGETS := $(BIN_DIR)/program
SOURCES := $(wildcard $(addprefix $(SRC_DIR)/*,$(SRCEXTS)))
HEADERS := $(wildcard $(addprefix $(LIB_DIR)/*,$(HDREXTS)))
OBJECTS := $(addsuffix .o, $(basename $(SOURCES)))
CXX = g++
CXXFLAGS = -std=c++17 -c -g -Wall
.PHONY: all clean
all: $(TARGETS)
$(TARGETS): $(OBJECTS)
$(CXX) $^ -o $#
$(OBJ_DIR)%$(OBJECTS): $(SRC_DIR)%$(SOURCES)
$(CXX) $(CXXFLAGS) $< -o $#
clean:
rm -f $(OBJECTS) $(TARGETS)
I've tried to make it as "generic" as possible, so future projects could be started with this layout and makefile as a template. Currently, it creates the .o-files inside the src-directory alongisde the source code. It also fails when trying to compile the program with
g++ src/main.o -o bin/program
/usr/bin/ld: src/main.o: _ZSt4cout: invalid version 3 (max 0)
/usr/bin/ld: src/main.o: error adding symbols: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:23: bin/program] Error 1
Very new to C++ development. Been on a wild goose-chase for a while, trying to get a clear image of how it all works. My code is basically a weird Frankenstein monster of several code snippets I've stumbled upon. Hopefully my intentions are clear enough, this is my last ditch effort! Thanks in advance :)
As #JohnBollinger points out, you are attempting too much at once. I will suggest a few changes to get your makefile off the ground.
I can't explain the error you get when you try to build the executable (you haven't given us enough information to reproduce the error), but it doesn't look like a Make problem. I suggest you try to build it without Make, using the command line, and see what happens.
I will assume that the names of your sources end in ".cpp" (such as src/sailboat/foo.cpp), the names of your headers end in ".hpp", and the directory tree under obj/ is already present and correct. These restrictions are temporary training wheels; you can remove them when you have more skill.
First, finding the source files. This:
SOURCES := $(wildcard $(addprefix $(SRC_DIR)/*,$(SRCEXTS)))
will not work if src/ has subdirectories. To recurse into subdirectories, we will use find. (There is a shortcut available to GNUMake, but for now we'll do things the slow and careful way).
SOURCES := $(shell find src -name "*.cpp")
Now to construct the names of the desired object files, such as obj/sailboat/foo.o. This:
OBJECTS := $(addsuffix .o, $(basename $(SOURCES)))
will give you src/sailboat/foo.o. We need a different command to change the leading directory as well as the suffix:
OBJECTS := $(patsubst src/%.cpp,obj/%.o,$(SOURCES))
Some of the source files refer to header files, so before we can start building objects, we must be able to supply them. The compiler can find the needed headers, but we must tell it where to search. So we need the directories, not the full paths:
HEADERS := $(shell find inc -name "*.hpp")
HEADERDIRS := $(sort $(dir $(HEADERS)))
(The sort is just to remove duplicates. Not necessary, but tidy.)
Now the rule to build the objects. This is incorrect:
$(OBJ_DIR)%$(OBJECTS): $(SRC_DIR)%$(SOURCES)
$(CXX) $(CXXFLAGS) $< -o $#
Remember that OBJECTS can contain several space-separated words. So if it contains foo bar, the target will be obj/%foo bar, which is clearly not what you intended. Likewise the prerequisite list is wrong, and the recipe too. Junk it and start over.
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $< -c -o $#
Then remember the header files, and add flags to tell the compiler where to look for them:
INCLUDEFLAGS := $(addprefix -I,$(HEADERDIRS))
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $< -c $(INCLUDEFLAGS) -o $#
That should be enough to get your makefile working; further refinements can wait.
I'm not mastering makefiles but one thing for sure : target "all" is definitively not a PHONY target because it often depends on other targets (in fact, it always depends on other targets, by definition !).
Also, as said John Bollinger, it is obviously possible to have only one makefile at the root.
"all" target is not mandatory : make will look for the first target fisrt.
The folder structure is like this :
----root
----src
----inc
----obj
----lib
Here's a simple one of mine (rules to build static libraries have been commented out) :
CC=g++
SRCDIR=./src/
INCDIR=./inc/
INCFLAG=-I$(INCDIR)
OBJDIR=./obj/
LIB=./lib/
LIBFLAG=-lstdc++
#-lmystaticlibrary -lmyclasses
#$(LIBFLAG) -L$(LIB)
#STATICLIBRARIES= mystaticlibrary myclasses
OBJECTS = $(OBJDIR)apprendre.o $(OBJDIR)myfunctions.o $(OBJDIR)myclasses.o
apprendre: $(OBJECTS)
# echo
# echo --------------------- Edition des liens
$(CC) $(OBJECTS) -o $# $(INCFLAG)
# mystaticlibrary: mystaticlibrary.o
# # echo
# # echo --------------------- Compilation librairie statique $#
# ar cr $(LIB)lib$#.a $(OBJ)$#.o
# ranlib $(LIB)lib$#.a
# myclasses: myclasses.o
# # echo
# # echo --------------------- Compilation librairie statique $#
# ar cr $(LIB)lib$#.a $(OBJ)$#.o
# ranlib $(LIB)lib$#.a
$(OBJDIR)%.o: $(SRCDIR)%.cpp $(INCDIR)myfunctions.h $(INCDIR)myclasses.h
# echo
# echo --------------------- Compilation $<
$(CC) -c $< $(INCFLAG) -o $#
run:
# echo
# echo "-----------------------> GO !!! : apprendre"
# ./apprendre

C++ makefile building multiple dll and project structuring

I have tried searching for an answer but to no avail, so given that my project has got the following structure
makefile
./src
strings.cpp
networking.cpp
./bin
strings.dll
networking.dll
./build
strings.o
networking.o
./include
strings.h
networking.h
./lib
boost
I am very new to Makefiles and from the research I have done so far I have managed to get this together (not very complicated, I know)
CC = g++
SRC = src/strings.cpp
OUT = bin/strings.dll
OBJ = build/strings.o
INC= -I include
all: strings.dll
strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
The issues/questions I have are
1- It always goes through the whole compilation process, even when I have not changed the source code ?
2- How could I make things more 'effective' ? I saw examples of people using wildcards and such, but I had difficulty following along. Could I use wildcards to begin with since I want separate dlls for each target ?
3 - Lets say I introduced algorithms.h and algorithms.cpp what would be the recommended way of including that in the build ?
Thanks for any help, really appreciate it
First. Whole compilation process goes because make search for target "strings.dll" but build bin/strings.dll. So if you replace it to
bin/strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
bin/strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
build of targets (bin/strings.o and bin/strings.dll) will be performed only if prerequisite is changed.
Second - basically wildcards are used for search all files inside the directory something like this: $(whildcard *.cpp) evaluates to all cpp file inside the current directory. So you can write something like this:
all_sources = $(wildcard *.cpp)
all_objects = $(addprefix bin/,$(all_sources:.cpp=.o))
all: bin/strings.dll
bin/strings.dll: $(all_objects)
<how to build strings.dll from objects>
bin/%.o: %.cpp
<how to build objects inside bin dir from cpp of current dir>
Third - makefile is not build system itself it is just a tool that has domain specific language. You can write your own build system using make. If you want ready build you better to study automake/cmake/... many of them.
Also it is good beginning to start using make tool. Don't stop and you will surprise how much power inside it.

How to get cpp files from different directories compiled into one folder?

I have a number of C++ files distributed in several folders.
a_library/
file1.cpp
file2.cpp
category1/
file3.cpp
file4.cpp
They are guaruanteed to be uniquely named. I want to compile all those C++ files to seperate Object-files in the obj/ directory.
I have a list of all source-files with relative path, and their corresponding destination-names.
a_library/file1.cpp
a_library/file2.cpp
a_library/category1/file3.cpp
a_library/category1/file4.cpp
obj/file1.obj
obj/file2.obj
obj/file3.obj
obj/file4.obj
How can I make a rule that will convert a C++ file from the first list to a object-file from the second one?
These attempts do not work:
obj/%.obj: %:cpp
# ...
%.obj: %.cpp
# ...
.cpp.obj:
# ...
I would like to not write rules like this:
obj/%.obj: a_library/%.cpp
# ...
obj/%.obj: a_library/category1/%.cpp
# ...
Try setting VPATH:
VPATH = a_library:a_library/category1
obj/%.o: %.cpp
$(CXX) -c $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -o $# $<
And to add complete file list (I would recommend you explicitely list the files, do not use $(wildcard ...) function) and linking of the application:
files := main.cpp $(wildcard a_library/*.cpp) a_library/category1/file.cpp
obj/application: $(patsubst %.cpp,obj/%.o,$(notdir $(files)))
$(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $# $+
The $(wildcard) has an annoying tendency to pick up anything in the directories, like one-off test files or temporaries (if they happen to have a fitting name: ~file.cpp).
One solution I can think of: just build them inplace with a simple rule and then make a "collection phase" moving the ".o" files to a single folder.
Make a "collect_objs" target which depends on your $(OBJS) and then your "main" target must depend on "collect_objs".
The traversal can be done using shell
dirs := $(shell find ./ -type d)
collect_objs: $(dirs)
for d in $+; do \
mv *.o YourDestDir/*.o
done
Of course, this implies using UnxUtils package (with 'find' and 'mv') or Cygwin since you are on Windows.
The other option is to generate the targets for each of your .c/.cpp file explicitly, using some tool. Grab python, traverse source directories and for each .c/.cpp file write
obj/file_name.o:
gcc -c path/fo/file_name.c -o obj/file_name.o
Use cmake to make the build configuration for you.
Some time ago I set up a simple example project on github.
The standard way is to have a Makefile in each folder and call recursively with include
This was my first two hits on 10^100:
http://owen.sj.ca.us/~rk/howto/slides/make/slides/makerecurs.html
http://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/Recursion.html
Not strictly related to this question as it doesn't have to do with Make, though I'd like to show how I compile my projects now, 3 years later. Craftr is a Python based meta build system that encourages indirect out-of-tree builds (eg. a build in the working tree). Building object files and cresting a static library is as easy as
# craftr_module(my_project)
from craftr import *
from craftr.ext.platform import cxx, ar
objects = cxx.compile(
sources = path.platform('**/*.cpp'),
)
lib = ar.staticlib(
output = 'myproj',
inputs = [objects],
)
Running craftr -eb will result with the following structure of build products
Craftfile
file1.c
file2.c
category1/
file3.c
file4.c
build/
my_project/
obj/
file1.o
file2.o
category1/
file3.o
file4.o
libmyproj.a

make include directive and dependency generation with -MM

I want a build rule to be triggered by an include directive if the target of the include is out of date or doesn't exist.
Currently the makefile looks like this:
program_NAME := wget++
program_H_SRCS := $(wildcard *.h)
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)
DEPS = make.deps
.PHONY: all clean distclean
all: $(program_NAME) $(DEPS)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
#- $(RM) $(program_NAME)
#- $(RM) $(program_OBJS)
#- $(RM) make.deps
distclean: clean
make.deps: $(program_CXX_SRCS) $(program_H_SRCS)
$(CXX) $(CPPFLAGS) -MM $(program_CXX_SRCS) > make.deps
include $(DEPS)
The problem is that it seems like the include directive is executing before the rule to build make.deps which effectively means that make is either getting no dependency list if make.deps doesn't exist or always getting the make.deps from the previous build and not the current one.
For example:
$ make clean
$ make
makefile:32: make.deps: No such file or directory
g++ -MM addrCache.cpp connCache.cpp httpClient.cpp wget++.cpp > make.deps
g++ -c -o addrCache.o addrCache.cpp
g++ -c -o connCache.o connCache.cpp
g++ -c -o httpClient.o httpClient.cpp
g++ -c -o wget++.o wget++.cpp
g++ addrCache.o connCache.o httpClient.o wget++.o -o wget++
Edit
I read the docs for the include directive, and it sounds like if the include target doesn't exist it will continue processing the parent makefile try and build the target, but it's not completely clear to me how this works:
If an included makefile cannot be
found in any of these directories, a
warning message is generated, but it
is not an immediately fatal error;
processing of the makefile containing
the include continues. Once it has
finished reading makefiles, make will
try to remake any that are out of date
or don't exist. See section How
Makefiles Are Remade. Only after it
has tried to find a way to remake a
makefile and failed, will make
diagnose the missing makefile as a
fatal error.
ANSWER
This is a modification of the answer I accepted. The one thing missing was that the dependency files also depend on the sources, and won't get regenerated unless they are added to the deps files which are being included:
%.d: $(program_CXX_SRCS)
# $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e 's#^\(.*\)\.o:#\1.d \1.o:#' > $#
sed adds the name of the .d file to the beginning of each dependency line like so:
foo.d foo.o: foo.cpp foo.h bar.h baz.h
I got the idea from this amazing paper on the dangers of recursive make:
Recursive Make Considered Harmful
I also add the following to the makefile:
clean_list += ${program_SRCS:.c=.d}
# At the end of the makefile
# Include the list of dependancies generated for each object file
# unless make was called with target clean
ifneq "$(MAKECMDGOALS)" "clean"
-include ${program_SRCS:.c=.d}
endif
You are relying on an implicit rule to compile your .cpp files. You have to redefine it to use the -MM and -MF flags that will create the dependency file.
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $# -MM -MF $#.d
Then, you have to include these dependencies files in the Makefile, using -include that will not error when the dependencies files do not exist yet (on the first time, or after a clean).
program_DEPS := $(program_OBJS:.o=.o.d)
-include $(program_DEPS)
And remember to add the rm command for the dependencies files in the clean rule.
An important point that it took me a while to grasp is that the make.deps from the previous build are good enough. Think about it: for a given object file, the only way the list of dependency files can change is if... one of the old dependency files has been altered. And if that's the case, then the old make.deps will cause that object file to be rebuilt, and if rebuilding the object file also rebuilds make.deps, then everything will be up to date. You don't have to rebuild make.deps before checking to see which objects must be rebuilt.
The include directives work like they do in C and C++ - they are processed before anything else happens, to build the "real" makefile that make then processes. Specifically, they are processed before any rules are fired.

minimum c++ make file for linux

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.
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 $<
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". Also, ensure that the tab on the start of the line after clean: does not get changed to spaces when you paste this code or make will give you a missing separator error.
Have you looked at SCons?
Simply create a SConstruct file with the following:
Program("t.cpp")
Then type:
scons
Done!
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
a fairly small GNU Makefile, using predefined rules and auto-deps:
CC=c++
CXXFLAGS=-g -Wall -Wextra -MMD
LDLIBS=-lm
program: program.o sub.o
clean:
$(RM) *.o *.d program
-include $(wildcard *.d)
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).
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.
SConstruct with debug option:
env = Environment()
if ARGUMENTS.get('debug', 0):
env.Append(CCFLAGS = ' -g')
env.Program( source = "template.cpp" )
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. The latest is now on github: https://github.com/jdkoftinoff/magicmake
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.
[edit] At this point I use cmake for all my projects since it generates useful project files for many build systems.
jeff koftinoff
I was hunting around for what a minimal Makefile might look like other than
some_stuff:
#echo "Hello World"
I know I am late for this party, but I thought I would toss my hat into the ring as well. The following is my one directory project Makefile I have used for years. With a little modification it scales to use multiple directories (e.g. src, obj, bin, header, test, etc). Assumes all headers and source files are in the current directory. And, have to give the project a name which is used for the output binary name.
NAME = my_project
FILES = $(shell basename -a $$(ls *.cpp) | sed 's/\.cpp//g')
SRC = $(patsubst %, %.cpp, $(FILES))
OBJ = $(patsubst %, %.o, $(FILES))
HDR = $(patsubst %, -include %.h, $(FILES))
CXX = g++ -Wall
%.o : %.cpp
$(CXX) $(HDR) -c -o $# $<
build: $(OBJ)
$(CXX) -o $(NAME) $(OBJ)
clean:
rm -vf $(NAME) $(OBJ)
If your issues are because autoconf thinks the .h file is a c file, try renaming it to .hpp or .h++