Related
We are required to use a Makefile to pull everything together for our project, but our professor never showed us how to.
I only have one file, a3driver.cpp. The driver imports a class from a location, "/user/cse232/Examples/example32.sequence.cpp".
That's it. Everything else is contained with the .cpp.
How would I go about making a simple Makefile that creates an executable called a3a.exe?
Since this is for Unix, the executables don't have any extensions.
One thing to note is that root-config is a utility which provides the right compilation and linking flags; and the right libraries for building applications against root. That's just a detail related to the original audience for this document.
Make Me Baby
or You Never Forget The First Time You Got Made
An introductory discussion of make, and how to write a simple makefile
What is Make? And Why Should I Care?
The tool called Make is a build dependency manager. That is, it takes care of knowing what commands need to be executed in what order to take your software project from a collection of source files, object files, libraries, headers, etc., etc.---some of which may have changed recently---and turning them into a correct up-to-date version of the program.
Actually, you can use Make for other things too, but I'm not going to talk about that.
A Trivial Makefile
Suppose that you have a directory containing: tool tool.cc tool.o support.cc support.hh, and support.o which depend on root and are supposed to be compiled into a program called tool, and suppose that you've been hacking on the source files (which means the existing tool is now out of date) and want to compile the program.
To do this yourself you could
Check if either support.cc or support.hh is newer than support.o, and if so run a command like
g++ -g -c -pthread -I/sw/include/root support.cc
Check if either support.hh or tool.cc are newer than tool.o, and if so run a command like
g++ -g -c -pthread -I/sw/include/root tool.cc
Check if tool.o is newer than tool, and if so run a command like
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
Phew! What a hassle! There is a lot to remember and several chances to make mistakes. (BTW-- the particulars of the command lines exhibited here depend on our software environment. These ones work on my computer.)
Of course, you could just run all three commands every time. That would work, but it doesn't scale well to a substantial piece of software (like DOGS which takes more than 15 minutes to compile from the ground up on my MacBook).
Instead you could write a file called makefile like this:
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
and just type make at the command line. Which will perform the three steps shown above automatically.
The unindented lines here have the form "target: dependencies" and tell Make that the associated commands (indented lines) should be run if any of the dependencies are newer than the target. That is, the dependency lines describe the logic of what needs to be rebuilt to accommodate changes in various files. If support.cc changes that means that support.o must be rebuilt, but tool.o can be left alone. When support.o changes tool must be rebuilt.
The commands associated with each dependency line are set off with a tab (see below) should modify the target (or at least touch it to update the modification time).
Variables, Built In Rules, and Other Goodies
At this point, our makefile is simply remembering the work that needs doing, but we still had to figure out and type each and every needed command in its entirety. It does not have to be that way: Make is a powerful language with variables, text manipulation functions, and a whole slew of built-in rules which can make this much easier for us.
Make Variables
The syntax for accessing a make variable is $(VAR).
The syntax for assigning to a Make variable is: VAR = A text value of some kind
(or VAR := A different text value but ignore this for the moment).
You can use variables in rules like this improved version of our makefile:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
which is a little more readable, but still requires a lot of typing
Make Functions
GNU make supports a variety of functions for accessing information from the filesystem or other commands on the system. In this case we are interested in $(shell ...) which expands to the output of the argument(s), and $(subst opat,npat,text) which replaces all instances of opat with npat in text.
Taking advantage of this gives us:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
which is easier to type and much more readable.
Notice that
We are still stating explicitly the dependencies for each object file and the final executable
We've had to explicitly type the compilation rule for both source files
Implicit and Pattern Rules
We would generally expect that all C++ source files should be treated the same way, and Make provides three ways to state this:
suffix rules (considered obsolete in GNU make, but kept for backwards compatibility)
implicit rules
pattern rules
Implicit rules are built in, and a few will be discussed below. Pattern rules are specified in a form like
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
which means that object files are generated from C source files by running the command shown, where the "automatic" variable $< expands to the name of the first dependency.
Built-in Rules
Make has a whole host of built-in rules that mean that very often, a project can be compile by a very simple makefile, indeed.
The GNU make built in rule for C source files is the one exhibited above. Similarly we create object files from C++ source files with a rule like $(CXX) -c $(CPPFLAGS) $(CFLAGS).
Single object files are linked using $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS), but this won't work in our case, because we want to link multiple object files.
Variables Used By Built-in Rules
The built-in rules use a set of standard variables that allow you to specify local environment information (like where to find the ROOT include files) without re-writing all the rules. The ones most likely to be interesting to us are:
CC -- the C compiler to use
CXX -- the C++ compiler to use
LD -- the linker to use
CFLAGS -- compilation flag for C source files
CXXFLAGS -- compilation flags for C++ source files
CPPFLAGS -- flags for the c-preprocessor (typically include file paths and symbols defined on the command line), used by C and C++
LDFLAGS -- linker flags
LDLIBS -- libraries to link
A Basic Makefile
By taking advantage of the built-in rules we can simplify our makefile to:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
We have also added several standard targets that perform special actions (like cleaning up the source directory).
Note that when make is invoked without an argument, it uses the first target found in the file (in this case all), but you can also name the target to get which is what makes make clean remove the object files in this case.
We still have all the dependencies hard-coded.
Some Mysterious Improvements
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
Notice that
There are no longer any dependency lines for the source files!?!
There is some strange magic related to .depend and depend
If you do make then ls -A you see a file named .depend which contains things that look like make dependency lines
Other Reading
GNU make manual
Recursive Make Considered Harmful on a common way of writing makefiles that is less than optimal, and how to avoid it.
Know Bugs and Historical Notes
The input language for Make is whitespace sensitive. In particular, the action lines following dependencies must start with a tab. But a series of spaces can look the same (and indeed there are editors that will silently convert tabs to spaces or vice versa), which results in a Make file that looks right and still doesn't work. This was identified as a bug early on, but (the story goes) it was not fixed, because there were already 10 users.
(This was copied from a wiki post I wrote for physics graduate students.)
I've always thought this was easier to learn with a detailed example, so here's how I think of makefiles. For each section you have one line that's not indented and it shows the name of the section followed by dependencies. The dependencies can be either other sections (which will be run before the current section) or files (which if updated will cause the current section to be run again next time you run make).
Here's a quick example (keep in mind that I'm using 4 spaces where I should be using a tab, Stack Overflow won't let me use tabs):
a3driver: a3driver.o
g++ -o a3driver a3driver.o
a3driver.o: a3driver.cpp
g++ -c a3driver.cpp
When you type make, it will choose the first section (a3driver). a3driver depends on a3driver.o, so it will go to that section. a3driver.o depends on a3driver.cpp, so it will only run if a3driver.cpp has changed since it was last run. Assuming it has (or has never been run), it will compile a3driver.cpp to a .o file, then go back to a3driver and compile the final executable.
Since there's only one file, it could even be reduced to:
a3driver: a3driver.cpp
g++ -o a3driver a3driver.cpp
The reason I showed the first example is that it shows the power of makefiles. If you need to compile another file, you can just add another section. Here's an example with a secondFile.cpp (which loads in a header named secondFile.h):
a3driver: a3driver.o secondFile.o
g++ -o a3driver a3driver.o secondFile.o
a3driver.o: a3driver.cpp
g++ -c a3driver.cpp
secondFile.o: secondFile.cpp secondFile.h
g++ -c secondFile.cpp
This way if you change something in secondFile.cpp or secondFile.h and recompile, it will only recompile secondFile.cpp (not a3driver.cpp). Or alternately, if you change something in a3driver.cpp, it won't recompile secondFile.cpp.
Let me know if you have any questions about it.
It's also traditional to include a section named "all" and a section named "clean". "all" will usually build all of the executables, and "clean" will remove "build artifacts" like .o files and the executables:
all: a3driver ;
clean:
# -f so this will succeed even if the files don't exist
rm -f a3driver a3driver.o
EDIT: I didn't notice you're on Windows. I think the only difference is changing the -o a3driver to -o a3driver.exe.
Why does everyone like to list out source files? A simple find command can take care of that easily.
Here's an example of a dirt simple C++ Makefile. Just drop it in a directory containing .C files and then type make...
appname := myapp
CXX := clang++
CXXFLAGS := -std=c++11
srcfiles := $(shell find . -name "*.C")
objects := $(patsubst %.C, %.o, $(srcfiles))
all: $(appname)
$(appname): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)
depend: .depend
.depend: $(srcfiles)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
dist-clean: clean
rm -f *~ .depend
include .depend
You had two options.
Option 1: simplest makefile = NO MAKEFILE.
Rename "a3driver.cpp" to "a3a.cpp", and then on the command line write:
nmake a3a.exe
And that's it. If you're using GNU Make, use "make" or "gmake" or whatever.
Option 2: a 2-line makefile.
a3a.exe: a3driver.obj
link /out:a3a.exe a3driver.obj
I used friedmud's answer. I looked into this for a while, and it seems to be a good way to get started. This solution also has a well defined method of adding compiler flags. I answered again, because I made changes to make it work in my environment, Ubuntu and g++. More working examples are the best teacher, sometimes.
appname := myapp
CXX := g++
CXXFLAGS := -Wall -g
srcfiles := $(shell find . -maxdepth 1 -name "*.cpp")
objects := $(patsubst %.cpp, %.o, $(srcfiles))
all: $(appname)
$(appname): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)
depend: .depend
.depend: $(srcfiles)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
dist-clean: clean
rm -f *~ .depend
include .depend
Makefiles seem to be very complex. I was using one, but it was generating an error related to not linking in g++ libraries. This configuration solved that problem.
Your Make file will have one or two dependency rules depending on whether you compile and link with a single command, or with one command for the compile and one for the link.
Dependency are a tree of rules that look like this (note that the indent must be a TAB):
main_target : source1 source2 etc
command to build main_target from sources
source1 : dependents for source1
command to build source1
There must be a blank line after the commands for a target, and there must not be a blank line before the commands. The first target in the makefile is the overall goal, and other targets are built only if the first target depends on them.
So your makefile will look something like this.
a3a.exe : a3driver.obj
link /out:a3a.exe a3driver.obj
a3driver.obj : a3driver.cpp
cc a3driver.cpp
I suggest (note that the indent is a TAB):
tool: tool.o file1.o file2.o
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
or
LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o
The latter suggestion is slightly better since it reuses GNU Make implicit rules. However, in order to work, a source file must have the same name as the final executable (i.e.: tool.c and tool).
Notice, it is not necessary to declare sources. Intermediate object files are generated using implicit rule. Consequently, this Makefile work for C and C++ (and also for Fortran, etc...).
Also notice, by default, Makefile use $(CC) as the linker. $(CC) does not work for linking C++ object files. We modify LINK.o only because of that. If you want to compile C code, you don't have to force the LINK.o value.
Sure, you can also add your compilation flags with variable CFLAGS and add your libraries in LDLIBS. For example:
CFLAGS = -Wall
LDLIBS = -lm
One side note: if you have to use external libraries, I suggest to use pkg-config in order to correctly set CFLAGS and LDLIBS:
CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)
The attentive reader will notice that this Makefile does not rebuild properly if one header is changed. Add these lines to fix the problem:
override CPPFLAGS += -MMD
include $(wildcard *.d)
-MMD allows to build .d files that contains Makefile fragments about headers dependencies. The second line just uses them.
For sure, a well written Makefile should also include clean and distclean rules:
clean:
$(RM) *.o *.d
distclean: clean
$(RM) tool
Notice, $(RM) is the equivalent of rm -f, but it is a good practice to not call rm directly.
The all rule is also appreciated. In order to work, it should be the first rule of your file:
all: tool
You may also add an install rule:
PREFIX = /usr/local
install:
install -m 755 tool $(DESTDIR)$(PREFIX)/bin
DESTDIR is empty by default. The user can set it to install your program at an alternative system (mandatory for cross-compilation process). Package maintainers for multiple distribution may also change PREFIX in order to install your package in /usr.
One final word: Do not place source files in sub-directories. If you really want to do that, keep this Makefile in the root directory and use full paths to identify your files (i.e. subdir/file.o).
So to summarise, your full Makefile should look like:
LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)
all: tool
tool: tool.o file1.o file2.o
clean:
$(RM) *.o *.d
distclean: clean
$(RM) tool
install:
install -m 755 tool $(DESTDIR)$(PREFIX)/bin
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++. I've been reading up on shared libraries and it seems to be the best solution.
However, as headers/source change frequently, I'm hoping to create a makefile that would automatically generate all the .so files from the headers and source.
To better demonstrate what I'm trying to do, I'll take one of my sub-libraries, Chrono and show how I would do this manually.
I first create the object files like so,
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp
So that I now have DateTime.o, Schedule.o, Duration.o, and DayCount.o in the current directory. I then create the .so file,
$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc
I then go,
$ rm ./*.o && ldconfig -n ./
So that my working directory now contains, libChrono.so.1.0.1 and the symlink libChrono.so.1.
There are quite a few subdirectories I need to do this for, so you can see that this quickly grows inefficient whenever changes to headers/source are made. I would be grateful if anyone can help me design a makefile that accomplishes all this simply by invoking make.
Thanks!
UPDATE:
Based on goldilock's advice and some digging, I managed to bang together:
CXX=g++
CFLAGS=-std=c++11
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/, $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))
all: $(TARGET)
#true
clean:
#-rm -f $(TARGET) $(CHRONOOBJ)
./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
#echo "======================="
#echo "Creating library file $#"
#echo "======================="
#$(CXX) -shared -Wl,-soname,$(join $(basename $#), .1) -o $# $^ -l
#echo "-- $# file created --"
$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $#
4 .o files are produced in lib/ but I get multiple definition complaints from ld. Before I was compiling the object files separately, but this unwinds CHRONOOBJ on one line. Any ideas?
Fortunately you included the origin of your problem:
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++.
Because this reveals a potential XY problem. The straightforward solution to this is to put object files into an archive (aka. a static library) and use that.
GNU make has an implicit rule for creating C++ .o files. It amounts to this:
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
Meaning, if you make DateTime.o in a directory with a makefile that doesn't redefine this, it will make DateTime.o. You may want to add things to $(CXXFLAGS) however, e.g.:
CXXFLAGS += -Wall -Wextra --std=c++11
If you intend to stick with the shared lib route, -fPIC can go there too. That one line could be your entire makefile.
However, you also want to put these together, so you must first declare all the objects and a rule for combining them:
OBJS = DateTime.o Schedule.o Duration.o
libChrono.a: $(OBJS)
ar crvs $# $^
This last line (see man ar) creates the archive (libChrono.a) containing all the objects in $(OBJS). You can then use this with whatever program by placing it in the same directory (or a directory in the library path) and linking -lChrono. Only the necessary parts will be extracted and compiled in. This saves you having to maintain a shared lib in a system directory.
If you still think you need a shared lib, $# and $^ are automatic variables; you can use similar methodology to create a .so, something along the lines of:
SO_FLAGS = -shared
libChrono.so.1.0.1: $(OBJS)
$(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $# $^ -lc
If that is your first rule, make will take care of everything: building first the objects and then the library. Notice this one has excluded your normal $(CXXFLAGS) to duplicate exactly the compiler line from the question.
I work in a computational biophysics lab. I am not a programmer, although I do get paid to act like one. Here's my problem: the main product of the lab is a ginormous (50+ source files) C program. I need to get our lab's program to work with another lab's toolkit, which just so happens to be in the form of a series of C++ libraries (.a files). I can get the main library for our program to compile using the following makefile:
CC = gcc
#CC = icc
CFLAGS = -g -Wall
#CFLAGS = -xT -openmp -I/opt/local/include -I/usr/local/include -I/opt/GDBM/include
#CFLAGS = -O3 -g -Wall -I/opt/GDBM/include -fopenmp
LIB = mcce.a
AR = ar
ARFLAGS = rvs
SRC = all.c ddvv.c geom_3v_onto_3v.c ins_res.c strip.c\
app.c del_conf.c geom_apply.c line_2v.c vdotv.c\
avv.c del_prot.c geom_inverse.c load_all_param.c vector_normalize.c\
avvvv.c del_res.c geom_move.c load_param.c vector_vminusv.c\
cpy_conf.c det3.c geom_reset.c mxm4.c vector_vplusv.c\
cpy_prot.c det4.c geom_roll.c new_prot.c vector_vxv.c\
cpy_res.c dll.c get_files.c param_get.c param_exist.c\
db_close.c dvv.c iatom.c param_sav.c\
db_open.c free_strings.c ins_conf.c plane_3v.c pdbline2atom.c\
premcce.c init.c load_pdb.c write_pdb.c rotamers.c assign_rad.c get_connect12.c\
surfw.c vdw.c vdw_conf.c shuffle_n.c cmp_conf.c sort_conf.c sort_res.c id_conf.c\
energies.c assign_crg.c coulomb.c coulomb_conf.c\
get_vdw0.c get_vdw1.c relax_water.c relax_h.c monte.c monte2.c ran2.c\
relaxation.c collect_connect.c torsion.c vdw_fast.c hbond_extra.c swap.c quick_e.c\
check_tpl.c zip.c del_dir.c make_matrices.c\
mem_position.c probe.c add_membrane.c load_pdb_no_param.c ga_engine.c rotamers_ga.c compute_patches.c
OBJ = $(SRC:.c=.o)
HEADER = mcce.h
$(LIB): $(OBJ)
$(AR) $(ARFLAGS) $(LIB) $(OBJ)
$(OBJ): $(HEADER)
.c.o:
$(CC) $(CFLAGS) -c $*.c
clean:
rm -f *.o mcce.a
The executable itself then compiles with this makefile:
CC = gcc -g -O3
#CC = icc -xT -static-intel -L/opt/local/lib -L/usr/local/lib
mcce: mcce.c lib/mcce.h lib/mcce.a
# $(CC) -o mcce mcce.c mcce.a /opt/GDBM/lib/libgdbm.a -lm -lz -openmp; cp mcce bin
$(CC) -o mcce mcce.c lib/mcce.a -lgdbm -lm -lz -fopenmp; cp mcce bin
I can get a standalone version of the other lab's code to compile using this other makefile:
OEDIR = ../..
INCDIR = $(OEDIR)/include
LIBDIR = $(OEDIR)/lib
INCS = -I$(INCDIR)
LIBS = -L$(LIBDIR) \
-loezap \
-loegrid \
-loefizzchem \
-loechem \
-loesystem \
-loeplatform \
-lz \
-lpthread -lm
CXX = /usr/bin/c++
RM = rm -f
CXXFLAGS = -m64 -W -Wall -O3 -fomit-frame-pointer -ffast-math
LFLAGS = -m64 -s
TEXT2HEX = ../text2hex
PROGRAMS = other_labs_code
.SUFFIXES: .cpp
.SUFFIXES: .o
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCS) -c $<
.SUFFIXES: .txt
.SUFFIXES: .itf
.txt.itf:
$(TEXT2HEX) $< InterfaceData > $#
all: $(PROGRAMS)
clean:
$(RM) $(PROGRAMS)
$(RM) ii_files core a.out *.itf
$(RM) *.o
other_labs_code.o: other_labs_code.cpp other_labs_code.itf
other_labs_code: other_labs_code.o
$(CXX) other_labs_code.o $(LFLAGS) -o $# $(LIBS)
I know that I have to change the paths of the various libs and stuff, but other than that, how do I combine all of these makefiles into one working product? Also, since some of the source files that go into compiling my program's main library (mcce.a) are going to need to be able to call functions from the C++ source file, it's the library's makefile that I need to modify, right?
I know extremely little about makefiles, so even if someone can just point me in the direction of a tutorial that covers this kind of problem (writing a makefile for a many source file C and C++ program), that may be sufficient.
For bonus points, the C++ FAQ says that:
You must use your C++ compiler when compiling main() (e.g., for static initialization)
Your C++ compiler should direct the linking process (e.g., so it can get its special libraries)
I don't exactly know what those things are supposed to mean, but assuming that I did, are there any other important points like that I should be aware about when combining C and C++?
Preparing the code
C programs cannot just use C++ symbols. Unless the authors of the C++ code arranged for that. This is because some features that C++ offers, such as function overloading (having several functions of the same name but with different formal arguments) demand that the function name be mangled in some way. Else the linker would see the same symbol defined several times. C compilers don't understand this name mangling and therefore cannot use C++ symbols. There are, generally, two possible solutions.
Declare and define all C++ symbols that the C code wants to use within extern "C" { ... } blocks and let your C++ tools handle the linking. The C code does not need to be changed in this case.
Compile the C code with the (exact same) C++ compiler as the C++ code. Fix the C++ compiler's complaints of the C code as they arise. Depending on project size and coding style, this may or may not be a lot of work.
Preparing a master Makefile
I personally try to avoid becoming intimate with other people's Makefiles, especially if they are subject to change or complex. So, assuming generating a Makefile that orchestrates the bits you already have (as opposed to writing one Makefile incorporating everything) is okay, I'd start out with something similar to this:
I'm assuming that
One of the above-mentioned options has been implemented
The code for mcce.a lies in subdirectory mcce/lib/
other_labs_code.cpp lies in other_labs_code/
The main function you want to use lies in ./mystuff.c
the following top-level Makefile may get you started
CXX = c++
CXXFLAGS = -m64 # From other_labs_code/Makefile
LDFLAGS = -m64 -L<path to OEDIR> # From other_labs_code/Makefile
LIBS = -lgdbm -lm -lz # From mcce/lib/Makefile
LIBS += -loezap \ # From other_labs_code/Makefile
-loegrid \
-loefizzchem \
-loechem \
-loesystem \
-loeplatform \
-lpthread
mystuff: mystuff.c mcce/lib/mcce.a other_labs_code/other_labs_code.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
mcce/lib/mcce.a:
cd mcce/lib/ && $(MAKE) CC="$(CXX) -m64" mcce.a
other_labs_code/other_labs_code.o:
cd other_labs_code/ && $(MAKE) other_labs_code.o
Makefile: mcce/lib/Makefile other_labs_code/Makefile
echo "Warning: `pwd`/$# is out of date" >&2
This Makefile will employ the existing sub-project Makefiles to do the compilations. If the sub-project Makefiles have a newer timestamp than this Makefile, potentially rendering it obsolete, then this will be warned about. The linking basically works by combining the required libraries of both sub-projects. I've removed duplicates. The compiler switches are basially those of the original authors since compiling is delegated to the sub-projects. The code both sub-projects generate must be for the same platform. If your compiler is gcc/g++ then either -m64 is the default and therefore redundant in the second project or should be added to the first project. I have illustrated injecting it into the first project without changing their Makefile (using GNU make). NB: This example also causes the first project to be compiled with the C++ compiler.
An extern "C" {...} block located in a C or C++ header file that C code wants to include should look like this
/* inclusion guard etc */
#if defined(__cplusplus)
extern "C" {
#endif
/* C declarations */
#if defined(__cplusplus)
}
#endif
/* inclusion guard etc */
Minor points
In the first posted Makefile, I suggest changing the bottom part to
.c.o:
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm -f $(OBJ) mcce.a
.PHONY: clean
which is a tiny bit cleaner.
The second Makefile is broken. The bottom rule links the binary and then copies it to a directory named bin, if it exists, else a copy of the file is created and named `bin'. If the linking fails, that fact is not propagated to the caller, i.e. the error is ignored. The bottom rule should read
mcce: mcce.c lib/mcce.h lib/mcce.a
$(CC) -o $# mcce.c lib/mcce.a -lgdbm -lm -lz -fopenmp
cp mcce bin/
i.e. the link command should be on its own line and that `bin' is supposed to be a directory should be made explicit.
http://www.gnu.org/software/make/manual/make.html#Introduction
How can I link jsoncpp with a C++ program using g++? I tried:
g++ -o program program.cpp -L/path/to/library/files -ljsoncpp, -ljson, -llibjsoncpp
but g++ keeps saying:
/usr/bin/ld: cannot find -lsomething
You could also try using the new Amalgamated version of jsoncpp, which is new as of version 0.6.0.
The Amalgamated version allows you to use jsoncpp by adding just one directory with a couple of header files and one .cpp file to your project. You then can directly compile jsoncpp into your program with no worries about having to link to any jsoncpp libraries.
Look in /path/to/library/files to see what your *.a file is really named. On my system, I link with:
-ljson_linux-gcc-4.4.3_libmt
Some libraries will create a link from lib<name>.a to lib<name>-<version>.a for you, but I don't think that jsoncpp does this automatically. Therefore, you need to specify the complete name when linking.
You basically need to tell the path and the library.
jsoncpp library has pkg-config and you can use the command
`pkg-config --cflags path/to/jsoncpp/build/pkg-config/jsoncpp.pc`
for the include path and
`pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
for linking (when running the command with g++ use the ). To see the single commands which is -L/libraryPath -ljsoncpp) run the commands above in the terminal without the ``.
It is easier to use this commands in a Makefile. As example my Makefile is:
CXX = g++
CXXFLAGS = -std=c++11
INC_PATH = `pkg-config --cflags ../jsoncpp/build/pkg-config/jsoncpp.pc`
LIBS = `pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
SOURCES := $(wildcard *.cpp)
OBJDIR=obj
OBJECTS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,$(OBJDIR)/%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: yourProjectExecutableName
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
yourProjectExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $#
and then in the directory of the file I run make. The final command(s) will be printed out in the Terminal
We are required to use a Makefile to pull everything together for our project, but our professor never showed us how to.
I only have one file, a3driver.cpp. The driver imports a class from a location, "/user/cse232/Examples/example32.sequence.cpp".
That's it. Everything else is contained with the .cpp.
How would I go about making a simple Makefile that creates an executable called a3a.exe?
Since this is for Unix, the executables don't have any extensions.
One thing to note is that root-config is a utility which provides the right compilation and linking flags; and the right libraries for building applications against root. That's just a detail related to the original audience for this document.
Make Me Baby
or You Never Forget The First Time You Got Made
An introductory discussion of make, and how to write a simple makefile
What is Make? And Why Should I Care?
The tool called Make is a build dependency manager. That is, it takes care of knowing what commands need to be executed in what order to take your software project from a collection of source files, object files, libraries, headers, etc., etc.---some of which may have changed recently---and turning them into a correct up-to-date version of the program.
Actually, you can use Make for other things too, but I'm not going to talk about that.
A Trivial Makefile
Suppose that you have a directory containing: tool tool.cc tool.o support.cc support.hh, and support.o which depend on root and are supposed to be compiled into a program called tool, and suppose that you've been hacking on the source files (which means the existing tool is now out of date) and want to compile the program.
To do this yourself you could
Check if either support.cc or support.hh is newer than support.o, and if so run a command like
g++ -g -c -pthread -I/sw/include/root support.cc
Check if either support.hh or tool.cc are newer than tool.o, and if so run a command like
g++ -g -c -pthread -I/sw/include/root tool.cc
Check if tool.o is newer than tool, and if so run a command like
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
Phew! What a hassle! There is a lot to remember and several chances to make mistakes. (BTW-- the particulars of the command lines exhibited here depend on our software environment. These ones work on my computer.)
Of course, you could just run all three commands every time. That would work, but it doesn't scale well to a substantial piece of software (like DOGS which takes more than 15 minutes to compile from the ground up on my MacBook).
Instead you could write a file called makefile like this:
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
and just type make at the command line. Which will perform the three steps shown above automatically.
The unindented lines here have the form "target: dependencies" and tell Make that the associated commands (indented lines) should be run if any of the dependencies are newer than the target. That is, the dependency lines describe the logic of what needs to be rebuilt to accommodate changes in various files. If support.cc changes that means that support.o must be rebuilt, but tool.o can be left alone. When support.o changes tool must be rebuilt.
The commands associated with each dependency line are set off with a tab (see below) should modify the target (or at least touch it to update the modification time).
Variables, Built In Rules, and Other Goodies
At this point, our makefile is simply remembering the work that needs doing, but we still had to figure out and type each and every needed command in its entirety. It does not have to be that way: Make is a powerful language with variables, text manipulation functions, and a whole slew of built-in rules which can make this much easier for us.
Make Variables
The syntax for accessing a make variable is $(VAR).
The syntax for assigning to a Make variable is: VAR = A text value of some kind
(or VAR := A different text value but ignore this for the moment).
You can use variables in rules like this improved version of our makefile:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
which is a little more readable, but still requires a lot of typing
Make Functions
GNU make supports a variety of functions for accessing information from the filesystem or other commands on the system. In this case we are interested in $(shell ...) which expands to the output of the argument(s), and $(subst opat,npat,text) which replaces all instances of opat with npat in text.
Taking advantage of this gives us:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
which is easier to type and much more readable.
Notice that
We are still stating explicitly the dependencies for each object file and the final executable
We've had to explicitly type the compilation rule for both source files
Implicit and Pattern Rules
We would generally expect that all C++ source files should be treated the same way, and Make provides three ways to state this:
suffix rules (considered obsolete in GNU make, but kept for backwards compatibility)
implicit rules
pattern rules
Implicit rules are built in, and a few will be discussed below. Pattern rules are specified in a form like
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
which means that object files are generated from C source files by running the command shown, where the "automatic" variable $< expands to the name of the first dependency.
Built-in Rules
Make has a whole host of built-in rules that mean that very often, a project can be compile by a very simple makefile, indeed.
The GNU make built in rule for C source files is the one exhibited above. Similarly we create object files from C++ source files with a rule like $(CXX) -c $(CPPFLAGS) $(CFLAGS).
Single object files are linked using $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS), but this won't work in our case, because we want to link multiple object files.
Variables Used By Built-in Rules
The built-in rules use a set of standard variables that allow you to specify local environment information (like where to find the ROOT include files) without re-writing all the rules. The ones most likely to be interesting to us are:
CC -- the C compiler to use
CXX -- the C++ compiler to use
LD -- the linker to use
CFLAGS -- compilation flag for C source files
CXXFLAGS -- compilation flags for C++ source files
CPPFLAGS -- flags for the c-preprocessor (typically include file paths and symbols defined on the command line), used by C and C++
LDFLAGS -- linker flags
LDLIBS -- libraries to link
A Basic Makefile
By taking advantage of the built-in rules we can simplify our makefile to:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
We have also added several standard targets that perform special actions (like cleaning up the source directory).
Note that when make is invoked without an argument, it uses the first target found in the file (in this case all), but you can also name the target to get which is what makes make clean remove the object files in this case.
We still have all the dependencies hard-coded.
Some Mysterious Improvements
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
Notice that
There are no longer any dependency lines for the source files!?!
There is some strange magic related to .depend and depend
If you do make then ls -A you see a file named .depend which contains things that look like make dependency lines
Other Reading
GNU make manual
Recursive Make Considered Harmful on a common way of writing makefiles that is less than optimal, and how to avoid it.
Know Bugs and Historical Notes
The input language for Make is whitespace sensitive. In particular, the action lines following dependencies must start with a tab. But a series of spaces can look the same (and indeed there are editors that will silently convert tabs to spaces or vice versa), which results in a Make file that looks right and still doesn't work. This was identified as a bug early on, but (the story goes) it was not fixed, because there were already 10 users.
(This was copied from a wiki post I wrote for physics graduate students.)
I've always thought this was easier to learn with a detailed example, so here's how I think of makefiles. For each section you have one line that's not indented and it shows the name of the section followed by dependencies. The dependencies can be either other sections (which will be run before the current section) or files (which if updated will cause the current section to be run again next time you run make).
Here's a quick example (keep in mind that I'm using 4 spaces where I should be using a tab, Stack Overflow won't let me use tabs):
a3driver: a3driver.o
g++ -o a3driver a3driver.o
a3driver.o: a3driver.cpp
g++ -c a3driver.cpp
When you type make, it will choose the first section (a3driver). a3driver depends on a3driver.o, so it will go to that section. a3driver.o depends on a3driver.cpp, so it will only run if a3driver.cpp has changed since it was last run. Assuming it has (or has never been run), it will compile a3driver.cpp to a .o file, then go back to a3driver and compile the final executable.
Since there's only one file, it could even be reduced to:
a3driver: a3driver.cpp
g++ -o a3driver a3driver.cpp
The reason I showed the first example is that it shows the power of makefiles. If you need to compile another file, you can just add another section. Here's an example with a secondFile.cpp (which loads in a header named secondFile.h):
a3driver: a3driver.o secondFile.o
g++ -o a3driver a3driver.o secondFile.o
a3driver.o: a3driver.cpp
g++ -c a3driver.cpp
secondFile.o: secondFile.cpp secondFile.h
g++ -c secondFile.cpp
This way if you change something in secondFile.cpp or secondFile.h and recompile, it will only recompile secondFile.cpp (not a3driver.cpp). Or alternately, if you change something in a3driver.cpp, it won't recompile secondFile.cpp.
Let me know if you have any questions about it.
It's also traditional to include a section named "all" and a section named "clean". "all" will usually build all of the executables, and "clean" will remove "build artifacts" like .o files and the executables:
all: a3driver ;
clean:
# -f so this will succeed even if the files don't exist
rm -f a3driver a3driver.o
EDIT: I didn't notice you're on Windows. I think the only difference is changing the -o a3driver to -o a3driver.exe.
Why does everyone like to list out source files? A simple find command can take care of that easily.
Here's an example of a dirt simple C++ Makefile. Just drop it in a directory containing .C files and then type make...
appname := myapp
CXX := clang++
CXXFLAGS := -std=c++11
srcfiles := $(shell find . -name "*.C")
objects := $(patsubst %.C, %.o, $(srcfiles))
all: $(appname)
$(appname): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)
depend: .depend
.depend: $(srcfiles)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
dist-clean: clean
rm -f *~ .depend
include .depend
You had two options.
Option 1: simplest makefile = NO MAKEFILE.
Rename "a3driver.cpp" to "a3a.cpp", and then on the command line write:
nmake a3a.exe
And that's it. If you're using GNU Make, use "make" or "gmake" or whatever.
Option 2: a 2-line makefile.
a3a.exe: a3driver.obj
link /out:a3a.exe a3driver.obj
I used friedmud's answer. I looked into this for a while, and it seems to be a good way to get started. This solution also has a well defined method of adding compiler flags. I answered again, because I made changes to make it work in my environment, Ubuntu and g++. More working examples are the best teacher, sometimes.
appname := myapp
CXX := g++
CXXFLAGS := -Wall -g
srcfiles := $(shell find . -maxdepth 1 -name "*.cpp")
objects := $(patsubst %.cpp, %.o, $(srcfiles))
all: $(appname)
$(appname): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)
depend: .depend
.depend: $(srcfiles)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
dist-clean: clean
rm -f *~ .depend
include .depend
Makefiles seem to be very complex. I was using one, but it was generating an error related to not linking in g++ libraries. This configuration solved that problem.
Your Make file will have one or two dependency rules depending on whether you compile and link with a single command, or with one command for the compile and one for the link.
Dependency are a tree of rules that look like this (note that the indent must be a TAB):
main_target : source1 source2 etc
command to build main_target from sources
source1 : dependents for source1
command to build source1
There must be a blank line after the commands for a target, and there must not be a blank line before the commands. The first target in the makefile is the overall goal, and other targets are built only if the first target depends on them.
So your makefile will look something like this.
a3a.exe : a3driver.obj
link /out:a3a.exe a3driver.obj
a3driver.obj : a3driver.cpp
cc a3driver.cpp
I suggest (note that the indent is a TAB):
tool: tool.o file1.o file2.o
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
or
LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o
The latter suggestion is slightly better since it reuses GNU Make implicit rules. However, in order to work, a source file must have the same name as the final executable (i.e.: tool.c and tool).
Notice, it is not necessary to declare sources. Intermediate object files are generated using implicit rule. Consequently, this Makefile work for C and C++ (and also for Fortran, etc...).
Also notice, by default, Makefile use $(CC) as the linker. $(CC) does not work for linking C++ object files. We modify LINK.o only because of that. If you want to compile C code, you don't have to force the LINK.o value.
Sure, you can also add your compilation flags with variable CFLAGS and add your libraries in LDLIBS. For example:
CFLAGS = -Wall
LDLIBS = -lm
One side note: if you have to use external libraries, I suggest to use pkg-config in order to correctly set CFLAGS and LDLIBS:
CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)
The attentive reader will notice that this Makefile does not rebuild properly if one header is changed. Add these lines to fix the problem:
override CPPFLAGS += -MMD
include $(wildcard *.d)
-MMD allows to build .d files that contains Makefile fragments about headers dependencies. The second line just uses them.
For sure, a well written Makefile should also include clean and distclean rules:
clean:
$(RM) *.o *.d
distclean: clean
$(RM) tool
Notice, $(RM) is the equivalent of rm -f, but it is a good practice to not call rm directly.
The all rule is also appreciated. In order to work, it should be the first rule of your file:
all: tool
You may also add an install rule:
PREFIX = /usr/local
install:
install -m 755 tool $(DESTDIR)$(PREFIX)/bin
DESTDIR is empty by default. The user can set it to install your program at an alternative system (mandatory for cross-compilation process). Package maintainers for multiple distribution may also change PREFIX in order to install your package in /usr.
One final word: Do not place source files in sub-directories. If you really want to do that, keep this Makefile in the root directory and use full paths to identify your files (i.e. subdir/file.o).
So to summarise, your full Makefile should look like:
LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)
all: tool
tool: tool.o file1.o file2.o
clean:
$(RM) *.o *.d
distclean: clean
$(RM) tool
install:
install -m 755 tool $(DESTDIR)$(PREFIX)/bin