Вызовите cmake из make, чтобы создать Makefiles? - PullRequest
15 голосов
/ 02 января 2009

Я использую cmake для создания своего проекта. Для UNIX я хотел бы набрать make из корневого каталога моего проекта и вызвать cmake, чтобы создать надлежащие файлы Makefile (если они еще не существуют), а затем собрать мой проект. Мне бы хотелось, чтобы cmake «внутренние» файлы (объектные файлы, cmake внутренние файлы Makefile и т. Д.) Были скрыты (например, помещены в каталог .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. Можно ли это сделать? Решение элегантное или грязное? Должен ли я пытаться сделать что-то еще вместо этого?

Спасибо!

1 Ответ

8 голосов
/ 02 января 2009

Если cmake генерирует make-файлы, вы можете просто включить сгенерированный make-файл в основной make-файл, например,

# makefile
all:                # Default
include $GENERATED
$GENERATED:$CMAKEFILE
   #  Generate the makefile here`

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

Вы должны иметь возможность изменять расположение используемых файлов с помощью директивы vpath, см., Например, Gnu делает руководство ,

vpath %.o project/.build

В противном случае утомительный способ состоит в том, чтобы переписать правила, отмечая необходимый каталог.

Ed: Возможно, нам не следует использовать плоский 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) работает в командной строке, и мы скрыли cmake в генерирующей цели. Вам также нужно будет скопировать любые другие цели в основной make-файл и позаботиться о запуске make параллельно.

Распространение объектных файлов должно включать что-то вроде

%.o:$(GUI-MAKE)
    $(MAKE) -f $(GUI-MAKE) $@

хотя вы, вероятно, получите ошибки при попытке сделать тестовые объекты

...