gpt4 book ai didi

c++ - 链接LLVM导致gcov失败

转载 作者:太空狗 更新时间:2023-10-29 21:32:50 25 4
gpt4 key购买 nike

在将--coverage传递到gcc的同时还链接LLVM会导致链接器出现undefined reference to `__gcov_exit'错误。我建立了一个新项目来尝试解决此问题。您可以view the source on githubinspect the compiler output on Travis-CI

这是承保范围和非承保范围的区别

-DCMAKE_CXX_FLAGS="--coverage"

这是LLVM和非LLVM构建之间的区别
target_link_libraries(Test
PUBLIC
LLVMCore
)
LLVM作业成功。 Coverage作业成功。 LLVM + Coverage作业因此错误而失败
undefined reference to `__gcov_exit'

最佳答案

注释:

  • 检查[cmake 3.13]: CMAKE_<LANG>_FLAGS以获得有关哪个环境变量影响哪个cmake变量的详细信息-如您在(已删除的)答案中所想的那样
  • 仅注意到cmake 3中的cxx_std_17。 8 ,因此您可能要更新cmake_minimum_required
  • 将您的存储库 fork 到[GitHub]: CristiFati/gcov_error - An attempt to reproduce the gcov/llvm linker error并进行了一些调试-请注意,我有一天可能会删除它
  • 能够使我对Travis CI有所了解,这是真正的金矿

  • 一开始我以为它是一个简单的修复程序(与-fprofile-arcs,-ftest-coverage和-lgcov标志有关的东西),如 [man7]: GCC(1)(-coverage选项)所述,但事实并非如此。
    我无法在Ubtu 16 x64 VM上重现该问题(尽管travis很好,但出于调试目的,它有点慢(特别是由于急于在编辑时匆匆忙忙忘记或添加额外的字符:))以及它没有提供与本地计算机相同的访问级别,),因为环境:
  • cmake 3.5.1
  • gcc 5.4.0
  • llvm 3.8.0

  • 与travis docker镜像上的内容相去甚远。我必须提到,我既没有尝试从源代码构建软件包(这可能会引起很多麻烦),也没有尝试从CI生成过程中从下载它们的存储库中下载它们(甚至没有检查那些存储库是否公开) )。无论如何,VM几乎无法使用,因为:
  • 我无法重现此问题(在进行一些较小的更改以适应较旧的工具之后),一切正常
  • 更多:我遇到了[SO]: Error when using CMake with LLVM - (@CristiFati's answer)

  • 为了让它活着,我一直在吃东西,所以我最终在travis上建立了 48 抓狂时间,以便使其正常工作,这仅仅是因为我没有注意到明显的情况。

    问题

    对于这3种配置中的每一种,我将粘贴生成的编译和链接(g++)命令(来自 您的构建: [Travis CI]: Kerndog73 / gcov_error- Build #24)
  • LLVM:

    /usr/bin/g++-7  -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/usr/lib/llvm-7/include  -std=gnu++1z -o CMakeFiles/Test.dir/main.cpp.o -c /home/travis/build/Kerndog73/gcov_error/main.cpp
    /usr/bin/g++-7 -rdynamic CMakeFiles/Test.dir/main.cpp.o -o Test -L/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/llvm-7/lib/libLLVMCore.a /usr/lib/llvm-7/lib/libLLVMBinaryFormat.a /usr/lib/llvm-7/lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread -lm /usr/lib/llvm-7/lib/libLLVMDemangle.a
  • 覆盖范围:

    /usr/bin/g++-7  -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/usr/lib/llvm-7/include  --coverage   -std=gnu++1z -o CMakeFiles/Test.dir/main.cpp.o -c /home/travis/build/Kerndog73/gcov_error/main.cpp
    /usr/bin/g++-7 --coverage -rdynamic CMakeFiles/Test.dir/main.cpp.o -o Test
  • LLVM +覆盖范围:

    /usr/bin/g++-7  -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/usr/lib/llvm-7/include  --coverage   -std=gnu++1z -o CMakeFiles/Test.dir/main.cpp.o -c /home/travis/build/Kerndog73/gcov_error/main.cpp
    /usr/bin/g++-7 --coverage -rdynamic CMakeFiles/Test.dir/main.cpp.o -o Test -L/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/llvm-7/lib/libLLVMCore.a /usr/lib/llvm-7/lib/libLLVMBinaryFormat.a /usr/lib/llvm-7/lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread -lm /usr/lib/llvm-7/lib/libLLVMDemangle.a

  • 追逐大量幽灵之后,我注意到在包含llvm时, -L / usr / lib / gcc / x86_64-linux-gnu / 4.8 被传递给链接器。 gcc 4.8 是在docker上安装的,因此显然gcc 7.4 用于编译,而gcc 4.8 用于链接,即 Undefined Behavior 。我还粘贴了 #3的细微变化(带有-v)的collect命令(更靠近链接器)。 (所有用-l *指定且没有完整路径的库(例如-lgcov,-lgcc_s,-lgcc)的 版本不正确,因为将从错误的目录中拾取该版本):

    /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/ccyDh97q.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o Test /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. CMakeFiles/Test.dir/main.cpp.o /usr/lib/llvm-7/lib/libLLVMCore.a /usr/lib/llvm-7/lib/libLLVMBinaryFormat.a /usr/lib/llvm-7/lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread /usr/lib/llvm-7/lib/libLLVMDemangle.a -lstdc++ -lm -lgcov -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/7/crtend.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.0


    放在.travis.yml的after_script部分中的一些测试命令产生以下输出:

    $ _GCOV_LIB7=/usr/lib/gcc/x86_64-linux-gnu/7/libgcov.a
    $ (nm -S ${_GCOV_LIB7} 2>/dev/null | grep __gcov_exit) || echo ${_GCOV_LIB7}
    0000000000001e40 000000000000008b T __gcov_exit
    $ _GCOV_LIB48=/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcov.a
    $ (nm -S ${_GCOV_LIB48} 2>/dev/null | grep __gcov_exit) || echo ${_GCOV_LIB48}
    /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcov.a


    因此,libgcc(libgcov.a)在两个涉及的版本之间进行了修改(添加了 __gcov_exit 符号),并且g++知道它有一个,但ld没有提供它(由于错误的lib),因此出现了错误。

    现在, 为何会为llvm添加此库搜索路径,我不知道(可能是因为它是使用gcc 4.8构建的-或者更接近它),但是我能想到的是:
  • llvm不适用于gcc 7(尽管我在快速浏览[LLVM]: Getting Started with the LLVM System时未发现任何此类限制)
  • llvm中的错误(考虑到我遇到的其他问题,我倾向于认为这是赢家)

  • 我找到了两种方法:
  • 使用较旧的g++(4.8-默认安装在docker上)
  • export CXX=g++(甚至可能不是必需的)
  • g++(这次是而不是 cmake)不了解cxx_std_17,因此最简单的方法是删除传入的target_compile_features(缺点是代码不会与C++ 17“兼容”)。
  • 因为我不知道如何“撤消”通过(错误的)库搜索路径,所以我想到的解决方法是在之前指定正确的

    CMakeLists.txt:
    cmake_minimum_required(VERSION 3.2)
    project(gcov_test)

    find_package(LLVM 7.0.0 REQUIRED CONFIG)
    message(STATUS "Found LLVM: ${LLVM_DIR} ${LLVM_PACKAGE_VERSION}")

    add_executable(Test
    "main.cpp"
    )

    target_compile_features(Test
    PUBLIC cxx_std_17
    )

    target_include_directories(Test
    PUBLIC ${LLVM_INCLUDE_DIRS}
    )

    target_compile_definitions(Test
    PUBLIC ${LLVM_DEFINITIONS}
    )

    if(LINK_WITH_LLVM)
    # @TODO - cfati: Everything in this block is to avoid hardcoding default libgcc path (/usr/lib/gcc/x86_64-linux-gnu/7)
    set(_COLLECT_LTO_WRAPPER_TEXT "COLLECT_LTO_WRAPPER=")
    execute_process(
    COMMAND bash -c "$0 -v 2>&1 | grep ${_COLLECT_LTO_WRAPPER_TEXT} | sed s/${_COLLECT_LTO_WRAPPER_TEXT}//" "${CMAKE_CXX_COMPILER}"
    OUTPUT_VARIABLE _GAINARIE_COLLECT_TMP_VAR
    )
    get_filename_component(_GAINARIE_GCC_DEFAULT_PATH ${_GAINARIE_COLLECT_TMP_VAR} DIRECTORY)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${_GAINARIE_GCC_DEFAULT_PATH}")
    #set (GCCOPT "${GCCOPT} -L${_GAINARIE_GCC_DEFAULT_PATH}")
    # @TODO END
    target_link_libraries(Test
    PUBLIC LLVMCore
    )
    endif()

    请注意:我试图提出一些更优雅的方法(我敢肯定是的),但是目前还不能(使用CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES,target_link_libraries,link_directories等尝试过)。
  • 关于c++ - 链接LLVM导致gcov失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53626481/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com