创建可执行文件时的CMake未定义参考 [英] CMake Undefined reference when creating executables

查看:68
本文介绍了创建可执行文件时的CMake未定义参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



项目




  • SRC


    1. subProject_1

      .cpp(所有源文件)和此文件夹的CMakeLists.txt 1(创建静态库)

    2. subproject_2

      .cpp(所有源文件)和此文件夹的CMakeLists.txt 2(创建静态库)

    3. subproject_3

      .cpp(所有源文件)和此文件夹的CMakeLists.txt 3(创建可执行文件)


  • Include


    1. subProject_1

      .h(所有头文件)

    2. subProject_2 < br>
      .h(所有头文件)

    3. subProject_3

      .h(所有头文件)


  • 构建/ Linux


    1. CMakeLists.txt(主CMakelist文件)




Main CMakeLists.txt

  cmake_minimum_required(版本2.6)
SET(CMAKE_CXX_COMPILER g ++)
项目(ort)
SET(CMAKE_CXX_FLAGS -g -Wall -pThread)

#设置源和头目录位置
set(ORT_HEADER_DIRECTORY ../../include)#include解释了文件夹结构在
以上set(ORT_SOURCE_DIRECTORY ../../src)
set(ORT_BINARY_DIRECTORY ../../lib)#lib文件夹包含所有库

集(CMAKE_CURRENT_BINARY_DIR。)

#包含库包
include_directories( / usr / include / wx-2.8)
include_directories( / usr / local / cuda / include)等等


#设置所有项目的名称(用于创建库)
SET(PROJECT_NAMES log data cc )

foreach(PROJECT_NAME $ {PROJECT_NAMES})
#在out文件夹中创建与cmake相关的文件,以便可以将库复制到
#复制到lib文件夹
add_subdirectory( {ORT_SOURCE_DIRECTORY} / $ {PROJECT_NAME} $ {CMAKE_CURRENT_BINARY_DIR} / out / $ {PROJECT_NAME}

endforeach(PROJECT_NAME $ {PROJECT_NAMES})

#设置所有项目的名称(用于创建库)
SET(EXECUATALE_PROJECTS元数据)

foreach(EXECUATALE_PROJECT $ {EXECUATALE_PROJECTS})
#创建与cmake相关的out文件夹中的文件,以便可以将库
#复制到lib文件夹
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)库(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中的一个函数。 / p>

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



所以,我有几个问题:



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



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



c)每个项目都需要使用自己的编译设置进行编译。您能告诉我如何为每个项目指定相同的项目吗?



错误详细信息:



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



I还得到未定义的引用错误
/home...../metadata/data.cpp 172:xmlSerahNs
的未定义引用,依此类推。
collect2:ld返回1个退出状态



感谢您的帮助。

解决方案


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


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

  target_link_libraries(subProject3 subProject2 subProject1)







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


是的。从 target_link_libraries 的文档中:


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

  add_library(A STATIC ac)
add_library(B STATIC bc)
target_link_libraries (AB)
target_link_libraries(BA)
add_executable(main main.c)
target_link_libraries(main A)

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








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


在顶级CMakeLists.txt中,之前添加子目录后,您可以在那里设置所需的所有标志。 (请参见 add_definitions 属性(例如,针对目标) ),除非为子项目专门更改,否则所有子项目都将采用它们。


I am new to CMake and I am trying to get my project compiling. The project creates a few static libraries and a few executables.

Below is the example of the file structure that I have.

PROJECT

  • SRC

    1. subProject_1
      .cpp (all source files) and CMakeLists.txt 1 for this folder (creating a static library)
    2. subproject_2
      .cpp (all source files) and CMakeLists.txt 2 for this folder (creating a static library)
    3. subproject_3
      .cpp (all source files) and CMakeLists.txt 3 for this folder (creating the executable)

  • Include

    1. subProject_1
      .h (all the header files)
    2. subProject_2
      .h (all the header files)
    3. subProject_3
      .h (all the header files)

  • build/linux

    1. CMakeLists.txt (Main CMakelist file)

Main 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 file for log directory (the same logic I have used for cc and data projects)

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)

metadata CMakeLists.txt file (creating the executable project)

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)

When I just make the project, without the creation of the executables, static files are being generated. But, when I make the whole project (i.e. with the inclusion of the subProject_3 directory) I get undefined reference to a::String which is a function in a.cpp.

Note: All the 3 projects are dependent on each other. For example, in a.cpp, I have #include "b.h" and in b.cpp I have #include "a2.h".

So, I have few questions:

a) How do I resolve the undefined reference issue? Once I have generated the libraries for project 1 and 2, how do I link these to the executable?

b) Should I provide or add any dependencies when I am creating the static libraries? Is this the right way of creating the static libraries (as the projects are inter dependent)? i.e. target_link_libraries(project1 project2 ...) in project 1 and target_link_libraries(project2 project1 ...) in project 2.

c) Every project needs to be compiled with its own compilation setting. Can you please let me know how can I specify the same for every individual project?

ERROR DETAILS:

Liking CXX executable metadata_d ../log/liblog_d.a: file not recognized: File truncated collect2: ld returned 1 exit status

I also get the undefined reference error /home...../metadata/data.cpp 172: undefined reference to xmlSerahNs and so on. collect2: ld returned 1 exit status

Thanks for the help.

解决方案

How do I resolve the undefined reference issue ? Since, I have generating the libraries for project 1 and 2, how do I link these to the executable.

Just use target_link_libraries again, this time in subProject3's CMakeLists.txt:

target_link_libraries(subProject3 subProject2 subProject1)


Is this the right way of creating the static libraries (as the projects are inter dependent)

Yes. From the docs for target_link_libraries:

The library dependency graph is normally acyclic (a DAG), but in the case of mutually-dependent STATIC libraries CMake allows the graph to contain cycles (strongly connected components). When another target links to one of the libraries CMake repeats the entire connected component. For example, the code

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)

links 'main' to 'A B A B'. (While one repetition is usually sufficient, pathological object file and symbol arrangements can require more. One may handle such cases by manually repeating the component in the last target_link_libraries call. However, if two archives are really so interdependent they should probably be combined into a single archive.)


Every project needs to be compiled with there own compilation setting. Can you please let me know how can I specify the same for every individual project?

In the top-level CMakeLists.txt, before adding the subdirectories, you can set all the flags you need there. (see add_definitions and Properties on Targets for example) They will be adopted by all the subprojects unless specifically changed for a subproject.

这篇关于创建可执行文件时的CMake未定义参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆