2016-09-27 3 views
0

Моя структура проекта выглядит следующим образом:Как закодировать makefile, когда исходные файлы находятся в разных каталогах?

. 
├── build 
│   ├── makefile 
└── src 
    ├── subsys1 
    │   ├── includes 
    │   └── src_1.cpp 
    └── subsys2 
     ├── includes 
     └── src_2.cpp 

Я написал Makefile построить исполняемый «MyApp» из приведенных выше исходных файлов:

print-% : ; @echo $* = $($*) 

# Application name 
APP := myapp 

# Set the directory to store the object files in 
OBJDIR_R = _gnuRelease 
OBJDIR_D = _gnuDebug 

# Names of compiler and linker, and their associated switches 
CXX:=g++ 
LINKER:=g++ 
CXXFLAGS+=-Wall -std=c++11 -pedantic -lpthread -m64 

ifeq ($(DEBUG),1) 
OBJDIR := $(OBJDIR_D) 
CXXFLAGS += -g 
else 
OBJDIR := $(OBJDIR_R) 
CXXFLAGS += -O2 
endif 

LDFLAGS = 

# Set the name of the output executable 
EXEFILE := LedaAP 

VPATH = ../src/subsys1 ../src/subsys2 

CPP_FILES = src_1.cpp src_2.cpp 

OBJ_FILES = $(patsubst %.cpp,%.o,$(CPP_FILES)) 

DEP_FILES = $(patsubst %.cpp,%.d,$(CPP_FILES)) 

INC_DIRS := ../src/subsys1/includes ../src/subsys2/includes 
INC_SWITCHES=$(foreach d, $(INC_DIRS), -I$d) 

# This default target builds the executable by linking the object files 
$(APP) : $(OBJ_FILES) 
    $(LINKER) $(CXXFLAGS) $^ -o [email protected] 

# A rule to build an .o file from a .cpp file 
%.o: %.cpp 
    $(CXX) $(CXXFLAGS) $(INC_SWITCHES) -c $< -o [email protected] 

# Running 'make clean' deletes the executables and all the libraries. 
.PHONY: clean 
clean: 
    @echo Deleting executables and libraries. Use make clean_exe to delete just the executables. 
    @rm -f $(OBJDIR_D)/$(EXEFILE) 
    @rm -f $(OBJDIR_R)/$(EXEFILE) 
    @rm -rf $(OBJDIR_D) 
    @rm -rf $(OBJDIR_R) 

В результате объектные файлы и исполняемые в сборке каталог:

build 
├── makefile 
├── myapp 
├── src_1.o 
└── src_2.o 

Я на самом деле хочу:

build 
├── _gnuRelease 
│   ├── myapp 
│   └── objects 
│    ├── src_1.o 
│    └── src_2.o 
└── makefile 

Как я мог это достичь?

+0

Привет, Дэвид, у меня был аналогичный вопрос некоторое время назад. Пожалуйста, проверьте это сообщение: http://stackoverflow.com/questions/39015453/building-c-program-out-of-source-tree-with-gnu-make –

+0

Спасибо, это очень полезное решение. – DavidA

ответ

0

Для линии: CPP_FILES = src_1.cpp src_2.cpp лучше поместить туда имена каталогов (то есть CPP_FILES = subsys1/src_1.cpp subsys2/src_2.cpp). Во-первых, это позволяет избежать проблем, если две подсистемы имеют файл с тем же именем, и, во-вторых, он упрощает ваш make-файл и упрощает его поддержку.

Если вы намерены делать что-то по-своему, добавьте каталог в OBJ_FILES: OBJ_FILES=$(SOURCE_FILES:%.cpp=$(OBJ_DIR)/%.o) и соответствующим образом измените правило шаблона: $(OBJ_DIR)/%.o : %.cpp, который поместит файлы .o в соответствующий каталог.

+0

Спасибо за ваш ответ. Я согласен, что лучше всего указывать каждый файл src с именем каталога. Тем не менее, моя трудность заключается в том, что для того, чтобы затем создать пути к файлу obj, мне нужно отключить каталог и заменить его на желаемый путь к файлу объекта. Итак, используя patsubst, как я могу удалить «../subsys1/» или «../subsys2/» и заменить OBJDIR? Тем более, что в реальном проекте у меня также есть некоторые файлы в «../../some_dir/». Можно ли использовать регулярные выражения? – user1768576

+0

@ user1768576: '$ (addprefix $ (OBJDIR) /, $ (notdir $ (SOURCE_FILES)))' – Beta

+0

Спасибо. Так что теперь у меня есть: 'CPP_FILES = ../src/subsys1/src_1.cpp ../src/subsys1/src_2.cpp OBJ_FILES_TMP = $ (. Patsubst% .cpp,% о, $ (CPP_FILES)) OBJ_FILES = $ (addprefix $ (OBJDIR) /, $ (notdir $ (OBJ_FILES_TMP))), но мое правило зависимостей по-прежнему: '% .o:% .cpp \t $ (CXX) $ (CXXFLAGS) $ (INC_SWITCHES) - c $ <-o $ @ ', поэтому, когда я запускаю make, я получаю' no rule, чтобы сделать target_gnuRelease/src_1.o необходимым для myapp'. Как изменить это правило зависимостей, чтобы справиться с изменением пути? – DavidA

Смежные вопросы