Создание библиотеки с использованием autotools из cmake

#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)
  

Несколько замечаний:

  1. Это злоупотребляет DOWNLOAD_COMMAND выполнением autogen.sh шага. git clean -dfX Вероятно, в этом нет необходимости (это остаток от более ранней версии, в которой использовалась эта BUILD_IN_SOURCE опция. Если вы действительно хотите загрузить код вместо использования подмодуля git, вам нужно соответствующим образом изменить эту строку.
  2. Мы берем на себя труд принудительно выполнить статическую сборку библиотеки. Настройте configure командную строку, если вам нужны общие библиотеки.
  3. set_target_properties Команда для установки IMPORTED_LOCATION завершится ошибкой без BUILD_BYPRODUCTS ${MODBUS_STATIC_LIB} объявления.
  4. Аналогично, set_target_properties команда для установки INTERFACE_INCLUDE_DIRECTORIES завершится ошибкой без file(MAKE_DIRECTORY ${MODBUS_INCLUDES}) .

Комментарии:

1. Я случайно заключил строку после CONFIGURE_COMMAND в кавычки, и это не сработало. Потребовалось некоторое время, чтобы разобраться с этим.

2. Обратите внимание, что можно было бы передавать дополнительные команды после, CONFIGURE_COMMAND выполнив COMMAND ls и аналогичные после *_COMMAND .