Makefile для многих исполняемых файлов c ++ - PullRequest
0 голосов
/ 14 февраля 2019

Я работаю над проектом, в котором мне постоянно нужно создавать новые исполняемые файлы c ++.Все они основаны на общих заголовочных файлах и исходных файлах, поэтому мне интересно, как упростить компиляцию и написание Makefile.Лучшее, что я придумал, это что-то вроде этого:

file1: $(BUILDDIR)/$@.o $(COMMON_OBJECTS) $(COMMON_LIBS)
    $(CCCOM) $(CCFLAGS) $(BUILDDIR)/$@.o $(COMMON_OBJECTS) -o $(BINDIR)/$@ $(LIBFLAGS)

, а затем мне нужно скопировать эту цель для каждого исполняемого файла, который я хочу добавить.В идеале я хочу определить это правило один раз для произвольной цели, а затем просто вызвать make any_file_name.

Возможно ли что-то подобное?Как люди организуют проект C ++ с большим количеством исполняемых файлов?(Я новичок в C ++ и пришел из Python, что очень естественно)

Ответы [ 3 ]

0 голосов
/ 14 февраля 2019

Вот пример файла makefile с автоматической генерацией зависимости заголовка для вас:

BUILD := debug
BUILD_DIR := ${BUILD}

CXX := g++

cppflags.debug :=
cppflags.release := -DNDEBUG
cppflags := ${cppflags.${BUILD}} ${CPPFLAGS}

cxxflags.debug :=
cxxflags.release := -O3
cxxflags := ${cxxflags.${BUILD}} ${CXXFLAGS}

ldflags := ${LDFLAGS}
ldlibs := ${LDLIBS}

exes := # Executables to build.

### Define executables begin.

exes += exe1
exe1.obj := exe1.o

exes += exe2
exe2.obj := exe2.o

### Define executables end.

all : ${exes:%=${BUILD_DIR}/%}

.SECONDEXPANSION:

${BUILD_DIR}:
    mkdir -p $@

# Rule to link all exes.
${exes:%=${BUILD_DIR}/%} : ${BUILD_DIR}/% : $$(addprefix ${BUILD_DIR}/,$${$$*.obj}) | $${@D}
    ${CXX} -o $@ ${ldflags} $^ ${ldlibs}

# Rule to compile C sources. And generate header dependencies.
${BUILD_DIR}/%.o : %.cc | $${@D}
    ${CXX} -o $@ -c ${cppflags} ${cxxflags} -MD -MP $<

# Include automatically generated header dependencies.
ifneq ($(MAKECMDGOALS),clean)
-include $(foreach exe,${exes},$(patsubst %.o,${BUILD_DIR}/%.d,${${exe}.obj}))
endif

clean:
    rm -rf $(BUILD_DIR)

.PHONY: all clean

Пример использования:

$ cat exe1.cc 
#include <iostream>
int main() { std::cout << "Hello, world!\n"; }

$ cat exe2.cc 
#include <iostream>
int main() { std::cout << "Hello, world!\n"; }

$ make
mkdir -p debug
g++ -o debug/exe1.o -c     -MD -MP exe1.cc
g++ -o debug/exe1  debug/exe1.o 
g++ -o debug/exe2.o -c     -MD -MP exe2.cc
g++ -o debug/exe2  debug/exe2.o 

$ make BUILD=release 
mkdir -p release
g++ -o release/exe1.o -c -DNDEBUG  -O3  -MD -MP exe1.cc
g++ -o release/exe1  release/exe1.o 
g++ -o release/exe2.o -c -DNDEBUG  -O3  -MD -MP exe2.cc
g++ -o release/exe2  release/exe2.o 

$ make clean
rm -rf debug

$ make BUILD=release clean
rm -rf release
0 голосов
/ 14 февраля 2019

Чтобы упростить все, я предполагаю, что у вас есть источники file1.cpp, file2.cpp и так далее, и все ваши файлы находятся в одном каталоге.Тогда Makefile фрагмент ниже будет делать то, что вы хотите:

all: $(basename $(wildcard file?.cpp))

file%: file%.cpp

Чтобы сделать все:

make all

Чтобы сделать file1:

make file1

Длясделать file1 и file2:

make file1 file2
0 голосов
/ 14 февраля 2019

Вы можете сделать так, чтобы каждый исполняемый файл соответствовал одному .cpp файлу в каталоге (например, executables/foo.cpp, executables/bar.bpp), а затем работать оттуда - это спасет васот необходимости прикасаться к Makefile каждый раз, когда вы добавляете еще одну.

Возможно, вам также следует настроить свой проект для создания общей библиотеки, на которую ссылаются (облегченные) исполняемые файлы.(Исполняемые файлы фактически просто выполняют некоторый синтаксический анализ командной строки и выгружают реальную работу в библиотечные функции.) Таким образом, вы не получите код из этих $(COMMON_OBJECTS), реплицируемых в каждом исполняемом файле.

...