Reputation: 16860
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
# ...
Upvotes: 6
Views: 3007
Reputation: 16860
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
Upvotes: 0
Reputation: 8958
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
Upvotes: 0
Reputation: 3461
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
).
Upvotes: 6
Reputation: 14467
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
Upvotes: 1