c++ - CMake 和 GitHub Actions - GitHub Actions 上 CMake 库的 Windows 构建未将库链接到测试套件
问题描述
我有一个在 Linux 上运行良好的开源 CMake 项目。但是,为了使其更便携,我决定添加 Windows 构建选项。为了测试这一点,我设置了 GitHub Actions 基于 CMake 的应用程序,并将条件设置为在ubuntu-latest
、windows-latest
和macos-latest
.
我的工作流文件如下:
name: CMake
on: [push]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{github.workspace}}/build
# Note the current convention is to use the -S and -B options here to specify source
# and build directories, but this is only available with CMake 3.13 and higher.
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
# Execute the build. You can specify a specific target with "--target <NAME>"
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C $BUILD_TYPE
它非常标准并且工作正常。当我尝试在 Windows 上构建时,问题就出现了,而且只有 Windows。为了向 Windows 添加可移植性,我将其添加到我的CMakeLists.txt
:
if(WIN32)
set(FETCHCONTENT_BASE_DIR "C:/Users/$ENV{USERNAME}/AppData/Local/Temp")
endif()
这非常适合将我获取的依赖项保留在源目录之外(CMake 会抱怨)。但是当我尝试使用 Windows 构建时,该库会构建得很好,但找不到与测试套件(Catch2 + CTest)链接。
Link:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64\link.exe /ERRORREPORT:QUEUE /OUT:"D:\a\libeztp\libeztp\build\tests\Release\tests.exe" /INCREMENTAL:NO /NOLOGO ..\Release\libeztp.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"D:/a/libeztp/libeztp/build/tests/Release/tests.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:/a/libeztp/libeztp/build/tests/Release/tests.lib" /MACHINE:X64 /machine:x64 tests.dir\Release\mainTest.obj
LINK : fatal error LNK1181: cannot open input file '..\Release\libeztp.lib' [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
Done Building Project "D:\a\libeztp\libeztp\build\tests\tests.vcxproj" (default targets) -- FAILED.
Done Building Project "D:\a\libeztp\libeztp\build\ALL_BUILD.vcxproj" (default targets) -- FAILED.
Build FAILED
...
D:\a\libeztp\libeztp\build\ALL_BUILD.vcxproj" (default target) (1) ->
"D:\a\libeztp\libeztp\build\tests\tests.vcxproj" (default target) (5) ->
(Link target) ->
LINK : fatal error LNK1181: cannot open input file '..\Release\libeztp.lib' [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
我正在拔头发,发现这个 SO 帖子似乎有一些相关的问题。所以对我CMakeLists.txt
来说,我改变了 Windows,如果:
if(WIN32)
set(FETCHCONTENT_BASE_DIR "C:/Users/$ENV{USERNAME}/AppData/Local/Temp")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) # I did try commenting out this line, but it was the same error from before.
set(BUILD_SHARED_LIBS TRUE)
endif()
现在库正在正确链接(或者看起来如此),但现在它找不到一些导出的符号。
Link:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64\link.exe /ERRORREPORT:QUEUE /OUT:"D:\a\libeztp\libeztp\build\tests\Release\tests.exe" /INCREMENTAL:NO /NOLOGO ..\Release\libeztp.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"D:/a/libeztp/libeztp/build/tests/Release/tests.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:/a/libeztp/libeztp/build/tests/Release/tests.lib" /MACHINE:X64 /machine:x64 tests.dir\Release\mainTest.obj
mainTest.obj : error LNK2019: unresolved external symbol "class std::map<int,class eztp::Die,struct std::less<int>,class std::allocator<struct std::pair<int const ,class eztp::Die> > > eztp::dice" (?dice@eztp@@3V?$map@HVDie@eztp@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHVDie@eztp@@@std@@@4@@std@@A) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____0(void)" (?____C_A_T_C_H____T_E_S_T____0@@YAXXZ) [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
D:\a\libeztp\libeztp\build\tests\Release\tests.exe : fatal error LNK1120: 1 unresolved externals [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
Done Building Project "D:\a\libeztp\libeztp\build\tests\tests.vcxproj" (default targets) -- FAILED.
Done Building Project "D:\a\libeztp\libeztp\build\ALL_BUILD.vcxproj" (default targets) -- FAILED.
...
"D:\a\libeztp\libeztp\build\ALL_BUILD.vcxproj" (default target) (1) ->
"D:\a\libeztp\libeztp\build\tests\tests.vcxproj" (default target) (5) ->
(Link target) ->
mainTest.obj : error LNK2019: unresolved external symbol "class std::map<int,class eztp::Die,struct std::less<int>,class std::allocator<struct std::pair<int const ,class eztp::Die> > > eztp::dice" (?dice@eztp@@3V?$map@HVDie@eztp@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHVDie@eztp@@@std@@@4@@std@@A) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____0(void)" (?____C_A_T_C_H____T_E_S_T____0@@YAXXZ) [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
D:\a\libeztp\libeztp\build\tests\Release\tests.exe : fatal error LNK1120: 1 unresolved externals [D:\a\libeztp\libeztp\build\tests\tests.vcxproj]
在这一点上,我已经筋疲力尽,只想结束这一切,因为我已经有一段时间没有打算在 Windows 上进行开发了。有人可以指出我正确的方向并帮助我弄清楚我错过了什么吗?在这一点上,我只是把东西扔在墙上,希望有东西能粘住。
编辑:
这是导出符号的实现:
dice.hpp
namespace eztp {
class Die {
//Implementation probably irrelevant
};
extern std::map<int, Die> dice;
}
dice.cpp
std::map<int, eztp::Die> eztp::dice = {
{0, eztp::Die(0)},
{1, eztp::Die(1)},
{2, eztp::Die(2)},
{4, eztp::Die(4)},
{6, eztp::Die(6)},
{8, eztp::Die(8)},
{10, eztp::Die(10)},
{12, eztp::Die(12)},
{20, eztp::Die(20)},
{100, eztp::Die(100)}
};
解决方案
推荐阅读
- python - 如何让我的多目标跟踪器更高效?
- java - Spring WebClient PageImpl Content 缺少字段
- json - Laravel 8 在数据库中手动保存 JSON
- vbscript - 需要帮助将多个函数添加到一个 VBScript
- node.js - 使用 node.js 和 Bullmq 部署 API 的流程布局
- reactjs - 反应查询突变打字稿
- arrays - vb.net - “在数组中”函数?
- node.js - 为什么我使用 express-validator 得到未处理的 Promise 错误
- laravel - 带有 Laravel 的 VueJS 3 内联模板
- python - Pip freeze requirements.txt 不起作用