【问题标题】:How to resolve undefined reference when they are not used with GCC & CMAKE未与 GCC 和 CMAKE 一起使用时如何解决未定义的引用
【发布时间】:2017-11-20 21:51:33
【问题描述】:

我正在尝试在 CMAKE 的帮助下将一些 MSVC 项目移植到 Linux。 在其中一个库项目中,有一些函数只是声明了,没有在任何地方定义或在任何地方使用。 例如:

int fun_a();
int fun_unsed() /*This function is never used in project*/
{
    fun_a();
}

现在,当我尝试在 Linux 中进行 make 时,我观察到对已声明函数的未定义引用。但是相同的代码适用于具有相同 CMAKE 文件的 MSVC。

我尝试在我的 CMAKE 文件中使用以下标志(来自 here),但它似乎没有帮助。

SET(GCC_COVERAGE_COMPILE_FLAGS "-unresolved-symbols=ignore-all")
SET(GCC_COVERAGE_LINK_FLAGS    "-unresolved-symbols=ignore-all")

SET( CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )

我错过了什么吗?

下面是可执行的 cmake 文件

#Add Library Projects to the test application
add_subdirectory ("${PROJECT_BINARY_DIR}/../../src/build/vc/" "${PROJECT_BINARY_DIR}/../../src/build/vc/")


#set additional search paths for libraries
#set(CMAKE_LIBRARY_PATH ${PROJECT_BINARY_DIR}/../../lib/Debug)
  link_directories(${PROJECT_BINARY_DIR}/../../lib ${OPENCV_BUILD}/lib)
  #set ignore undefined & unused functions errors. It seems GCC by defalt looks for them.
  SET(GCC_COVERAGE_LINK_FLAGS    "-unresolved-symbols=ignore-all")
  SET(GCC_COVERAGE_COMPILE_FLAGS "-ffunction-sections")
  SET(GCC_COVERAGE_LINK_FLAGS    "-Wl,-gc-sections -flto")


  SET( CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
  SET( CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )

#Get the exicutable for source files
add_executable (FaceAnalysis ${sources})
  target_link_libraries (FaceAnalysis faceDetect.a libopencv_core.so libopencv_imgproc.so libopencv_imgcodecs.so libopencv_videoio.so libopencv_objdetect.so libopencv_highgui.so libopencv_video.so libopencv_ml.so SDL2)

add_dependencies(FaceAnalysis faceDetect) 

【问题讨论】:

  • 显示精确的CMakeLists.txt。关于设置 CMAKE_CXX_FLAGS 有一些具体规定。此外,运行构建过程make V=1,使用该选项您可能会看到用于编译和链接的完整命令行。
  • @Tsyvarev 添加了 CMakeLists.txt 文件,make V=1 不提供任何额外信息
  • 对不起,我的意思是make VERBOSE=1。你的CMakeLists.txt 的内容看起来很合理,除了: 1. 你设置了 GCC_COVERAGE_LINK_FLAGS 变量 twice,所以第二个赋值会覆盖第一个。 2. 在第一个赋值中,它应该在值的开头附加破折号:--unresolved-symbols=...

标签: c++ linux gcc cmake


【解决方案1】:

如果它们确实未被引用,您将不会收到“未定义引用”错误。

链接器错误应该告诉您符号的使用位置。

编辑:修改后的问题

这可以通过要求编译器将每个函数放入单独的部分来解决,因此它们在目标文件中保持分开直到最终链接,然后指示链接器丢弃未引用的部分。

酌情将-ffunction-sections 添加到CFLAGS 和/或CXXFLAGS,并将-Wl,--gc-sections 添加到LDFLAGS

链接时优化器 (-flto) 也可以执行此操作,但 AFAIK 需要启用优化,因此它会在 Debug 构建中失败。

【讨论】:

  • 我认为我没有正确提出问题,我已更正。该函数被引用,但没有使用调用函数。
  • 尝试过提到的编译器、链接器的标志。但我仍然看到错误。甚至 -flto 似乎也不起作用。
  • @Rama 这些标志确实是正确的。问题是 GCC(我认为也是 Clang,虽然不确定)不支持某些目标(Windows 和 Linux、X86 和 64)上的这些标志。他们至少在 ARM 目标中支持它们(可能也在其他平台中)
【解决方案2】:

如果您的项目中没有该功能的实现,那么它必须在另一个库中实现。在您的 Visual Studio 项目中,右键单击该项目,选择“属性”,然后在“链接器”下查看链接的库和链接目录。您将看到至少在那里定义了一个库。然后在 CMAKE 中你只需要 target_link_libraries 到同一个库。

【讨论】:

    【解决方案3】:

    正如西蒙在他的回答中所说,删除死亡代码的标志是:

    -ffunction-sections-Wl,--gc-sections1

    但是,GCC 在某些目标中不支持它们,例如 X86 和 64 上的 Windows 和 Linux,具有 ELF 文件格式。

    我的解决方案是通过使用以下标志来降低所有函数的可见性:

    -fvisibility=hidden-fvisibility-inlines-hidden 2

    将所有标志放在一起,消除链接时间错误。


    1-ffunction-sections 将每个函数放在不同的部分

    -Wl,--gc-sections 应该删除所有未使用的部分。

    2 此标志将所有函数的可见性从默认(公共)更改为隐藏。因此,链接器现在知道,如果这些函数不在可执行文件或库中使用,则不再需要这些函数,因此可以随意删除它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-30
      • 2013-09-12
      • 2017-06-27
      • 2010-10-11
      • 2015-07-30
      • 1970-01-01
      • 2019-09-05
      相关资源
      最近更新 更多