当它们不与GCC和CMAKE一起使用时,如何解析未定义的引用



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

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

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

我尝试在我的 CMAKE 文件中使用以下标志(从这里开始(,但它似乎没有帮助。

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) 

如果它们确实未引用,则不会收到"未定义的引用"错误。

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

编辑:修改后的问题

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

根据需要将-ffunction-sections添加到CFLAGS和/或CXXFLAGS,并将-Wl,--gc-sections添加到LDFLAGS

链接时间优化器(-flto(也可以这样做,但AFAIK需要启用优化,因此它会在调试版本中失败。

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

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

-ffunction-sections-Wl,--gc-sections 1

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

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

-fvisibility=hidden-fvisibility-inlines-hidden 2

所有标志一起,删除了链接时间错误。


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

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

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

最新更新