Я использую cmake для сборки своего проекта. Для UNIX я хотел бы набрать make из корневого каталога моего проекта и вызвать cmake для создания правильных файлов Makefile (если они еще не существуют), а затем построить свой проект. Я бы хотел, чтобы «внутренние» файлы cmake (объектные файлы, внутренние Make-файлы cmake и т. д.) Были скрыты (например, помещены в каталог .build), чтобы они не загромождали каталог моего проекта.
В моем проекте есть несколько подпроектов (в частности, библиотека, исполняемый файл пользователя и исполняемый файл модульного теста). Я хотел бы, чтобы Makefiles (т.е. я набираю make, и это происходит) для каждого подпроекта, чтобы выполнить cmake (как указано выше) и построить только этот подпроект (с зависимостями, чтобы библиотека была построена из Makefiles исполняемых файлов, если необходимо ). Полученный двоичный файл (библиотека .so или исполняемый файл) должен находиться в каталоге подпроекта.
Я сделал Makefile, который неплохо справляется с основным проектом, хотя и выглядит несколько хакерским. Я не могу создавать с его помощью определенные цели, потому что мой Makefile просто вызывает make в каталоге сборки cmake.
Обратите внимание: поскольку библиотека является единственной зависимостью (и, вероятно, ее не нужно собирать вручную, и из-за того, что я ленив), я пропустил ее в моем Makefile.
BUILD_DIR := .build
.PHONY: all clean project-gui ${BUILD_DIR}/Makefile
all: project-gui project-test
clean:
@([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean && rm -r ${BUILD_DIR}) || echo Nothing to clean
project-gui: ${BUILD_DIR}/Makefile
@make -C ${BUILD_DIR} project-gui
@cp ${BUILD_DIR}/project-gui/project-gui $@
project-test: ${BUILD_DIR}/Makefile
@make -C ${BUILD_DIR} project-test
@cp ${BUILD_DIR}/project-test/project-test $@
${BUILD_DIR}/Makefile:
@[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}
@[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CMAKE_OPTS} ..)
Если это поможет, вот моя структура проекта (если это «неправильно», скажите, пожалуйста, я все еще изучаю cmake):
project/
project/CMakeLists.txt
project/common.cmake
project/Makefile -- see Makefile above for this; should be replaced with something better, building libproject, project-gui, and project-test
project/libproject/
project/libproject/CMakeLists.txt
project/libproject/libproject.so -- after build
project/libproject/Makefile -- doesn't exist yet; should build libproject only
project/libproject/source/
project/libproject/include/
project/project-gui/
project/project-gui/CMakeLists.txt
project/project-gui/Makefile -- doesn't exist yet; should build libproject then project-gui
project/project-gui/source/
project/project-gui/include/
project/project-test/
project/project-test/CMakeLists.txt
project/project-test/Makefile -- doesn't exist yet; should build libproject then project-test
project/project-test/source/
project/project-test/include/
Если вы еще не поняли, я в основном ищу способ собрать проект и подпроекты, как если бы cmake не было: как если бы мой проект состоял только из Makefiles. Можно ли это сделать? Решение элегантное или беспорядочное? Должен ли я вместо этого попытаться сделать что-нибудь еще?
Спасибо!





Если cmake генерирует make-файлы, вы можете просто включить сгенерированный make-файл в главный make-файл, например
# makefile
all: # Default
include $GENERATED
$GENERATED:$CMAKEFILE
# Generate the makefile here`
Включенные файлы генерируются, затем make перезапускается с новыми включенными файлами. Включенные файлы должны подробно описывать цели и т. д.
Вы должны иметь возможность изменять расположение используемых файлов с помощью директивы vpath, см., Например, GNU сделать руководство,
vpath %.o project/.build
иначе утомительный способ - переписать правила, отметив необходимый каталог.
Эд: Возможно, нам не следует использовать простой make-файл.
Попробуйте что-нибудь вроде:
# makefile
all: gui test
clean:
$(MAKE) -f $(GUI-MAKE) clean
$(MAKE) -f $(TEST-MAKE) clean
gui:$(GUI-MAKE)
$(MAKE) -f $(GUI-MAKE) all
$(GUI-MAKE):$(GUI-CMAKE)
# Generate
# Same for test
Это должно работать, если команда $ (MAKE) -f $ (GUI-MAKE) all работает в командной строке, и мы скрыли cmake в целевой генерации. Вам также придется скопировать любые другие цели в главный make-файл и позаботиться о параллельном запуске make.
Распространение объектных файлов должно включать что-то вроде
%.o:$(GUI-MAKE)
$(MAKE) -f $(GUI-MAKE) $@
хотя вы, вероятно, получите ошибки, пытаясь сделать тестовые объекты
Я не думаю, что вы можете изменить рабочий каталог между правилами, однако я добавил примечание о vpath, которое должно позволить вам найти ваши объектные файлы и т. д. В правильном месте.
Я получаю следующую ошибку без vpath: make [1]: CMakeFiles / Makefile2: Нет такого файла или каталога. Это вызвано вызовом Makefile, созданного cmake: $ (MAKE) -f CMakeFiles / Makefile2 all. CMakeFiles - это подкаталог в моем каталоге сборки. [продолжение ...]
[...] Я пробовал использовать vpath следующими способами: VPATH = $ {BUILD_DIR} в верхней части моего Makefile, а также экспорт VPATH = $ {BUILD_DIR}. Ни один из них не работал (такая же ошибка). Затем я попробовал: vpath CMakeFiles /% $ {BUILD_DIR}. Опять же, без изменений. Я неправильно использую директиву? Должен ли я вставить Makefile cmake?
Конечно. Я предполагаю, что makefile cmake отлично работает из своего собственного каталога, и что запуск make -f CMakeFiles / Makefile2 из основного каталога makefile дает ту же ошибку?
@cramsin, это правильно. Запуск из pwd = $ {BUILD_DIR} работает нормально, как и ожидалось. Это то, что делал мой старый Makefile.
Ваше обновление в значительной степени то, что у меня есть сейчас. Я хотел бы иметь возможность создавать конкретные цели, например конкретные файлы .o, если это возможно. Решение include кажется близким. Если бы только есть способ временно изменить текущий рабочий каталог ...
Каждая «команда» в make-файле запускается в отдельной оболочке, поэтому все, что вам нужно сделать, это дать одну команду, которая изменяет каталоги, а затем что-то запускает. target: deps (cd $ DIR; $ (MAKE) target) Вы также можете посмотреть на флаг -C, чтобы сделать
Ух ты! Я даже не подумал об этом! Однако есть одна проблема: включенный Makefile ($ GENERATED) ожидает другой pwd / $ CUR_DIR, чем каталог проекта (он думает, что он находится в project / .build). Как это исправить?