I am new to make files and I put this together with a bit of trial & error. This code is used to compile my c++ program.
My main.cpp file in the same folder as the makefile. I have a lib/ folder that contains the headers main depends on.
The following makefile results in a correct and complete compilation of my code. But I was expecting that I would find *.o objects left behind. (Note that I've tried to make both with and without the "clean" rule, and I get the same results both times.)
#
# Makefile
#
CXX = g++
CCFLAGS = -O3 -I/sw/include -L/sw/lib
## /sw/include and /sw/lib contain dependencies for files in my lib/
LDFLAGS = -lpng
OPTS = $(CCFLAGS) $(LDFLAGS)
SOURCES = $(wildcard lib/*.cpp) main.cpp
OBJECTS = $(SOURCES: .cpp = .o)
TARGET = spirals
$(TARGET): $(OBJECTS)
$(CXX) $(OPTS) $^ -o $#
.PHONY: depend
depend:
g++ -MM $(SOURCES) > depend
## generate dependencies list
include depend
.PHONY: clean
clean:
rm -f *.o lib/*.o $(TARGET)
Also, in case it matters, I'm on MacOSX and my program is designed in xcode. (I know that xcode has its own build flow, but I'm designing a command-line program for a linux system and I'd like to test compilation & linking in a bash environment instead of only going through xcode.)
Questions:
Am I correct to expect makefiles to produce *.o files that stick around once the main target has been created?
If so, why doesn't my makefile do this?
If you observe what command your $(TARGET) rule causes to be run:
g++ -O3 -I/sw/include -L/sw/lib -lpng lib/bar.cpp lib/foo.cpp main.cpp -o spirals
you'll see that $(OBJECTS) in fact contains *.cpp files, and there are no *.o files sticking around because you haven't asked for any.
The problem is here:
OBJECTS = $(SOURCES:.cpp=.o)
In your GNU makefile as written, this substitution reference is written with excess spaces, so never matches anything and $(OBJECTS) ends up the same as $(SOURCES). Rewrite it as above and it'll do what you expect.
(Other notes: -lpng needs to go at the end of the link command to work in general, so you should introduce another make variable (traditionally called $(LDLIBS)) so as to arrange that. Especially as someone new to makefiles, you would do better to spell out your dependencies explicitly rather than playing games with $(wildcard) and a computed $(OBJECTS). -I options are needed during compilation while -L options are used during linking, so it would be good to arrange separate $(CXXFLAGS)/$(LDFLAGS) variables used in separate rules so they are only added when required.)
Related
Just to review the terminology, this is the structure of a makefile 'rule':
target: dependencies ...
commands
...
This is the makefile I've written:
CC = mpicc
SHAREDLIB = libfmd.so
CFLAGS = -fPIC -Wall -Wno-unused-result -O3 -fopenmp
LFLAGS = -lm -fopenmp -lgsl -lgslcblas
OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
.PHONY: all shared clean
all: shared
shared: $(SHAREDLIB)
$(SHAREDLIB): depend.mk $(OBJS)
$(CC) $(OBJS) -shared -o $# $(LFLAGS)
depend.mk: *.c *.h
$(CC) -MM *.c > depend.mk
-include depend.mk
clean:
rm -f *.o libfmd.so depend.mk
When the folder is clean, and I enter make clean, the following lines are shown:
mpicc -MM *.c > depend.mk
rm -f *.o libfmd.so depend.mk
It seems to me that -include depend.mk in addition to including depend.mk, executes the rule that depend.mk is its target. I'd like to stop this behavior.
You are correct. See How Makefiles are Remade in the documentation.
There is no way to prevent this behavior: if there's a rule that creates an included makefile, make will always rebuild it if it's out of date, then re-invoke itself to read the latest version.
The question is, why do you want to avoid it? Maybe if you explained the behavior you are actually looking for at a higher level we could help. As you have it here it's possible for .o files to be created without any depend.mk file created, then a compile fails, you modify a header file to fix it, but since the depend.mk file doesn't exist when you re-run make the source files are not rebuilt properly.
If you want to get accurate handling of C/C++ dependencies with GCC you might take a look at Auto-Dependency Generation.
depend.mk: *.c *.h
$(CC) -MM *.c > depend.mk
FYI, this is wrong, as make doesn't support shell wildcards in a rule string. Although on a recipe line that could work as it gets expanded by the shell itself.
I'd like to stop this behavior
depend.mk is a prerequisite of the default target, so it is a target anyway.
Also, preprocessing into depend.mk is slow for large projects, so it totally makes sense either to switch to manually written dependencies, or use a recommended way to generate them, as #MadScientist suggested.
I am finding problem when I try to include a C source file in my Makefile. This C source file contains a function which is called by the C++ code (list.cpp) through external C linkage option. I would like to know which is the right place in the Makefile to include this C source code whose function is invoked inside C++ code. If I try adding this C file in the Makefile's SOURCES variable in order to built it, then the C++ code fails to correctly resolve the function call of C and I am getting linker error: undefined reference
Following is my Makefile content:
CFLAGS =-c -g -Wall -std=c++11
SOURCES = list.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXEC = a.out
all: $(SOURCES) $(EXEC)
$(EXEC): $(OBJECTS)
#$(CXX) $(OBJECTS) -o $# && $(EXEC)
.cpp.o:
#$(CXX) $(CFLAGS) $< -o $#
Let's assume the C source file that you need in the build is bar.c,
and that it has an associated header file bar.h that you are
#include-ing in list.cpp, and that you have correctly coded the extern C
boilerplate in bar.h.
Then the following makefile will do what you need:
Makefile
CXX_SOURCES := list.cpp
C_SOURCES := bar.c
OBJECTS = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
CXXFLAGS := -g -Wall -std=c++11
CFLAGS := -g -Wall
CPPFLAGS :=
LDFLAGS :=
LDLIBS :=
EXEC := a.out
.PHONY: all clean test
all: $(EXEC)
test: $(EXEC)
./$<
$(EXEC): $(OBJECTS)
$(CXX) $(LDFLAGS) $^ -o $# $(LDLIBS)
list.o: bar.h
clean:
rm -f $(EXEC) *.o
There are a lot of learning-points here:
1. Use immediate evaluation (:=) rather than recursive evaluation (=) of
make variables unless you particularly want recursive evaluation. See
6.2 The Two Flavors of Variables
2. If a target is merely a name for a task and not the name of a file that
the task will create, then it's a phony target
and you should tell make that it is a phony target, like:
.PHONY: all clean test
3. It is not normal for the make-recipe that builds a program to run the program as
well, like your:
#$(CXX) $(OBJECTS) -o $# && $(EXEC)
You don't always want to run a program just because you've built it, and
if the program is a long-running or interactive one then this approach
will make it impractial to build the program at all.
Probably, you want to run the program to test that it has been built correctly.
But building is one task, testing is another (that may take much longer and
involve additional resources); so you should provide a separate phony target
for testing. I've called it test in this makefile: often it is called check.
To build the program without testing it, just run make. To test it,
run make test - and this will also (re)build the program if it needs to be (re)built.
4. You don't need to write a rule to make name.o from a name.cpp, or
a rule to make name.o from a name.c. GNU make has builtin rules for doing
this correctly, as long as you have correctly set the make-variables that
make uses in those builtin rules:
CC: The command that invokes C compilation or linkage, e.g. gcc
CXX: The command that invokes C++ compilation or linkage, e.g. g++
CFLAGS: Options for C compilation
CXXFLAGS: Options for C++ compilation
CPPFLAGS: Options for the C/C++ preprocessor
5. Two more important make-variables that have conventional meanings are:
LDFLAGS: Options for linkage, excluding library (-l) options
LDLIBS: Library options (-l) for linkage.
In the simple makefile above, CPPFLAGS, LDFLAGS and LDLIBS are not
needed and could be ommitted. Instead, I've assigned them empty values
just to illustrate their use.
6. A makefile should have a phony target clean that deletes any files
that the makefile might have created, so that make clean gets you
ready to build anything or everything from scratch.
7.. If name.o is compiled from name.c or name.cpp, then of
course name.o depends on name.c|name.cpp, but it also depends
on every header file that is included by name.c|name.cpp, and the
makefile needs to express all those dependencies to work reliably. So
in this case you need (at least) the rule:
list.o: bar.h
so that if you change bar.h then make will see that foo.o is out of
date and will carry out its recipe for re-making foo.o. When you
start building complex programs it will become impractical for you
to figure out all these header-file dependencies yourself: then you'll need
to find out about auto dependency generation.
Here is the GNU Make manual
I have a project structure like this
-Project
--Common
---types.f90
---global.f90
---common_routines.f90
--Program 1
---program1.f90
---module1.f90
---module2.f90
---etc...
--Program 2
--etc...
Where, Common is folder that contains some modules that are shared across all programs. How do I include this modules on my makefile?
I tried this:
FC = gfortran
FCFLAGS = -fbounds-check -O3
FCFLAGS += -I ../Common
all: program1
program1: module1.o module2.o module3.o
program1.o: module1.o module2.o module3.o
module2.o: module1.o
module3.o: module2.o module1.o
%: %.o
$(FC) $(FCFLAGS) -o $# $^
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
clean:
rm -rf *.o *.mod
but I get an undefined reference error to the common modules variables.
I tried FCFLAGS += -I../Common types.o global.o common_routines.o
This will not work because -I is an option to the GNU Fortran preprocessor
to specify a path that the preprocessor shall search for files to be INCLUDE-ed
prior to compilation. You cannot use it to specify a path where object files (*.o)
will be searched for, after compilation, by the linker. It means nothing to
the linker and is not passed to the linker.
For simplicity let's assume that the object files you need to to link for
program1 are just program1/program1.o plus the pre-existing common/types.o,
common/global.o and common/common_routines.o
Then the following Makefile, placed in directory program1, will build it:
OBJS = program1.o ../common/types.o ../common/global.o ../common/common_routines.o
.phony: all
all: program1
program1: program1.o
$(FC) -o $# $(FCFLAGS) $(OBJS)
clean:
rm -f *.o program1
Just list all the required object files to the linker, in this case via $(OBJS)
You might wish to take the precaution of making sure that the common modules
are up to date before you build program1, and you now might think that you can do that
simply be replacing:
program1: program1.o
with:
program1: $(OBJS)
thus prompting make to recompile any of the four object files that is out
of date with respect to the corresponding source file, as a prerequisite of
building program1
make will certainly endeavour to do that, but take care. That way, it will
recompile, say, ../common/types.o from ../common/types.f90 just by its
implicit default recipe for making an .o from an .f90, since this makefile is
not telling it to do any different. But that may not be the way in which
../common/types.f90 is meant to be compiled, if you also have is a makefile in common
that stipulates how to do it in some non-default manner.
In that case, the common object files should always be compiled as per the
makefile in common. Better leave the prerequisites of program1 alone but change the recipe to:
program1: program1.o
$(MAKE) -C ../common
$(FC) -o $# $(FCFLAGS) $(OBJS)
Now, any time program1 needs to be rebuilt, the recipe will preemptively run make in ../common
before it links the four object files. (It's a small inelegance that this $(MAKE) -C ../common
will be invoked even if there's nothing for it to do: this is avoidable by more advanced make usage).
Lastly you might also find a need (if not in this case, then in another) to distinguish
between flags passed to preprocessing and/or flags passed to compilation and/or flags passed to linkage.
Conventionally, these are assigned to distinct make variables, e.g. FPPFLAGS (preprocessor),
FCFLAGS (compiler), LDFLAGS (linker).
The GNU syntax to define additional include directory is -Idir not -I dir (extra space)
Also make sure that common modules are already compiled and include search path points to the directory where you have compiled modules, not source files:
This path is also used to search for .mod files when previously compiled modules are required by a USE statement.
I'm trying to set up a Makefile to handle two different targets from one set of sources, and I'm a little out of my element. The vast majority of it works fine, but my dependency structure is hosed and thus I'm forced to do a full recompile each time. A pared down sample is as follows:
first: OBJDIR = obj
second: OBJDIR = obj-2
SRCS = $(wildcard src/*.cc)
OBJECTS = $(patsubst %.cc,$(OBJDIR)/%.o,$(SRCS))
first: CFLAGS = -g -Wall -Wextra -std=c++11 -MMD
second: CFLAGS = -g -Wall -Wextra -std=c++11 -MMD -DCOMPILE_FLAG
$(OBJDIR)/%.o: %.cc
#mkdir -p $(OBJDIR)/src
clang++ -c $(CFLAGS) -o $(OBJDIR)$# $<
#DEPENDENCIES AREN'T WORKING PROPERLY
-include $(OBJECTS:.o=.d)
first: $(OBJECTS)
clang++ -o gen/first $(OBJECTS)
second: $(OBJECTS)
clang++ -o gen/second $(OBJECTS)
If I #echo $(OBJECTS:.o=.d) under my first: executable generation (or as it's used in the compilation step), it properly expands to /obj/src/filename.d. However, when it's in the include line, it shows up simply as /src/filename.d. Obviously the .d files don't exist in that location, so it doesn't find them and does a full recompile.
Makefiles are not something I'm heavily experienced with, so if there are better ways to do anything up above, I'm all ears. The key point, though, is being able to have two sets of object files and two sets of dependencies from the same sources.
--
To clarify on the eventual goals, what I have is a set of source files that are used to build two separate executables, with the differences handled via #ifdefs.
What I want to get out of the makefile structure is a single makefile with two targets. Each target generates its own .o/.d files, so that when a change is made to the source, I can run make first and make second to generate the two new executables without having to recompile everything from scratch. I've handled this previously by having two separate makefiles, but that just seems wrong.
You've missed a critical sentence in the GNU make manual related to target-specific variables:
As with automatic variables, these values are only available within the context of a target's recipe
This means that you can't use target-specific variables in either the target or prerequisite lists: any variables used there will ALWAYS have the global value and never the target-specific value. Similarly, include lines are parsed as the makefile is read in: there's no target context at all here either so the global value is used.
Further, any time you see ANY rule in a makefile that is creating a file which is not exactly $# but is instead some modification of it, that's a red flag and you know you have a problem: -o $(OBJDIR)$# is wrong.
In general, there's a lot wrong with this makefile and it's not entirely clear exactly what you're trying to do here. Maybe if you stepped back and described the goal you want to achieve we can give you some pointers.
I believe the answer is simply to rethink the way I was doing it. I've rewritten the makefile to be as follows (trimming out anything unrelated), after reading a lot of Makefile documentation and taking into consideration some comments from MadScientist:
CC = clang++
SRCS = $(wildcard src/*.cc)
OBJECTS = $(patsubst %.cc,$(OBJDIR)/%.o,$(SRCS))
CFLAGS = -g -Wall -Wextra -std=c++11 -MMD
.PHONY: all clean run
all: $(EXECUTABLE)
-include $(OBJECTS:.o=.d)
$(EXECUTABLE): $(OBJECTS)
#mkdir -p gen
$(CC) -o gen/$(EXECUTABLE) $(OBJECTS)
$(OBJDIR)/%.o: %.cc
#mkdir -p $(#D)
$(CC) -c $(CFLAGS) $(CMDFLAGS) -o $# $<
clean:
rm -rf obj obj-2 gen
run:
cd gen && ./$(EXECUTABLE)
From there, I made a couple aliases in my .bash_profile:
alias mfirst="make OBJDIR=obj EXECUTABLE=first"
alias msecond="make OBJDIR=obj-2 CMDFLAGS=-DCOMPILE_FLAG EXECUTABLE=second"
Because the variables are now set outside of any target specification, everything plays nicely. It keeps the object files and the dependencies separate, and the aliases still allow quick usage (including mfirst run, for example).
Feel free to point out any flaws here, but I'm fairly happy with the result.
i need to build the same source tree twice,
1 - with normal cflags to build the project binary
2 - with cflags plus -fPIC to build a static library that would be some sort of SDK to develop project dynamic modules.
Using only one Makefile, what is the best approach to accomplish this?
It would be nice to do some sort of :
all: $(OBJECTS)
lib_rule: $(OBJECTS)
CFLAGS += -fPIC
.cpp.o:
$(CC) -c $< -o $# $(CFLAGS)
But obviously it can't be done.
Thanks
One thing I've used in the past is a different extension:
.cpp.o:
$(CC) -c $< -o $# $(CFLAGS)
.cpp.lo:
$(CC) -c $< -o $# $(CFLAGS) $(EXTRA_CFLAGS)
You then build your static library from the .lo files and you binary from the .o files:
prog: a.o b.o
libsdk.a: a.lo b.lo
Assuming you are using GNU Make, you can use some built in functions to only have to maintain the list of objects one time:
OBJS = a.o b.o
LOBJS = $(patsubst %.o, %.lo, $(OBJS))
GNU make offers also "Target-specific Variable Values". Consider the following Makefile:
# Makefile
CFLAGS := My Cflags
all: $(OBJECTS)
#echo "$# CFLAGS is: " $(CFLAGS)
lib_rule: CFLAGS += extended by -fPIC
lib_rule: $(OBJECTS)
#echo "$# CFLAGS is: " $(CFLAGS)
# Makefile - end.
$ make all
all CFLAGS is: My Cflags
$ make lib_rule
lib_rule CFLAGS is: My Cflags extended by -fPIC
$
(Please note: if you copy and paste the example, remember to re-add the tabstops in front of the command lines. I always get caught by that.)
Instead of placing the compiled .o files in the same directory as the source, I create them in labeled sub-directories. In your case, you can have the static library files created as source_dir/lib/*.o and your normal files as source_dir/bin/*.o. In your different build targets after you set up your unique CFLAGS, simply generate a DIR_NAME value holding the name of the appropriate sub-folder. You can use this variable when you create the paths for the compiler to use when building and when linking.
In a different make tool such as CMake, you can express something like that much more easily.
For instance, you could well do
set(sources ABC.cpp DEF.cpp XYZ.cpp)
ADD_LIBRARY(mylib STATIC ${sources})
add_executable(myExecutable ${sources} main.cpp)
Or, you could repeatedly build the same directory with different flags by including it several times from the directory's logical parent, i.e.
set(MyTweakFlag 2)
add_subdirectory("libDir" "libDir2")
set(MyTweakFlag 3)
add_subdirectory("libDir" "libDir3")
...and then use if() or whatnot in the child directory to set the right flags.
Particularly if you have many such configurations, using make becomes quite fragile; make won't correctly find the transitive closure of recursive make dependancies (and certainly won't correctly find the dependancy on the makefile itself - if you change flags, say) so if you're going to do complicated makefile magic: do it with a better tool!
(CMake simply happens to be what I replaced make with, but there are various other replacements possible, of course)