Generate object files in subdirectory using a Make

2019-08-23 10:36发布

问题:

I am trying to create a Makefile in order to generate object files in a subdirectory rather than let them in the src/ folder. Here is the structure of the project:

Trunk
- Server
  - src/
  - include/
- Common
  - src/
  - include/

The Makefile is located in Trunk/Server. Source files are located both in Server/src and Common/src, so the Makefile currently has something like this:

SRC        =        src/main.cpp                  \
                    src/Network.cpp               \
                    ../Common/src/SQLManager.cpp  \
                    ../Common/src/Utils.cpp

I woud like to put generated object files in respective obj folders, so Trunk/Server/obj and Trunk/Common/obj. How can I achieve this? I've found many ways to generate object files in subdirectories (vpath, patsubst and many more) but I can't make any of them work for this folder organization.

Edit: If there is a way to put all object files in Server/obj/, that would be ok too.

Here's the complete Makefile (minus some source files and linked libraries): Edit2: Updated with Didier Trosset's changes

CXX             =       g++

RM              =       rm -vf

NAME            =       Server

SRC             =       src/main.cpp                  \
                        src/Network.cpp               \
                        ../Common/src/SQLManager.cpp  \
                        ../Common/src/Utils.cpp

OBJ             =       $(subst src/,obj/, $(subst .cpp,.o, $(SRC)))

LDFLAGS         =       -lpthread -lm

CPPFLAGS        =       -std=c++0x -pedantic -Wextra -Wall -Wconversion -Iinclude -I../Common/include

all: Server

%.o: %.cpp
        $(CXX) $< -o $@

Server: $(OBJ)
        $(CXX) -o $(NAME) $(OBJ) $(LDFLAGS)

clean:
        $(RM) $(OBJ) *~

fclean: clean
        $(RM) $(NAME)

re: fclean Server

.PHONY: all clean fclean Server

回答1:

Given these definitions, subst should be used to substitute the src part of the directory, and the file extension.

OBJ = $(subst src/,bin/,$(subst .cpp,.o,$(SRC)))

Then, you have to add new pattern rules to compile your source files. (You have to write one pattern rule per directory where your source files are.)

obj/%.o: src/%.cpp
         $(CXX) -c $< -o $@

../Common/obj/%.o: ../Common/src/%.cpp
         $(CXX) -c $< -o $@


回答2:

I'm not sure that this will work, but I would try something like:

OBJ := $(join $(addsuffix ../obj/,$(dir $(SRC))),$(notdir $(SRC))
# or, as Didier suggested:
# OBJ := $(subst src/,obj/,$(SRC))

%.o: ../src/%.cpp
    $(CXX) $< -o $@


回答3:

It's not clear exactly what you're trying to do, but this should come close:

OBJ = $(subst src/,obj/,$(SRC:.cpp=.o))

obj/%.o : src/%.cpp
    $(CXX) $< -o $@

../Common/obj/%.o : ../Common/src/%.cpp
    $(CXX) $< -o $@