#build-process #build-automation #cmake #autotools #antlr3
#сборка-процесс #сборка-автоматизация #cmake #autotools #antlr3
Вопрос:
Это моя первая попытка с cmake, и я хотел бы, по возможности, получить некоторые отзывы о том, что я сделал, поскольку некоторые проблемы остаются.
В CMakeLists.txt из папки library я создал два целевых файла makefile: configure-antlr3c
и antlr3c
. Первая цель запускает сценарий оболочки настройки autotools, вторая запускает исполняемый файл make для сборки библиотеки:
# CMakeLists.txt in libantlr3c-3.1.3
add_custom_target(
configure-antlr3c
${SHELL_EXECUTABLE} configure
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_target(
antlr3c
${MAKE}
DEPENDS configure-antlr3c
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
Основная проблема заключается в том, что configure-antlr3c
цель всегда «устарела», поэтому она всегда будет выполняться, даже если никаких изменений не произошло. Более того, мне обязательно нужно сгенерировать мои make-файлы cmake в отдельном каталоге (не в корневом каталоге моего проекта), чтобы избежать переопределения Make-файла autotools библиотеки…
У кого-нибудь была эта проблема (создание проектов autotools с помощью cmake)? И если да, то каковы были ваши решения?
Спасибо.
РЕДАКТИРОВАТЬ: Решение в корне CMakeLists.txt:
include(ExternalProject)
ExternalProject_Add(
libantlr3c
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3/configure --prefix=${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/lib/libantlr3c-3.1.3
BUILD_COMMAND make
BUILD_IN_SOURCE 1
)
Комментарии:
1. Вы должны добавить свое решение в блок ответов, а не в вопрос.
Ответ №1:
Я думаю, что вам было бы лучше использовать функцию ExternalProject cmake. Я полагаю, у вас есть свой проект и libantrl в подкаталоге?
project
- libantlr
- mysrc
---- etc ----
Если это так, вы можете сделать что-то подобное на верхнем уровне CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(test)
include(ExternalProject)
ExternalProject_Add(libantlr
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libantlr
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/libantlr/configure --prefix=<INSTALL_DIR>
BUILD_COMMAND ${MAKE})
<INSTALL_DIR>
Расширен до чего-то вроде libantlr-prefix , поэтому все устанавливается в вашем дереве сборки, а не в / usr / local, что autotools сделал бы без префикса.
Комментарии:
1. Идеально! И это позволяет отслеживать тот факт, что я только что скомпилировал ее, и мне не нужно создавать ее каждый раз, когда у меня возникает зависимость. Большое спасибо 😉
2. Хороший ответ. Просто примите во внимание, что для «configure» требуется абсолютный путь для «—prefix».
3. Похоже, что при сборке внешнего проекта используется неправильный компилятор. По крайней мере, в цепочке инструментов mbed.
Ответ №2:
Мне нужно было сделать что-то подобное, но оказалось на удивление сложно получить рабочее решение, несмотря на приведенный здесь пример с принятым ответом и фрагменты кода, предоставленные в нескольких других сообщениях в блоге, архивы службы поддержки CMake по электронной почте listserv и т.д. В интересах других, кто сталкивается с этим вопросом, вот мое решение.
Внешний проект, который мы хотели использовать, является libmodbus
, хотя я считаю, что мое решение достаточно общее, чтобы работать с любым проектом, сконфигурированным по стандартному autoconf
рецепту ./autoconf.sh amp;amp; configure.sh amp;amp; make amp;amp; make install
.
Мы хотели добавить libmodbus
в качестве подмодуля нашего репозитория git. Мы добавили в наш репозиторий по пути <root>/opt/libmodbus
. CMake
Код для ее настройки находится в <root>/cmake/modbus.cmake
, который включен из нашего корневого каталога CMakeLists.txt
с использованием
# libmodbus
include(cmake/modbus.cmake)
Содержимое cmake/modbus.cmake
является:
include(ExternalProject)
set(MODBUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opt/libmodbus)
set(MODBUS_BIN ${CMAKE_CURRENT_BINARY_DIR}/libmodbus)
set(MODBUS_STATIC_LIB ${MODBUS_BIN}/lib/libmodbus.a)
set(MODBUS_INCLUDES ${MODBUS_BIN}/include)
file(MAKE_DIRECTORY ${MODBUS_INCLUDES})
ExternalProject_Add(
libmodbus
PREFIX ${MODBUS_BIN}
SOURCE_DIR ${MODBUS_DIR}
DOWNLOAD_COMMAND cd ${MODBUS_DIR} amp;amp; git clean -dfX amp;amp; ${MODBUS_DIR}/autogen.sh
CONFIGURE_COMMAND ${MODBUS_DIR}/configure --srcdir=${MODBUS_DIR} --prefix=${MODBUS_BIN} --enable-static=yes --disable-shared
BUILD_COMMAND make
INSTALL_COMMAND make install
BUILD_BYPRODUCTS ${MODBUS_STATIC_LIB}
)
add_library(modbus STATIC IMPORTED GLOBAL)
add_dependencies(modbus libmodbus)
set_target_properties(modbus PROPERTIES IMPORTED_LOCATION ${MODBUS_STATIC_LIB})
set_target_properties(modbus PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${MODBUS_INCLUDES})
Компонент, который использует libmodbus
, может объявить свою зависимость как обычно:
add_executable(hello_modbus main.cpp)
target_link_libraries(hello_modbus modbus)
Несколько замечаний:
- Это злоупотребляет
DOWNLOAD_COMMAND
выполнениемautogen.sh
шага.git clean -dfX
Вероятно, в этом нет необходимости (это остаток от более ранней версии, в которой использовалась этаBUILD_IN_SOURCE
опция. Если вы действительно хотите загрузить код вместо использования подмодуля git, вам нужно соответствующим образом изменить эту строку. - Мы берем на себя труд принудительно выполнить статическую сборку библиотеки. Настройте
configure
командную строку, если вам нужны общие библиотеки. set_target_properties
Команда для установкиIMPORTED_LOCATION
завершится ошибкой безBUILD_BYPRODUCTS ${MODBUS_STATIC_LIB}
объявления.- Аналогично,
set_target_properties
команда для установкиINTERFACE_INCLUDE_DIRECTORIES
завершится ошибкой безfile(MAKE_DIRECTORY ${MODBUS_INCLUDES})
.
Комментарии:
1. Я случайно заключил строку после
CONFIGURE_COMMAND
в кавычки, и это не сработало. Потребовалось некоторое время, чтобы разобраться с этим.2. Обратите внимание, что можно было бы передавать дополнительные команды после,
CONFIGURE_COMMAND
выполнивCOMMAND ls
и аналогичные после*_COMMAND
.