如何在我的项目中链接 re2 库,就像使用 cmake 的静态库一样

Posted

技术标签:

【中文标题】如何在我的项目中链接 re2 库,就像使用 cmake 的静态库一样【英文标题】:how to link re2 library in my project like a static library with cmake 【发布时间】:2017-01-20 12:32:51 【问题描述】:

我的问题:此时我正在动态链接 libre2,但我想静态地执行此操作。我在我的电脑上安装了这个库(sudo apt-get install libre2-dev),得到了“二进制”并将这个二进制“libre2.so”链接到我的可执行文件中。但我想 git clone 存储库或通过 git submodule 执行此操作,然后构建此存储库并将其静态链接到我的项目中。

我是新来的,很抱歉我的英语 rss 不好

1) 我的项目结构

- bin
- build
- external
    - re2
- main.cpp
- CMakeLists.txt
- README.md  

2) CMakeLists.txt

cmake_minimum_required( VERSION 2.6 )

project( simmc-agent )

# version number  
set ( VERSION_MAJOR 0 )  
set ( VERSION_MINOR 0 )  

# cpr requires c++11  
set ( CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++11" )  

# src : main   
file ( GLOB SOURCES *.cpp )  

# linking res library dinamically  
set(RE2_LIBRARIES -L$RE2_LIBRARY_DIR -l libre2.so)  

# src : collect functions - depend on OS  
if ( WIN32 )  
    file ( GLOB SOURCES $SOURCES src/windows/*.cpp )  
else ()     # if( UNIX )  
    file ( GLOB SOURCES $SOURCES src/linux/*.cpp )  
endif ()  

# headers  
include_directories ( "include" )  

# test   
option( PRINT_JSON "Set to ON to print json objects before sending" OFF )  
message(STATUS "$PRINT_JSON: $$PRINT_JSON")  
if ( PRINT_JSON )  
    add_definitions ( -DPRINT_JSON )  
endif ()  

# compile
set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin" )
add_executable ( agent-v$VERSION_MAJOR.$VERSION_MINOR $SOURCES )  
target_link_libraries ( agent-v$VERSION_MAJOR.$VERSION_MINOR $RE2_LIBRARY )

3) main.cpp

#include <iostream>     
#include <re2/re2.h>

using namespace std;  
using namespace re2;

int main (int argc, char **argv)   
    cout << "hello world" << endl;

 int matchResult;

 matchResult = RE2::FullMatch("hello", "h.*o"); 
 cout << "matchResult = " << matchResult << endl;  

   return 0;  


【问题讨论】:

要下载和构建 re2,您可以使用ExternalProject_Add()。您可以通过查看以下两个文件来查看您的案例示例:https://github.com/project-z/mutton/blob/master/ext/re2.cmake 和 https://github.com/petewarden/tensorflow_makefile/blob/master/tensorflow/contrib/cmake/external/re2.cmake,它们也使用静态库。 感谢您帮助我。我回家后试试。之后,我会给出反馈。 嘿...我测试了它,我有一些问题:“无法满足-lexternal/re2/src/RE2/obj/so/libre2.so” 执行“cmake ..”、“external/re2/src/RE2/obj/so/libre2.so”,库就满足了。但是,执行“make”命令,出现以下错误:'"/usr/bin/ld: it was not possible to meet -lexternal/re2/src/re2/obj/so/libre2.so"。可以看出该库一直在动态链接。我很抱歉我的英语不太好。 我不明白。您是否使用了 re2.cmake? 【参考方案1】:

编辑 - (26.01.17):大家好。我在这里谈谈我如何解决它。 按照此处给出的一些提示,我创建了一个名为 re2.cmake 的文件:

cmake_minimum_required ( VERSION 2.8.7 )

if (NOT RE2_NAME)

include (ExternalProject)

SET (RE2_INCLUDE_DIRS $CMAKE_CURRENT_BINARY_DIR/re2/src/re2/)
SET (RE2_EXTRA_INCLUDE_DIRS $CMAKE_CURRENT_BINARY_DIR/re2/src/re2/)
SET (RE2_URL https://github.com/google/re2.git)
SET (RE2_BUILD $CMAKE_BINARY_DIR/re2/src/re2)  
SET (RE2_LIBRARIES $RE2_BUILD/obj/so/libre2.so)
get_filename_component(RE2_STATIC_LIBRARIES $RE2_BUILD/libre2.a ABSOLUTE)  
SET (RE2_INCLUDES $RE2_BUILD)

if ( WIN32 )   
  SET (RE2_STATIC_LIBRARIES $RE2_BUILD/$CMAKE_BUILD_TYPE/re2.lib) 
else ()   
  SET (RE2_STATIC_LIBRARIES $RE2_BUILD/libre2.a) 
endif ()

ExternalProject_Add(RE2      
  PREFIX RE2      
  GIT_REPOSITORY $RE2_URL      
  # GIT_TAG $RE2_TAG      
  DOWNLOAD_DIR "$DOWNLOAD_LOCATION"      
  BUILD_IN_SOURCE 1      
  INSTALL_COMMAND sudo make install     
   CMAKE_CACHE_ARGS         
    -DCMAKE_BUILD_TYPE:STRING=Release          -DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF          -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON  
)

 ## put re2 includes in the directory where they are expected  
 add_custom_target(re2_create_destination_dir COMMAND $CMAKE_COMMAND -E make_directory $RE2_INCLUDE_DIR/re2 DEPENDS re2)   

 add_custom_target(re2_copy_headers_to_destination DEPENDS re2_create_destination_dir)   

 foreach(header_file $RE2_HEADERS)      
    add_custom_command(TARGET re2_copy_headers_to_destination PRE_BUILD COMMAND $CMAKE_COMMAND -E copy $header_file $RE2_INCLUDE_DIR/re2)  
  endforeach ()   

  ADD_LIBRARY(RE2_LIB STATIC IMPORTED DEPENDS RE2)  
  SET_TARGET_PROPERTIES(RE2_LIB PROPERTIES IMPORTED_LOCATION $RE2_STATIC_LIBRARIES)

endif (NOT RE2_NAME)

此文件下载存储库,在我的计算机中构建并安装库 libre2。这个库依赖于 Thread 库*(我认为所有的 linux 操作系统都带有这个库)。

但是,有一个问题:如果我是 root 用户,我只会这样做。因为该库使用“make install”命令并且要执行此操作,所以您需要是 root 用户。

我的项目结构:

- bin
- build
- src
- include
- modules
    - re2.cmake
- CMakeLists.txt

按照我的 CMakeLists.txt:

cmake_minimum_required ( VERSION 2.8.7 )

project ( project C CXX)

# version number
SET ( VERSION_MAJOR 0 )
SET ( VERSION_MINOR 0 )

SET ( CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++11" )

# src : main
file ( GLOB SOURCES src/main.cpp )

# headers
include_directories ( "include" )

# src : libre2 - Download, build and install the library

find_package (Threads)

include ( "modules/re2.cmake" )
set(RE2_STATIC_LIBRARIES -L$RE2_LIBRARY_DIR -l libre2.a )

# compile 
set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin" )
add_executable ( project-v$VERSION_MAJOR.$VERSION_MINOR $SOURCES)
target_link_libraries ( project-v$VERSION_MAJOR.$VERSION_MINOR $RE2_STATIC_LIBRARIES)

add_dependencies(project-v$VERSION_MAJOR.$VERSION_MINOR RE2)

target_link_libraries (project-v$VERSION_MAJOR.$VERSION_MINOR $CMAKE_THREAD_LIBS_INIT)

【讨论】:

【参考方案2】:

我的新CmakeLists.txt

cmake_minimum_required( VERSION 2.8.7 )

project( simmc-agent )

# version number
set ( VERSION_MAJOR 0 )
set ( VERSION_MINOR 0 )

# cpr requires c++11
set ( CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++11" )

# src : main
file ( GLOB SOURCES *.cpp )

# libre2

if (NOT RE2_NAME)

    include (ExternalProject)

    set(ABBREV "RE2")
    set(EXT_PREFIX "external/re2" )
    set($ABBREV_NAME         $ABBREV)
    set($ABBREV_INCLUDE_DIRS $EXT_PREFIX/src/re2/)
    set(APP_DEPENDENCIES $APP_DEPENDENCIES $ABBREV)

    message("Installing $RE2_NAME into ext build area: $EXT_PREFIX ...")

    ExternalProject_Add(RE2
      PREFIX $EXT_PREFIX
      URL https://re2.googlecode.com/files/re2-20130115.tgz
      URL_MD5 "ef66646926e6cb8f11f277b286eac579"
      PATCH_COMMAND ""
      CONFIGURE_COMMAND ""
      BUILD_COMMAND make
      INSTALL_COMMAND ""
      BUILD_IN_SOURCE 1
      )

    set(CXXFLAGS CMAKE_CXX_FLAGS)

    set($ABBREV_LIBRARIES $EXT_PREFIX/src/RE2/obj/so/libre2.so)
    set($ABBREV_STATIC_LIBRARIES $EXT_PREFIX/src/RE2/obj/libre2.a)

    set_target_properties($RE2_NAME PROPERTIES EXCLUDE_FROM_ALL ON)

  endif (NOT RE2_NAME)


if(RE2_INCLUDE_DIRS AND RE2_LIBRARIES)
  set(RE2_FOUND TRUE)
endif(RE2_INCLUDE_DIRS AND RE2_LIBRARIES)

if(RE2_FOUND)
  message(STATUS "Found RE2: $RE2_LIBRARIES")
else(RE2_FOUND)
  message(FATAL_ERROR "Could not find RE2 library.")
endif(RE2_FOUND)

set(INCLUDES $INCLUDES $RE2_INCLUDE_DIRS )
# set(LIBS $LIBS $RE2_STATIC_LIBRARIES )

# headers
include_directories ( "include" )

# test 
option( PRINT_JSON "Set to ON to print json objects before sending" OFF )
message(STATUS "$PRINT_JSON: $$PRINT_JSON")
if ( PRINT_JSON )
    add_definitions ( -DPRINT_JSON )
endif ()

# compile
set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin" )
add_executable ( agent-v$VERSION_MAJOR.$VERSION_MINOR $SOURCES )
target_link_libraries ( agent-v$VERSION_MAJOR.$VERSION_MINOR  $RE2_LIBRARIES)

【讨论】:

请将target_link_libraries ( agent-v$VERSION_MAJOR.$VERSION_MINOR $RE2_LIBRARIES) 替换为以下内容:target_link_libraries ( agent-v$VERSION_MAJOR.$VERSION_MINOR $RE2_STATIC_LIBRARIES)。那应该链接静态的!如果可行,我会写在答案中。 我成功了,但 continue 不起作用:/ 同样的错误:/usr/bin/ld: not possible to meet -lexternal/re2/src/re2/obj/libre2.a跨度>

以上是关于如何在我的项目中链接 re2 库,就像使用 cmake 的静态库一样的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 C++ 项目中链接本地安装的 SDK 的静态库?

使用 Cmake,如何防止库源包含在我的 IDE 中?

Visual Studio 2013 - 如何在我自己的库中链接/包含其他库

如何使用 cmake 链接 Python3 库?

如何将http C库正确包含到Android项目中?

如何强制 CMake 链接到系统库而不是同名目标