2

我是 CMake 的新手,我正在尝试编译我的项目。该项目创建了一些静态库和一些可执行文件。

下面是我拥有的文件结构的示例。

项目

  • SRC

    1. subProject_1
      .cpp(所有源文件)和 CMakeLists.txt 1 用于此文件夹(创建静态库)
    2. subproject_2
      .cpp(所有源文件)和 CMakeLists.txt 2 用于此文件夹(创建静态库)
    3. subproject_3
      .cpp(所有源文件)和 CMakeLists.txt 3 用于此文件夹(创建可执行文件)
  • 包括

    1. subProject_1
      .h(所有头文件)
    2. subProject_2
      .h(所有头文件)
    3. subProject_3
      .h(所有头文件)
  • 构建/Linux

    1. CMakeLists.txt(主 CMakelist 文件)

主 CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
SET(CMAKE_CXX_COMPILER "g++")
Project(ort)
SET (CMAKE_CXX_FLAGS " -g -Wall -pThread")

#set the source and header directories location
set(ORT_HEADER_DIRECTORY "../../include") #include folder structure explained above
set(ORT_SOURCE_DIRECTORY "../../src")
set(ORT_BINARY_DIRECTORY "../../lib")  # lib folder to contain all the libraries

set (CMAKE_CURRENT_BINARY_DIR ".")

#Include the library packages
include_directories("/usr/include/wx-2.8")
include_directories("/usr/local/cuda/include") and so on


#set the names of all the projects (for creating the libraries)
SET(PROJECT_NAMES "log" "data" "cc")

foreach(PROJECT_NAME ${PROJECT_NAMES})
     # Create the cmake related files in the out folder so that the libraries can be
     # copied to the lib folder
     add_subdirectory( "{ORT_SOURCE_DIRECTORY}/${PROJECT_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/out/${PROJECT_NAME}"

endforeach(PROJECT_NAME ${PROJECT_NAMES})

#set the names of all the projects (for creating the libraries)
SET(EXECUATALE_PROJECTS "metadata" )

foreach(EXECUATALE_PROJECT ${EXECUATALE_PROJECTS})
     # Create the cmake related files in the out folder so that the libraries can be
     # copied to the lib folder
     add_subdirectory( "{ORT_SOURCE_DIRECTORY}/${EXECUATALE_PROJECT}" "${CMAKE_CURRENT_BINARY_DIR}/out/${EXECUATALE_PROJECT}"

endforeach(EXECUATALE_PROJECT ${EXECUATALE_PROJECTS})

用于日志目录的 CMakeLists.txt 文件(与我用于 cc 和数据项目的逻辑相同)

include_directories(${ORT_HEADER_DIRECTORY})
SET(LOG_SOURCE a.cpp b.cpp c.cpp)
ADD_LIBRARY(log_d ${LOG_SOURCE})
target_link)libraries(log_d cc_d data_d)

元数据 CMakeLists.txt 文件(创建可执行项目)

FIND_PACKAGE(wxWidgets)
IF(wxWidgets_FOUND)
        INCLUDE(${wxWidgets_USE_FILE})
ENDIF(wxWidgets_FOUND)

Include_Directories(${wxWidgets_INCLUDE_DIRS})
include_directories(${ORT_HEADER_DIRECTORY})
include_directories("/usr/ort/lib/unixODBC/include")

SET(META_SOURCE meta.cpp data.cpp)

ADD_EXECUTABLE(meta_d ${META_SOURCE })
TARGET_LINK_LIBRARIES(meta_d log_d data_d)

当我只是制作项目时,没有创建可执行文件,正在生成静态文件。但是,当我制作整个项目(即包含 subProject_3 目录)时,我得到未定义的引用,a::String该引用是 a.cpp 中的一个函数。

注意:所有 3 个项目都是相互依赖的。例如,在 a.cpp 中,我有#include "b.h",在 b.cpp 中,我有#include "a2.h".

所以,我有几个问题:

a) 如何解决未定义的引用问题?为项目 1 和 2 生成库后,如何将它们链接到可执行文件?

b) 在创建静态库时是否应该提供或添加任何依赖项?这是创建静态库的正确方法(因为项目是相互依赖的)?即target_link_libraries(project1 project2 ...)在项目1和target_link_libraries(project2 project1 ...)项目2中。

c) 每个项目都需要使用自己的编译设置进行编译。您能否让我知道如何为每个单独的项目指定相同的内容?

错误详情:

喜欢 CXX 可执行 metadata_d ../log/liblog_d.a:文件无法识别:文件被截断 collect2:ld 返回 1 退出状态

我还收到未定义的引用错误 /home...../metadata/data.cpp 172: undefined reference to xmlSerahNs 等等。collect2: ld 返回 1 个退出状态

谢谢您的帮助。

4

1 回答 1

7

如何解决未定义的参考问题?因为,我已经为项目 1 和 2 生成了库,如何将它们链接到可执行文件。

再次使用target_link_libraries,这次是在 subProject3 的 CMakeLists.txt 中:

target_link_libraries(subProject3 subProject2 subProject1)

这是创建静态库的正确方法吗(因为项目是相互依赖的)

是的。从文档中target_link_libraries

库依赖图通常是非循环的(一个 DAG),但在相互依赖的 STATIC 库的情况下,CMake 允许图包含循环(强连接组件)。当另一个目标链接到其中一个库时,CMake 会重复整个连接的组件。例如,代码

add_library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c)
target_link_libraries(main A)

将“main”链接到“ABA B”。(虽然通常重复一次就足够了,但病态目标文件和符号排列可能需要更多。可以通过在最后一次 target_link_libraries 调用中手动重复组件来处理这种情况。但是,如果两个档案确实如此相互依赖,那么它们可能应该组合成一个单个存档。)


每个项目都需要使用自己的编译设置进行编译。您能否让我知道如何为每个单独的项目指定相同的内容?

在顶层 CMakeLists.txt 中,在添加子目录之前,您可以在其中设置所有需要的标志。(参见add_definitionsProperties on Targets举例)它们将被所有子项目采用,除非针对子项目进行特别更改。

于 2012-11-01T19:29:10.177 回答