My projects almst always consist of:
Pairs of Foo.h and Foo.cpp
Some extra headers util.h etc.
What is the simplest way to write a makefile that
Runs
$CC -c foo.cpp
for each .cpp file, keeping a dependency to its coresponding .h file
Provides some way that I can manually add extra dependencies
Includes a linking step with my manuall set $LIBS variable.
I work with Linux(Ubuntu) and gcc/g++.
Please, just use automake. You'll get proper dependency tracking, makefiles that comply with the GNU Makefile Standards (e.g., make install does the correct thing and respects DESTDIR and prefix), the ability to check for system quirks as needed and support for building proper distribution tarballs.
This is a minimal configure.ac:
-*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.61])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE([foreign])
# Checks for programs.
AC_PROG_CXX
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
and a minimal Makefile.am:
## Process this file with automake to generate Makefile.in
bin_PROGRAMS = foo
foo_SOURCES = foo.cpp bar.h baz.h quux.cpp
Run autoreconf -i to generate the configure script, followed by ./configure and make.
Here is an excellent autotools tutorial.
How about this:
%.o: %.cpp %.h
$(CC) -c $< -o $#
# Some things have extra dependencies. (Headers like util.h are unlikely
# to change, but you can handle them this way if you really want to.)
#
# foo.o and bar.o both depend on baz.h
foo.o bar.o: baz.h
# foo.o also depends on gab.h and jig.h
foo.o: gab.h jig.h
# You will need a list of object files. You can build it by hand:
OBJ_FILES = foo.o bar.o snaz.o # and so on
# ...or just grab all the files in the source directory:
SOURCE_FILES = $(wildcard *.cpp)
OBJ_FILES = $(SOURCE_FILES:.cpp=.o)
# It is possible to get this from the environment, but not advisable.
LIBS = -lred -lblue
final-thing: $(OBJ_FILES)
$(CC) $(LIBS) $^ -o $#
Perhaps you can check out CMake?
If you're unfamiliar with CMake, it's basically a Makefile generator (or XCode, or Visual Studio Projects, etc, depending on platform), so it lets you specify just the variables you need, and takes care of header dependency issues for you, makefile generation, etc.
Here is a simple shell script that constructs a makefile from all .cpp files in a given directory:
# !sh
if [ $# = 0 ]
then
echo -e "please give executable name"
exit 1
fi
echo -e -n "CC=g++\nOPTIMS=\nLIBS= " > makefile
echo >> makefile
echo -n "$1: " >> makefile
for fic in *.cpp
do
echo -n "${fic%\.cpp}.o " >> makefile
done
echo >> makefile
echo -n -e "\t\$(CC) " >> makefile
for fic in *.cpp
do
echo -n "${fic%\.cpp}.o " >> makefile
done
echo -n -e "-o $1 \$(OPTIMS) \$(LIBS)\n" >> makefile
echo >> makefile
for fic in *.cpp
do
g++ -MM $fic >> makefile
echo -e "\t\$(CC) -c $fic \$(OPTIMS)\n" >> makefile
done
exit 0
It uses the -MM option of gcc for creating makefile dependency lines. Just create the script in the sources directory, (let's call it micmake), make it executable (chmod +x micmake) and type
./micmake go
It will create a makefile and the make command compile your project. The executable is named go. You can edit the makefile if you need special compilation options or libraries. For more complex projects and dependencies, you should use automake, cmake or scons.
start here simple makefile for gcc
Here is an example from one of my projects -- you can simply drop new pairs foo1.cc and foo1.h in there and they will automagically be built for you:
# determine all sources and from that all targets
sources := $(wildcard *.cpp)
programs := $(sources:.cpp=)
## compiler etc settings used in default make rules
CXX := g++
CPPFLAGS := -Wall
CXXFLAGS := -O3 -pipe
LDLIBS :=
# build all and strip programs afterwards
all: $(programs)
#test -x /usr/bin/strip && strip $^
Related
I have a makefile compiling a shared library which I call from another makefile.
When developping the library I used the variable TARGET to name the library binary.
BUILD_DIR?=$(abspath ./build)
SRC=src/file.c
INC=-I inc
CFLAGS+=-Wall -Werror
LDFLAGS+=-Wl,--no-undefined
TARGET=libname
ifndef ARCH
$(error Undefined ARCH (Library targetted architecture))
endif
default: all
all: ${BUILD_DIR}/${ARCH}/${TARGET}
${BUILD_DIR}/${ARCH}/${TARGET}: ${BUILD_DIR}/${ARCH}
${CC} ${CFLAGS} ${LDFLAGS} -fPIC -shared -o $#.so ${SRC} ${INC}
${BUILD_DIR}/${ARCH}:
#mkdir -p $#
clean:
#rm -rf ${BUILD_DIR}/${ARCH}/${TARGET}
.PHONY: all clean ${BUILD_DIR}/${ARCH}/${TARGET} ${BUILD_DIR}/${ARCH}
However, into the parent makefile, I use the variable TARGET to specify the board on which I'm deploying the app.
ifeq (${TARGET},target1)
# Target1 compiling
${LIB}:
scp $# ${TARGET_USR}#${TARGET_IP}:
${SSH_CMD} make -C $# ARCH=arm
[...]
endif
ifeq (${TARGET},target2)
# Target2 compiling
${LIB}:
make -C $# BUILD_DIR=${BUILD_DIR} CC=${CC} ARCH=${ARCH}
[...]
endif
I'm compiling as follow: make TARGET=target2 and I'm using GNU make
Compiling the library from the parent makefile succeed but the name of the library is target2.so instead of libname.so.
I thought variables were passed to submakefiles only if explicitly precised on the command call (as for BUILD_DIR, CC and ARCH) but it seems that TARGET is also passed to sub makefile.
I know that I could just do override TARGET=libname into the sub makefile.
But I would like to know if there is another solution.
By default, any command line variable arguments will override any local assignments in the makefiles. There is a way around this by using the override directive:
override TARGET := libname
This will set the variable in the child makefile, regardless of whether the value was specified on the command line.
I am very new to Autoconf, I would like to have a configure file that when I call: configure --enable-gtest=yes, such that it adds a compiler flag. The following code that I put up after searching looks as follow, but does not do the trick.
Thanks a lot
this is how my makefile looks like.
-include Makefile.config
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
install: $(OBJ)
$(CC) $(CXXFLAGS) $(DEBUGFLAG) $(OBJ) -o run
%.o:%.cpp
$(CC) $(CXXFLAGS) $(DEBUGFLAG) -c $<
clean:
rm -f *.o
this is my configure.ac
AC_INIT([test], [1.7.0])
AC_PREREQ([2.59])
AC_CONFIG_MACRO_DIR([m4])
AC_CHECK_PROGS(CXX, [g++ c++ clang], ":")
AC_PROG_CXX
AC_SUBST(CXX)
AC_ARG_ENABLE([debug],
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],[debug=false])
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
AC_CONFIG_FILES(Makefile.config)
AC_OUTPUT
and my
Makefile.config.in
CC = #CXX#
CXXFLAGS = -std=c++14
if DEBUG
DBG = debug
else
DBG =
endif
thanks
Pretty close! But not quite.
You're probably best off using Automake, which automates a lot of the Makefile drudgery for you. But if you really want to avoid it, then you have to write your Makefile correctly according to what you write in configure.ac.
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
This defines a couple of autoconf substitutions, like DEBUG_TRUE and DEBUG_FALSE. The if form you've chosen only works in Automake, in an ordinary Makefile you have to write something like:
#DEBUG_TRUE#...stuff when
#DEBUG_TRUE#...true
Alternatively you can test the values of the substitutions using GNU make's if statement.
Another approach is not to use AM_CONDITIONAL at all but rather AC_SUBST the thing you want to use in your Makefile.config.in.
I am wondering why gcc/g++ doesn't have an option to place the generated object files into a specified directory.
For example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
I know that it's possible to achive this with separate -o options given to the compiler, e.g.:
gcc -c file1.c -o ../builddir/objdir/file1.o
gcc -c file2.c -o ../builddir/objdir/file2.o
gcc -c file3.c -o ../builddir/objdir/file3.o
... and I know that I can write Makefiles via VPATH and vpath directives to simplify this.
But that's a lot of work in a complex build environment.
I could also use
gcc -c file1.c file2.c file3.c
But when I use this approach my srcdir is full of .o garbage afterwards.
So I think that an option with the semantics of --outdir would be very useful.
What is your opinion?
EDIT: our Makefiles are written in such a way that .o files actually placed into builddir/obj. But I am simply wondering if there might be a better approach.
EDIT: There are several approaches which place the burden to achieve the desired behavior to the build system (aka Make, CMake etc.). But I consider them all as being workarounds for a weakness of gcc (and other compilers too).
This is the chopped down makefile for one of my projects, which compiles the sources in 'src' and places the .o files in the directory "obj". The key bit is the the use of the patsubst() function - see the GNU make manual (which is actually a pretty good read) for details:
OUT = lib/alib.a
CC = g++
ODIR = obj
SDIR = src
INC = -Iinc
_OBJS = a_chsrc.o a_csv.o a_enc.o a_env.o a_except.o \
a_date.o a_range.o a_opsys.o
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
$(OUT): $(OBJS)
ar rvs $(OUT) $^
.PHONY: clean
clean:
rm -f $(ODIR)/*.o $(OUT)
How about changing to the directory and running the compile from there:
cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c
That's it. gcc will interpret includes of the form #include "path/to/header.h" as starting in the directory the file exists so you don't need to modify anything.
A trivial but effective workaround is to add the following right after the gcc call in your Makefile:
mv *.o ../builddir/objdir
or even a soft-clean (possibly recursive) after the compilation is done, like
rm -f *.o
or
find . -name \*.o -exec rm {} \;
You can use a simple wrapper around gcc that will generate the necessary -o options and call gcc:
$ ./gcc-wrap -c file1.c file2.c file3.c --outdir=obj
gcc -o obj/file1.o -c file1.c
gcc -o obj/file2.o -c file2.c
gcc -o obj/file3.o -c file3.c
Here is such a gcc_wrap script in its simplest form:
#!/usr/bin/perl -w
use File::Spec;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure(pass_through);
my $GCC = "gcc";
my $outdir = ".";
GetOptions("outdir=s" => \$outdir)
or die("Options error");
my #c_files;
while(-f $ARGV[-1]){
push #c_files, pop #ARGV;
}
die("No input files") if(scalar #c_files == 0);
foreach my $c_file (reverse #c_files){
my($filename, $c_path, $suffix) = fileparse($c_file, ".c");
my $o_file = File::Spec->catfile($outdir, "$filename.o");
my $cmd = "$GCC -o $o_file #ARGV $c_file";
print STDERR "$cmd\n";
system($cmd) == 0 or die("Could not execute $cmd: $!");
}
Of course, the standard way is to solve the problem with Makefiles, or simpler, with CMake or bakefile, but you specifically asked for a solution that adds the functionality to gcc, and I think the only way is to write such a wrapper. Of course, you could also patch the gcc sources to include the new option, but that might be hard.
I believe you got the concept backwards...?!
The idea behind Makefiles is that they only process the files that have been updated since the last build, to cut down on (re-)compilation times. If you bunch multiple files together in one compiler run, you basically defeat that purpose.
Your example:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
You didn't give the 'make' rule that goes with this command line; but if any of the three files has been updated, you have to run this line, and recompile all three files, which might not be necessary at all. It also keeps 'make' from spawning a seperate compilation process for each source file, as it would do for seperate compilation (when using the '-j' option, as I would strongly suggest).
I wrote a Makefile tutorial elsewhere, which goes into some extra detail (such as auto-detecting your source files instead of having them hard-coded in the Makefile, auto-determining include dependencies, and inline testing).
All you would have to do to get your seperate object directory would be to add the appropriate directory information to the OBJFILES := line and the %.o: %.c Makefile rule from that tutorial. Neil Butterworth's answer has a nice example of how to add the directory information.
(If you want to use DEPFILES or TESTFILES as described in the tutorial, you'd have to adapt the DEPFILES := and TSTFILES := lines plus the %.t: %.c Makefile pdclib.a
rule, too.)
Meanwhile I found a "half-way" solution by using the -combine option.
Example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o
this "combines" all source files into one single object file.
However, this is still "half-way" because it needs to recompile everything when only one source file changes.
I think that telling pass gcc doesn't have an separate option to say where to put object file, since it already has it. It's "-c" - it says in what directory to put object.
Having additional flag for directory only must change meening of "-c".
For example:
gcc -c file.c -o /a/b/c/file.o --put-object-in-dir-non-existing-option /a1/a2/a3
You can not put /a/b/c/file.o under /a1/a2/a3, since both paths are absolute. Thus "-c" should be changed to name object file only.
I advise you to consider a replacement of makefile, like cmake, scons and other.
This will enable to implement build system as for for simple project as well as for bigger one too.
See for example how it's easy to compile using cmake your example.
Just create file CMakeList.txt in srcdir/:
cmake_minimum_required(VERSION 2.6)
project(test)
add_library(test file1.c file2c file3.c)
And now type:
mkdir -p builddir/objdir
cd builddir/objdir
cmake ../../srcdir
make
That's all, object files will reside somewhere under builddir/objdir.
I personaly use cmake and find it very convinient. It automatically generates dependencies and has other goodies.
I am trying to figure out the same thing. For me this worked
CC = g++
CFLAGS = -g -Wall -Iinclude
CV4LIBS = `pkg-config --libs opencv4`
CV4FLAGS = `pkg-config --cflags opencv4`
default: track
track: main.o
$(CC) -o track $(CV4LIBS) ./obj/main.o
ALLFLAGS = $(CFLAGS) $(CV4FLAGS)
main.o: ./src/main.cpp ./include/main.hpp
$(CC) $(ALLFLAGS) -c ./src/main.cpp $(CV4LIBS) -o ./obj/main.o
``
This is among the problems autoconf solves.
If you've ever done ./configure && make you know what autoconf is: it's the tool that generates those nice configure scripts. What not everyone knows is that you can instead do mkdir mybuild && cd mybuild && ../configure && make and that will magically work, because autoconf is awesome that way.
The configure script generates Makefiles in the build directory. Then the entire build process happens there. So all the build files naturally appear there, not in the source tree.
If you have source files doing #include "../banana/peel.h" and you can't change them, then it's a pain to make this work right (you have to copy or symlink all the header files into the build directory). If you can change the source files to say #include "libfood/comedy/banana/peel.h" instead, then you're all set.
autoconf is not exactly easy, especially for a large existing project. But it has its advantages.
Personally for single files I do this,
rm -rf temps; mkdir temps; cd temps/ ; gcc -Wall -v --save-temps ../thisfile.c ; cd ../ ; geany thisfile.c temps/thisfile.s temps/thisfile.i
temps folder will keep all the object, preprocessed and assembly files.
This is a crude way of doing things and I would prefer above answers using Makefiles.
My program comprises sharedmemory.c sharedmemory.h semaphore.c semaphore.h sumprime.c, now I want to compile in Linux an executable file named sumprime
sumprime.c code calls some methods that are declared in sharedmemory.h semaphore.h and implemented in sharedmemory.c semaphore.c
My makefile is like this:
HEADERFILES = semaphore.h sharedmemory.h
SOURCEFILES = sumprime.c semaphore.c sharedmemory.c
OBJFILES = sumprime.o semaphore.o sharedmemory.o
DISTFILES = $(HEADERFILES) $(SOURCEFILES) Makefile
DISTFOLDER = lab5
HANDIN = ${DISTFOLDER}.tar.bz2
DEST=sumprime
CCFLAG=
.PHONY: all clean pack
all: $(DEST)
$(DEST): sumprime.o
gcc sumprime.o -o $(DEST)
sumprime.o: $(HEADERFILES) $(SOURCEFILES)
gcc -c $(HEADERFILES) $(SOURCEFILES) -o sumprime.o
clean:
pack:
#echo [PACK] Preparing for packaging...
#rm -fr ${DISTFOLDER} ${HANDIN}
#mkdir ${DISTFOLDER}
#echo [PACK] Copying solution files
#for file in ${DISTFILES}; do\
cp -f $$file ${DISTFOLDER};\
echo \>\>\> $$file;\
done;
#echo [PACK] Creating ${HANDIN}...
#tar cjf ${HANDIN} ${DISTFOLDER}
#rm -fr ${DISTFOLDER}
#echo [PACK] Done!
I tried multiple ways in vain after searching. Please help me with this
As gcc should tell you, you cannot use -c with multiple input files, so
gcc -c $(HEADERFILES) $(SOURCEFILES) -o sumprime.o
does not work.
Fortunately, it also isn't necessary; in fact, you don't need special rules for the .o files because the built-in rules work quite well. This is particularly the case because the name of the output binary corresponds with one of the object files (sumprime.o; see "Linking a single object file" behind the link).
I would use something like
#!/usr/bin/make -f
CC = gcc
CPPFLAGS = -MD
CFLAGS = -O2 -g
LDFLAGS =
LDLIBS =
TARGET = sumprime
HEADERFILES = semaphore.h sharedmemory.h
SOURCEFILES = sumprime.c semaphore.c sharedmemory.c
DISTFOLDER = lab5
DISTFILES = $(HEADERFILES) $(SOURCEFILES) Makefile
HANDIN = $(DISTFOLDER).tar.bz2
OBJFILES = $(SOURCEFILES:.c=.o)
DEPFILES = $(OBJFILES:.o=.d)
all: $(TARGET)
$(TARGET): $(OBJFILES)
clean:
rm -f $(TARGET) $(OBJFILES)
distclean: clean
rm -f $(DEPFILES) $(HANDIN)
pack: dist
dist: $(HANDIN)
$(HANDIN): $(DISTFILES)
#echo [DIST] Preparing for packaging...
#rm -f $#
#tar cjf $# --transform 's,^,$(DISTFOLDER)/,' $+
#echo [DIST] Done!
.PHONY: all clean distclean dist pack
-include $(DEPFILES)
Obviously, this requires some explanation.
Explanation
Implicit rules
I mentioned these above: make predefines a number of rules that often just Do The Right Thing™; we can make them do most of our work. In fact, the shortest Makefile you could use to build your program is
sumprime: sumprime.o semaphore.o sharedmemory.o
This uses an implicit rule to build the .o files and an implicit recipe to build sumprime. Note that there are variables that influence the behavior of implicit rules; behind the link above is a list of such rules that includes their recipes, and in them the names of the variables they use. Since we're compiling C code, the ones we're interested in are:
CPPFLAGS = -MD # C preprocessor flags, such as -Ipath -DMACRO=definition
CFLAGS = -O2 -g # C compiler flags
LDFLAGS = # linker flags, such as -Lpath
LDLIBS = # linked libraries, such as -lpthread (Alternatively:
# LOADLIBES, but this is less usual)
Pattern substitution
The lines
OBJFILES = $(SOURCEFILES:.c=.o)
DEPFILES = $(OBJFILES:.o=.d)
use pattern substitution to generate a list of .o files from a list of .c files, and .d from .o. We'll use .d files for dependency tracking.
Dependency tracking
This is perhaps the most complex part, but it's not that bad.
One of the practical problems with the minimal Makefile is that it doesn't know about #includes. If sumprime.c includes semaphore.h and semaphore.h is changed, we would really like sumprime.c to be rebuilt. Fortunately, gcc has a mechanism to facilitate this that we invoke with
CPPFLAGS = -MD
When given this option, the preprocessor generates a .d file corresponding to the input .c it was given (i.e., if sumprime.c is compiled, sumprime.d is generated) that contains a make-compatible list of dependencies of the source file. For example, I expect a sumprime.d that looks something like
sumprime.c: semaphore.h sharedmemory.h
Then, with
-include $(DEPFILES)
make is instructed to include these files into its code if they exist. This means that make always knows the dependencies of source files as they were during the last build (!). That it lags one behind is not a problem because a change in the dependencies requires a change in one of the files that a target depended on last time, and that no dependencies are pulled in the first time is not a problem because the first time everything has to be built anyway.
And so we get dependency tracking with a minimum of fuss.
Packing with GNU tar
The
pack: dist
dist: $(HANDIN)
$(HANDIN): $(DISTFILES)
#echo [DIST] Preparing for distaging...
#rm -f $#
#tar cjf $# --transform 's,^,$(DISTFOLDER)/,' $+
#echo [DIST] Done!
rule requires GNU tar, but if it is available, its --transform option makes for a much nicer dist rule, as you can see. I took the liberty of changing it to that. Of course, if you prefer, you can still use your old way.
Side note: It is more usual to call what you called the pack rule dist. There is no technical reason for this, it's just a convention; people expect make dist. With this code, both names work.
i am new to makefiles and have just rescently created a makefile that works for a c++ project. it has two cpp files and one h file. i am trying to convert my file to work in linux but cant seem to figure out how. any ideas?
EXE = NumberGuessingGame.exe
CC = cl
LD = cl
OBJ = game.obj userInterface.obj
STD_HEADERS = header.h
CFLAGS = /c
LDFLAGS = /Fe
$(EXE): $(OBJ)
$(LD) $(OBJ) $(LDFLAGS)$(EXE)
game.obj: game.cpp $(STD_HEADERS)
$(CC) game.cpp $(CFLAGS)
userInterface.obj: userInterface.cpp $(STD_HEADERS)
$(CC) userInterface.cpp $(CFLAGS)
#prepare for complete rebuild
clean:
del /q *.obj
del /q *.exe
For in depth treatment of make on Linux, see GNU make.
There are a few differences. Binaries have no extension
EXE = NumberGuessingGame
The compiler is gcc, but need not be named, because CC is built in, same goes for LD. But since your files are named .cpp, the appropriate compiler is g++, which is CXX in make.
Object files have extension .o
OBJ = game.o userInterface.o
STD_HEADERS = header.h
Compiler flags
CXXFLAGS = -c
The equivalent for /Fe is just -o, which is not specified as LDFLAGS, but spelled out on the linker command line.
Usually, you use the compiler for linking
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $(OBJ) -o $(EXE)
You don't need to specify the rules for object creation, they are built in. Just specify the dependencies
game.o: $(STD_HEADERS)
userInterface.o: $(STD_HEADERS)
del is called rm
clean:
rm -f $(OBJ)
rm -f $(EXE)
One important point is, indentation is one tab character, no spaces. If you have spaces instead, make will complain about
*** missing separator. Stop.
or some other strange error.
You can also use CMake to accomplish your task:
Put following into CMakeLists.txt file in the root directory of your project (<project-dir>):
cmake_minimum_required (VERSION 2.6)
project (NumberGuessingGame)
add_executable(NumberGuessingGame game.cpp serInterface.cpp)
Then on the console do
"in-source" build
$ cd <project-dir>
$ cmake .
$ make
or "out-source" build
$ mkdir <build-dir>
$ cd <build-dir>
$ cmake <project-dir>
$ make
You can adjust build setting using nice GUI tool. Just go to the build directory and run cmake-gui.
You don't need to include headers in the dependency list. The compiler will fail on its own, stopping make from continuing. However, if you're including them in the dependency list to force make to rebuild files in case the header changes, nobody will stop you.
CFLAGS never needs to contain -c, nor does LDFLAGS need -o. Below is a revamped makefile. Note that you can always override a macro explicitly defined in a makefile or implicitly defined using something like make CFLAGS=-Wall for example. I used the de facto standard CXX macro name in the event that you have C source files, which must be compiled using a C compiler (the value of the CC macro) instead of a C++ compiler.
.POSIX:
#CC is already implicitly defined.
CXX = g++
OBJ = game.o userInterface.o
STD_HEADERS = header.h
.SUFFIXES:
.SUFFIXES: .o .cpp .c
NumberGuessingGame: $(OBJ) $(STD_HEADERS)
$(CXX) $(CFLAGS) -o $# $(OBJ) $(LDFLAGS)
.cpp.o: $(STD_HEADERS)
$(CXX) $(CFLAGS) -c $<
#There is already an implicit .c.o rule, thus there is no need for it here.
#prepare for complete rebuild
clean:
-rm -f NumberGuessingGame *.o
As yegorich answered, you can use a build system like Cmake. It is much more flexible, cross-platform, and can generate Unix Makefiles as well as Nmake Makefiles and Visual Studio solutions on Windows.