【问题标题】:Undefined References with Link-Time Optimization链接时优化的未定义引用
【发布时间】:2017-10-01 12:19:28
【问题描述】:

我正在尝试将静态库与可执行文件链接,遵循this example,但在 MinGW-w64 上。

我的 CMakeLists 文件:(请注意,这与该答案中的相同)

cmake_minimum_required (VERSION 2.6)
project (hellow)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
SET(CMAKE_AR  "gcc-ar")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_FINISH   true)
add_library(hello STATIC libhello.c)
add_executable(hellow hello.c)
target_link_libraries(hellow hello)
add_dependencies(hellow hello)

你好.c:

extern void hello(void);

int main(void) {
    hello();
    return 0;
}

libhello.c:

#include <stdio.h>

void hello(void) {
    puts("Hello");
}

配置按预期工作:

-- The C compiler identification is GNU 7.1.0
-- The CXX compiler identification is GNU 7.1.0
-- Check for working C compiler: C:/Program Files (x86)/mingw-w64/i686-7.1.0-win32-dwarf-rt_v5-rev2/mingw32/bin/gcc.exe
-- Check for working C compiler: C:/Program Files (x86)/mingw-w64/i686-7.1.0-win32-dwarf-rt_v5-rev2/mingw32/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/mingw-w64/i686-7.1.0-win32-dwarf-rt_v5-rev2/mingw32/bin/g++.exe
-- Check for working CXX compiler: C:/Program Files (x86)/mingw-w64/i686-7.1.0-win32-dwarf-rt_v5-rev2/mingw32/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/.../project

但是,当按原样编译时,会产生以下错误:

Scanning dependencies of target hello
[ 25%] Building C object CMakeFiles/hello.dir/libhello.c.obj
[ 50%] Linking C static library libhello.a
Error running link command: The system cannot find the file specified
mingw32-make.exe[3]: *** [CMakeFiles\hello.dir\build.make:95: libhello.a] Error 2
mingw32-make.exe[3]: *** Deleting file 'libhello.a'
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:67: CMakeFiles/hello.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:116: CMakeFiles/hellow.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:130: hellow] Error 2

删除CMakeLists.txt 文件中的SET(CMAKE_C_ARCHIVE_FINISH true) 行并重新编译会导致此“未定义引用”错误:

[ 25%] Linking C static library libhello.a
[ 50%] Built target hello
Scanning dependencies of target hellow
[ 75%] Building C object CMakeFiles/hellow.dir/hello.c.obj
[100%] Linking C executable hellow.exe
C:\...\Local\Temp\ccPctpZp.ltrans0.ltrans.o: In function `main':
E:/Documents/MONAD/projects/ltotest/hello.c:4: undefined reference to `hello'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [CMakeFiles\hellow.dir\build.make:97: hellow.exe] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:104: CMakeFiles/hellow.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:116: CMakeFiles/hellow.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:130: hellow] Error 2

运行 nm libhello.a 表明 libhello.c 正在使用 LTO 编译:

libhello.c.obj:
00000000 b .bss
00000000 d .data
00000000 r .gnu.lto_.decls.d7da3e90
00000000 r .gnu.lto_.inline.d7da3e90
00000000 r .gnu.lto_.opts
00000000 r .gnu.lto_.refs.d7da3e90
00000000 r .gnu.lto_.symbol_nodes.d7da3e90
00000000 r .gnu.lto_.symtab.d7da3e90
00000000 r .gnu.lto_hello.d7da3e90
00000000 r .rdata$zzz
00000000 t .text
00000001 C ___gnu_lto_slim
00000001 C ___gnu_lto_v1

这似乎是仅在 MinGW 上的问题,因为代码在之前链接的答案中似乎运行良好(尽管我自己无法测试它)。关于出了什么问题/如何解决它的任何想法?

【问题讨论】:

  • @HansPassant gcc-ar.exe 是 ar.exe 的包装器,提供 gcc LTO 插件(请参阅tin.org/bin/man.cgi?section=1&topic=gcc-ar-5)
  • @HansPassant 是的,可以找到它(我已经检查过了,此外,如果找不到,我希望会收到一个提到未知 exe 的错误)。

标签: c gcc cmake mingw-w64 lto


【解决方案1】:

做了更多研究,偶然发现了this page,其中提到还需要为ranlib 使用包装器。

果然,把CMakeLists.txt改成如下内容,项目就可以构建成功了:

cmake_minimum_required (VERSION 2.6)
project (hellow)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
SET(CMAKE_AR  "gcc-ar")
SET(CMAKE_RANLIB "gcc-ranlib")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
add_library(hello STATIC libhello.c)
add_executable(hellow hello.c)
target_link_libraries(hellow hello)
add_dependencies(hellow hello)

(注意新的SET(CMAKE_RANLIB "gcc-ranlib") 行)

此外,SET(CMAKE_C_ARCHIVE_FINISH "&lt;CMAKE_RANLIB&gt; &lt;TARGET&gt;") 行似乎不是必需的,因为这是CMAKE_C_ARCHIVE_FINISH 的默认值。

【讨论】:

  • gcc 文档还提到了The next version of binutils will support automatic loading of the liblto_plugin,因此对于最近的 binutils,包装器应该不是必需的。
  • 如果可以的话,我会投票两次。正是旧版 ubuntus/binutils (16.04) 所需要的。
猜你喜欢
  • 2012-08-28
  • 2011-04-03
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
相关资源
最近更新 更多