Makefile to get source files in multiple subdirectories - c++

I am creating a custom Makefile to to build a C++ Linux application. I have my cpp source files in a folder called src on the same level as the Makefile. So far I have been able to build my object files with the following :
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
Now my project is starting to get a bit more complicated and I want subdirectories within src , such as src/common , and also, not every file is a cpp file now but also a c file.
I guess having a separate Makefile for each subdirectory is the best way but I am trying to keep this simple for now with just one Makefile.
I tried the following but doesn't work
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/common/%.cpp $(SRC_DIR)/common/%.c | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
I could have the Makefile do a shell find to find all cpp and c files but also trying to avoid this.
I'd appreciate any recommendations.

This:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/common/%.cpp $(SRC_DIR)/common/%.c | $(OBJ_DIR)
cannot work; what it says that if make wants to build some file $(OBJ_DIR)/XXX.o and there is no explicit rule, then if and only if ALL the prerequisites $(SRC_DIR)/XXX.cpp, $(SRC_DIR)/common/XXX.cpp, and $(SRC_DIR)/common/XXX.c exist or can be created by make, then the rule will match.
If the same target could be built from multiple different prerequisites you must create multiple rules, one per prerequisite.
Also, it doesn't make sense to compile both C files (.c) and C++ files (.cpp) using the same recipe. C++ compilers use the variables CXX and CXXFLAGS and C compilers use the variables CC and CFLAGS.
As for avoiding find, you can't avoid informing make what files you want to be compiled, in some manner. You either have to list them in your makefile explicitly, or else use some method to generate them dynamically. There's no way around this. You don't have to use find if you don't want to; for example if you know that all the files will be either one or two directories down you could use wildcard, like:
SRCS := $(wildcard $(SRC_DIR)/*.cpp $(SRC_DIR)/*.c $(SRC_DIR)/*/*.cpp $(SRC_DIR)/*/*.c)

Related

How to include both C and C++ files in makefile directives

The following part is commonly found in makefiles.
OBJS := $(SRCS:%.c=$(OBJDIR)/%.o)
$(OBJDIR)/%.o : %.c
$(CC) $(DEFS) $(CFLAGS) -o$# $<
Now my source folder contains both C and C++ files, and I want to link all object files created together using g++. But how do I specify to also also include *.cpp files to get compiled. I mean how do I modify OBJS to also include *.cpp files.
For OBJDIR, maybe, I can do the C++ equivalent like this. I guess the makefile would guess correctly when to use CXX (g++ for C++ files) and when to use CC (gcc for C files).
$(OBJDIR)/%.o : %.cpp
$(CXX) $(DEFS) $(CFLAGS) -o$# $<
But then, how do I add this rule to OBJS?
You want to use:
OBJS := $(addsuffix .o,$(basename $(SRCS)))
then add your pattern rule for building .o from .cpp (unless, as mentioned here, you can just use the built-in rules).
The above strips off the suffix, regardless of what it is, then adds .o to the end.
You may not need a rule for building .o files from corresponding .cpp or .c files at all, as Make comes with default rules for that, and those look a lot like what you present. The key is probably to specify which .o files need to be built in the first place.
I often see that approached by classifying the C sources separately from the C++ sources. Then you might have something like this:
C_SRCS = ...
CPP_SRCS = ...
OBJS = $(C_SRCS:.c=.o) $(CPP_SRCS:.cpp=.o)
all: myprog
myprog: $(OBJS)
$(CXX) $(CFLAGS) $(LDFLAGS) -o $# $(OBJS) $(LIBS)
If you do need your own rules for building .o files from sources, then you could of course add those.
Note also that the above has no dependencies on GNU make extensions, and if that's important to you then you'll want to avoid GNU style pattern rules for building the object files. That's what traditional suffix rules are for.

How to link objects in different directories in c++ with make without refering to them in the makefile?

I'm trying to clean up my project a little and I want to put object files and include files in a separate folder and be able to compile another makefile in my a different testing subdirectory. I would like to do this so that the make file in the testing directory doesn't have to know about the objects in the the above directory: I have been struggling all day trying to figure out make and compilation.
Not sure what I'm doing wrong but in addition to this question I would be appreciative of any information to straighten out my thinking about make and g++ so in the future I know where to look.
Anyways I have 2 Questions both with regards to my project layout:
Project
inc/
-- header files
-obj/
--object files
-source
-make file for project that compiles objects in obj directory (makefile0)
-testing/
--test1/
---test.cc
---makefile1
Question 1
So I want to include the header files in the inc directory in test.cc and then just focus on compiling test.cc like I would if I included a standard library header file. Right now I need to make reference to the object in ../../obj/ in makefile1 and would like to ignore that. and just do something simple like
g++ -I ../../inc/ -c test.cc
How is it possible to do this?
Question 2
In makefile0, for each source file I have to append a $(OBJ) or $(INC) to the front of any file I have in those folders and wondering if there is anyway to clean up my make file an do something like
Spinless2DFieldIndex.o: Spinless2DFieldIndex.cc Utils.o Dispersion.h
instead of
$(ODIR)/Spinless2DFieldIndex.o: Spinless2DFieldIndex.cc $(ODIR)/Utils.o $(INC)/Dispersion.h
The following should work:
Project/Makefile
objdir := obj/
vpath %.cc source
vpath %.o $(objdir)
CPPFLAGS := -Iinc -MMD -MP
.PHONY: all
all: testing/test1/test
include source/Makefile
include testing/test1/Makefile
Project/source/Makefile
override objects := $(objdir)obj.o
$(objects): $(objdir)%.o: %.cc
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(OUTPUT_OPTION) $<
clean:: ; $(RM) $(objects) $(objects:.o=.d)
-include $(objects:.o=.d)
Project/testing/test1/Makefile
override dir := $(dir $(lastword $(MAKEFILE_LIST)))
$(dir)test: obj.o
clean:: ; $(RM) $(dir)test $(dir)test.d
-include $(dir)test.d
This should allow for a certain amount of modularity, although the asymmetry in the makefiles betrays the fact that your idea of having a separate obj directory while at the same time wanting to have the test executables in their own directory is perhaps not the best way to organize things. Personally I use a more configure style of makefile that recreates the project tree in the current working directory which helps separate the source from the build.

Example makefile for building simple c project recompiling when headers change

Does anyone have a complete makefile that can do the following:
Rebuilds the project if a HEADER file changes
The cpp files are listed in the makefile
The header files are NOT listed in the makefile
The header files are allowed to have different names than the cpp files
Some of the cpp files do not have header files
I have seen instructions for figuring out how to make the make tool figure out header dependencies, but none of these instructions provide anything remotely resembling a working example. A simple example would be as follows: main.cpp C1.cpp C1.h C2.cpp C2.h
CXX = g++
OBJECTS := main.o C1.o C2.o
all: $(OBJECTS)
%.o : %.cpp
$(CXX) $(CPPFLAGS) -Wall -MMD -c $< -o $#
-include *.d
EDIT: As TobySpeight points out, this won't work if you build an object file, rename or delete one of the prerequisite source or header files, then try to rebuild the object file; the .d file will still require the missing file, and the build will fail. I neglected to include lines to deal with that case:
%.h: ;
%.cpp: ;
(This is effective, but crude. The more precise approach is to put some sed commands in the %.o rule, so as to add specific null rules to the .d file, one for each prerequisite, but the sed commands are ugly, and the approach above is good enough for almost all cases.)
You can also use CMake for this. Everything you need to write is:
add_executable (exec main.cpp C1.cpp C2.cpp)

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

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

any building tool can automatically understand file dependencies in C++ project?

I have a project with 50+ .h files and 50+ .cpp files. I'm using make to build a project, which looks something like this (it's just a piece of an entire file):
HEADERS := $(shell find $(INCLUDE) -name "*.h")
%.obj: %.cpp $(HEADERS)
$(CPP) $(CPPFLAGS) -fPIC -o $# -g -c $<
When I'm making changes to one .h file, the whole project has to be re-compiled. It's annoying and time-consuming. But I don't want to hard-code file dependencies inside Makefile, since it's even more time-consuming. I would like to have some make-like tool, which will find dependencies right inside my .cpp/.h files, automatically. Any suggestions? Thanks in advance!
There are many options, but nothing that works exactly like make. Many build systems will generate the Makefiles with dependencies for you though. CMake and Automake are two commonly used systems that work like that. You define your project file in a meta-language and it will generate the Makefiles.
Scons is good in finding the right sources that need to be recompiled.
It scans the files and the headers and builds up an internal dependency tree.
www.scons.org
If you are using gcc then you can use the -M option. It is designed to do exactly what you want i.e. generate a Makefile rule describing the dependencies.
Simplest way:
depend:
g++ -M *.cpp >.depends
-include .depends
Better way:
SRC=foo.cpp bar.cpp ...
OBJ=$(patsubst %.cpp,%.o,$(SRC))
DEPS=$(patsubst %.o,.deps/%.o.dep,$(OBJ))
all: .deps
.deps:
mkdir -p .deps
.cpp.o:
$(CXX) $(CXXFLAGS) -MD -MF .deps/$#.dep -c -o $# $<
-include $(DEPS)
So compiler will generate all dependencies for each file during build automatically.
Or even better: use Autotools, CMake or other build system that does this job for you.
Jam.
Boost.Build.
The latter is based on a (massively) enhanced version of the former.