Separated compilation with multiple sources by Makefile -
i wrote simple makefile compile several type of sources. , works well. makefile find protobuf
sources , c++
sources. making program act follow.
protoc
generatec++
sources files*.proto
g++
compile object files*.cpp
,*.pb.cc
(generated step 1)g++
(actuallyld
) link object*.obj
single executable
this makefile sample is:
# define protoc generator protoc = protoc include = -i$(someplace) lib = -lxml2 -lpthread -lz # final single outputted executable output = svrkit_adapter_v2 # define cpp source code/object result sources = $(wildcard *.cpp) objects=$(sources:.cpp=.o) # define proto's source/generated result/object result proto_sources = $(wildcard *.proto) proto_cppsrc = $(patsubst %.proto,%.pb.cc,$(proto_sources)) proto_object = $(patsubst %.proto,%.pb.o,$(proto_sources)) # first actual making target all:$(output) # define rule generating proto's cpp sources $(proto_cppsrc) : $(proto_sources) $(protoc) --cpp_out=. $(filter %.proto, $^) # define rule compiling generated proto cpp sources $(proto_object) : $(proto_cppsrc) $(cxx) $(cppflags) $(include) -c $(filter %.cc, $^) # define rule compiling other cpp sources $(objects): $(sources) $(proto_object) $(cxx) $(cppflags) $(include) -c $(filter %.cpp, $^) # define rule linking final executable $(output): $(objects) $(proto_object) $(cxx) $(cflags) -o $@ $^ ${lib} clean: rm -f *.o *.~ *.bak *.pb.* rm -f $(output)
however command lines executed make follow (for example):
protoc a.proto b.proto g++ -c a.pb.cc b.pb.cc g++ -c x.cpp y.cpp z.cpp g++ -o output a.o b.o x.o y.o z.o
sometime works well. but if sources many, cost lot of time recompile unchanged sources. example, modified a.proto
, makefile recompile b.proto
.
my question is: how can make each source file compiled/generated separately. executed command lines should be:
protoc a.proto protoc b.proto g++ -c a.pb.cc -o a.o g++ -c b.pb.cc -o b.o g++ -c x.cpp -o x.o g++ -c y.cpp -o y.o g++ -c z.cpp -o z.o g++ -o output a.o b.o x.o y.o z.o
thanks in advanced.
you make mistake of having rules working on complete lists instead of individual files, taking away make
's ability work on individual files.
your generation rules:
# define rule generating proto's cpp sources $(proto_cppsrc) : $(proto_sources) $(protoc) --cpp_out=. $(filter %.proto, $^) # define rule compiling generated proto cpp sources $(proto_object) : $(proto_cppsrc) $(cxx) $(cppflags) $(include) -c $(filter %.cc, $^)
instead, make rules work on individual files.
# define rule generating proto's cpp sources %.pb.cc: %.proto $(protoc) --cpp_out=. $< # define rule compiling generated proto cpp sources %.pb.o: %.pb.cc $(cxx) $(cppflags) $(include) -c $< -o $@
the same goes c++ sources:
# define rule compiling other cpp sources $(objects): $(sources) $(proto_object) $(cxx) $(cppflags) $(include) -c $(filter %.cpp, $^)
(why $(proto_object)
included in dependencies? looks very wrong me.)
again, switch work on individual files instead of whole lists:
# define rule compiling other cpp sources %.o: %.cpp $(cxx) $(cppflags) $(include) -c $< -o $@
only final target needs full list of objects:
# define rule linking final executable $(output): $(objects) $(proto_object) $(cxx) $(cflags) -o $@ $^ ${lib}
drop proto_cppsrc
, not needed.
now, make
@ last rule, find object dependencies, , apply single-file rule on each object needs rebuilding.
unrelated question, while you're @ it, add following statement makefile:
.phony: clean
this make "all" , "clean" run always, even if file name exists. not problem, when happens, can confusing heck. ;-)
Comments
Post a Comment