简体   繁体   English

使用 cmake 中的 autotools 构建库

[英]Building a library using autotools from cmake

This is my first try with cmake and I would like to have, if possible, some feedbacks about what I did since some problems remain.这是我第一次尝试 cmake,如果可能的话,我希望得到一些关于我所做的事情的反馈,因为一些问题仍然存在。

In the CMakeLists.txt of the library folder, I created two makefile targets: configure-antlr3c and antlr3c .在库文件夹的 CMakeLists.txt 中,我创建了两个 makefile 目标: configure-antlr3cantlr3c The first target runs the autotools configuration shell script, the second one runs the make executable to build the library:第一个目标运行 autotools 配置 shell 脚本,第二个目标运行 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}
)

The main problem is that configure-antlr3c target is always "out of date", so it will always be executed even if no changes happened.主要问题是configure-antlr3c目标始终“过时”,因此即使没有发生任何更改,它也会始终执行。 Moreover, I necessarily need to generate my cmake makefiles in a separate directory (not in the root directory of my project) to avoid overriding the autotools Makefile of the library...此外,我必须在单独的目录中生成我的 cmake 生成文件(而不是在我的项目的根目录中),以避免覆盖库的自动工具生成文件...

Has anyone had this problem (building autotools projects with cmake) ?有没有人遇到过这个问题(用 cmake 构建 autotools 项目)? And if so, what have been your solutions ?如果是这样,您的解决方案是什么?

Thank you.谢谢你。

EDIT : Solution In the root CMakeLists.txt:编辑:解决方案在根 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
)

I think that you'd be better off using the ExternalProject feature of cmake.我认为您最好使用 cmake 的ExternalProject功能。 I guess you have your project and have libantrl in a sub directory?我猜你有你的项目并且在子目录中有 libantrl ?

project
      +- libantlr
      +- mysrc
  ---- etc ----

If that's the case, you can do something like this in the top level CMakeLists.txt:如果是这种情况,您可以在顶级 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})

The <INSTALL_DIR> is expanded to something like libantlr-prefix, so things are installed in your build tree rather than in /usr/local, which is what autotools would do without a prefix. <INSTALL_DIR>被扩展为类似 libantlr-prefix 的东西,所以东西被安装在你的构建树中而不是 /usr/local 中,这是 autotools 在没有前缀的情况下所做的。

I needed to do something similar but found it surprisingly difficult to get a working solution, despite the example provided here with the accepted answer, and code snippets provided in several other blog posts, the CMake support email listserv archives, etc. For the benefit of others who come across this question, here is my solution.我需要做一些类似的事情,但发现获得一个有效的解决方案非常困难,尽管这里提供的示例提供了可接受的答案,以及其他几篇博客文章、CMake 支持电子邮件列表服务档案等中提供的代码片段。为了利益遇到这个问题的其他人,这是我的解决方案。

The external project we wanted to use is libmodbus , though I believe my solution is general enough to work with any project configured with the standard autoconf recipe of ./autoconf.sh && configure.sh && make && make install .我们想要使用的外部项目是libmodbus ,尽管我相信我的解决方案足够通用,可以与使用./autoconf.sh && configure.sh && make && make install的标准autoconf配方配置的任何项目一起使用。

We wanted to add libmodbus as a submodule of our git repository.我们想添加libmodbus作为我们 git 存储库的子模块。 We added to our repository at the path <root>/opt/libmodbus .我们在路径<root>/opt/libmodbus添加到我们的存储库。 The CMake code to configure it is located in <root>/cmake/modbus.cmake , which is included from our root CMakeLists.txt using配置它的CMake代码位于<root>/cmake/modbus.cmake ,它包含在我们的根CMakeLists.txt使用

# libmodbus
include(cmake/modbus.cmake)

The content of cmake/modbus.cmake is: 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} && git clean -dfX && ${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})

A component that uses libmodbus can declare its dependency as usual:使用libmodbus的组件可以像往常一样声明其依赖项:

    add_executable(hello_modbus main.cpp)
    target_link_libraries(hello_modbus modbus)

A few notes:一些注意事项:

  1. This abuses the DOWNLOAD_COMMAND to perform the autogen.sh step.这会滥用DOWNLOAD_COMMAND来执行autogen.sh步骤。 The git clean -dfX is probably not necessary (it is a leftover from an earlier version that used the BUILD_IN_SOURCE option. If you really want to download the code instead of using a git submodule, you'll need to modify this line appropriately. git clean -dfX可能不是必需的(它是使用BUILD_IN_SOURCE选项的早期版本的BUILD_IN_SOURCE 。如果你真的想下载代码而不是使用 git 子模块,你需要适当地修改这一行。
  2. We go to the trouble to force a static-only build of the library.我们不厌其烦地强制对库进行仅静态构建。 Adjust your configure command line if you want shared libraries.如果需要共享库,请调整configure命令行。
  3. The set_target_properties command to set the IMPORTED_LOCATION will fail without the BUILD_BYPRODUCTS ${MODBUS_STATIC_LIB} declaration.set_target_properties命令设置IMPORTED_LOCATION没有将失败BUILD_BYPRODUCTS ${MODBUS_STATIC_LIB}声明。
  4. Likewise, the set_target_properties command to set the INTERFACE_INCLUDE_DIRECTORIES will fail without the file(MAKE_DIRECTORY ${MODBUS_INCLUDES}) .同样,设置INTERFACE_INCLUDE_DIRECTORIESset_target_properties命令将在没有file(MAKE_DIRECTORY ${MODBUS_INCLUDES})情况下失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM