akrasuski1
akrasuski1

Reputation: 840

Is there a way to create makefile that uses only required .o files?

I want to create a makefile that compiles more than one program at once. There may be some .cpp files that are used by all of them, and some .cpp files that are used by just one exclusively. The current makefile I have is following:

CPPFLAGS = -std=c++14 -MMD -pthread 
TARGETS = server.cpp client.cpp

SRC = $(wildcard *.cpp)
NON_TARGET_SRC = $(filter-out $(TARGETS),$(SRC))

all: $(TARGETS:%.cpp=%)

clean:
    rm -rf *.o
    rm -rf *.d

$(TARGETS:%.cpp=%): % : $(NON_TARGET_SRC:%.cpp=%.o) %.o ###redundant?
    g++ $(CPPFLAGS) -o $@ $^

-include $(SRC:%.cpp=%.d)

Server.cpp and client.cpp are names of files that contain main() function and are supposed to be compiled to executable, rather than .o file. While the above makefile works, I think it does work that is redundant, as it does the final compilation with using all the non-target .o files, while it probably should use only the needed ones (or does the linker pick the needed ones on itself, making such a command's overhead negligible?). So, the question is:

Is there a way to list .o files that are required by specific program?

EDIT:

The following code seems to work just fine, thanks to packing all the object files into one library file.

CPPFLAGS = -std=c++14 -MMD -pthread 
TARGETS = server.cpp client.cpp

LIBRARY_NAME=objects
LIBRARY_FILE=lib$(LIBRARY_NAME).a
SRC = $(wildcard *.cpp)
NON_TARGET_SRC = $(filter-out $(TARGETS),$(SRC))
LDFLAGS = -L.
LDLIBS = -l$(LIBRARY_NAME)

all: $(TARGETS:%.cpp=%)

clean:
    rm -rf *.o
    rm -rf *.d
    rm -rf *.a

$(TARGETS:%.cpp=%): % : $(LIBRARY_FILE) %.o
    g++ $(CPPFLAGS) -o $@ $*.o $(LDFLAGS) $(LDLIBS)

$(LIBRARY_FILE): $(NON_TARGET_SRC:%.cpp=%.o)
    ar rcu $@ $(NON_TARGET_SRC:%.cpp=%.o)
    ranlib $@

-include $(SRC:%.cpp=%.d)

Upvotes: 0

Views: 911

Answers (2)

Dietmar Kühl
Dietmar Kühl

Reputation: 153820

The way to do that is to build all object files except those with a main() function into a library and link with the library. Building a library is something like this:

libfoo.a: $(LIBOFILES)
    ar rcu $@ $(LIBOFILES)
    ranlib $@

You'd then also set the Makefile to use the library:

LDFLAGS = -L.
LDLIBS  = -lfoo

Upvotes: 2

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

"Is there a way to list .o files that are required by specific program?"

Yeah. List them (or at least the required sources, and substitute) manually.

Also directory search functions could come in handy, but that depends on how your project structure actually looks like.

The easiest way IMHO, is to bundle .o files to libraries, the linker will automatically pick what's actually needed for the specific TARGETS.

Upvotes: 0

Related Questions