我最近在一个项目中添加了一个新特性和相应的单元测试.项目的 struct 如下:

Sim
└── models
    ├── otherModels
    └── myModel
        ├── CMakeLists.txt
        ├── model.cpp
        ├── model.h
        ├── test
        │   ├── CMakeLists.txt
        │   ├── geometryTest.cpp
        │   └── geometryTest.h
        └── util
            ├── CMakeLists.txt
            ├── geometry.cpp
            ├── geometry.h
            └── probability.h

Summarize the problem

我的目标是能够构建上述项目,并在Windows和Linux上执行单元测试.

实际效果

在Windows上,我能够很好地构建项目并运行单元测试.

在Linux上,我在构建时得到一个错误,说无法找到正在测试的库:

/home/e40056742/projects/xxxx/build/make-Release/Sim/bin/modelTests: error while loading shared libraries: libmathUtil.so: cannot open shared object file: No such file or directory
CMake Error at /projs/xxxx/cmake-3.18.2/share/cmake-3.18/Modules/GoogleTestAddTests.cmake:77 (message):
  Error running test executable.

    Path: '/home/e40056742/projects/xxxx/build/make-Release/Sim/bin/modelTests'
    Result: 127
    Output:


Call Stack (most recent call first):
  /projs/xxxx/cmake-3.18.2/share/cmake-3.18/Modules/GoogleTestAddTests.cmake:173 (gtest_discover_tests_impl)


make[2]: *** [Sim/bin/modelTests] Error 1
make[2]: *** Deleting file `Sim/bin/modelTests'
make[1]: *** [Sim/src/models/myModel/test/CMakeFiles/modelTests.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

预期结果

能够在Linux上构建.

What I've tried

  1. 我在谷歌上搜索了如何在Linux上找到文件,并验证了该文件是否存在:

    find . -name libmathUtil.so
    >>> ./build/make-Release/Sim/lib/libmathUtil.so
    
    
  2. 如果我注释掉add_subdirectory(test),我验证了所有东西都构建在Linux上

  3. 我try 了这里发布的解决方案,回答了一个不同的(但我希望是相关的)问题:How to add linker directories to cmake gtest_discover_tests

  4. 我将CMake RPATH设置添加到我的测试目录的CMakeLists.txt中,如另一个答案所示:https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling#always-full-rpath

  5. 我try 正确设置CMakeLists.txt文件,如下所示:

Top level CMake for my working directory

set( target myCoolModel )

set( sources
    model.cpp
    )

set( headers
    model.h
    )

add_library( ${target} ${sources} ${headers} )

target_link_libraries( ${target}
    ${PROJECT_LIBRARIES}
    mathUtil
    )

# Group the target library into an IDE folder
set_target_properties( ${target} PROPERTIES FOLDER ${PROJECT_FOLDER} )

# Add the utility and test subdirectory 
enable_testing()
add_subdirectory( util )
add_subdirectory( test ) 

And in the 100 sub-directory:

set( target mathUtil)
set( sources geometry.cpp )
set( headers geometry.h probability.h)

add_library( ${target} ${sources} ${headers} )

target_link_libraries( ${target} genMath::genMath )

target_compile_options( ${target} PRIVATE ${PROJECT_CXX_FLAGS} )

target_include_directories( ${target}
    PUBLIC  ${CMAKE_CURRENT_SOURCE_DIR} )

And the 100 directory:

enable_testing()

# Set target name, and dependencies
set( target modelTests )
set( sources geometryTest.cpp )
set( headers geometryTest.h)

# Find Google Test
find_package( GTest REQUIRED )

# Make test executable. 
add_executable( ${target} ${sources} ${headers} )

target_link_libraries(${target}
    mathUtil
    GTest::gtest_main
)

# Load GoogleTest and add these tests to the suite
include(GoogleTest)
gtest_discover_tests(${target})

# File unit tests into the project test folder (makes it easier to find in solution explorer)
set( PROJECT_FOLDER ${PROJECT_FOLDER}/test )
set_target_properties( ${target} PROPERTIES FOLDER ${PROJECT_FOLDER} )

推荐答案

它可能会失败,因为默认情况下,gtest_discover_tests实际上在构建阶段运行测试可执行文件,以获取可用的测试列表.环境(尤其是$LD_LIBRARY_PATH)可能未正确设置,无法运行可执行文件.

如果其他方法都不起作用,并且CMake>;=3.18,则可以通过将DISCOVERY_MODE设置为PRE_TEST来延迟测试的发现(从构建阶段排除).引用document人的话:

DISCOVERY_MODE

版本3.18中的新功能.

可以更好地控制gtest_discovery_test()的执行时间 测试发现.缺省情况下,POST_BUILD设置一个生成后命令以 在构建时执行测试发现.在某些情况下,例如 交叉编译,这种POST_BUILD行为是不可取的.通过 相比之下,pre_test会将测试发现延迟到测试之前 行刑.这样,测试发现就会在目标环境中发生 测试有更好的机会找到合适的运行时 依赖关系.

我实际上试图通过使用google_discover_testsPROPERTIES设置正确的环境变量来在POST_BUILD模式下运行测试发现,但是没有起作用,并且在判断了GoogleTest cmake模块本身的源代码之后,我得出的结论是,不可能为google_discover_tests代表您运行测试可执行文件的shell 会话设置环境变量.

在不使用PRE_TEST的情况下,唯一可行的替代方法是为可执行文件正确设置RPATH,这样它就可以自己找到依赖项.然而,按照惯例,在CMake中,RPATH应该设置在安装阶段,而不是构建阶段.此外,从find_package调用中提取正确的路径,然后将它们添加到RPATH中并不总是很简单,而且容易出错.这就是为什么我最终得到了PRE_TEST分,即使我真的更喜欢POST_BUILD分,如果它可以用一种简单的方式完成的话.

Linux相关问答推荐

C++17:G++8.5版似乎无法正确生成无符号64位伪随机整数

如何检测文件系统是否支持权限?

Git - 打印以不同编码混合的文件

eBPF:仅使用系统调用加载 eBPF 程序并将其附加到 sys_enter_execve

如何在REPL控制台中使用PowerShell将特定的CSV列转换为TitleCase?

为什么rsp寄存器从0x7FFFFFFFDFD0开始

在 linux 中插入带有 sed 命令的文件的行

我需要制作一个 awk 脚本来解析文件中的文本.我不确定我是否做得正确

当接收端未从套接字读取时,通过 Unix 套接字发送的消息会发生什么情况?

查找在特定日期从特定机器登录的所有用户

为什么 fork() 在 setsid() 之前

为什么 Linux (x86) 的页面大小是 4 KB,这是如何计算的?

在不调试的情况下查找哪个汇编指令导致了非法指令错误

如何像 Nautilus 那样从命令行挂载?

如何克隆 OpenLDAP 数据库

nvm:无法卸载当前活动的 node 版本

我想为 Linux 内核做贡献

在 Linux 中,名称与正则表达式匹配的文件的磁盘使用情况?

在 Linux 上更新 PyCharm

我可以使用 awk 将所有小写字母转换为大写吗?