首页 > 解决方案 > CMake 和 GitHub Actions - GitHub Actions 上 CMake 库的 Windows 构建未将库链接到测试套件

问题描述

我有一个在 Linux 上运行良好的开源 CMake 项目。但是,为了使其更便携,我决定添加 Windows 构建选项。为了测试这一点,我设置了 GitHub Actions 基于 CMake 的应用程序,并将条件设置为在ubuntu-latestwindows-latestmacos-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)}
};

标签: c++windowsvisual-studiocmakegithub-actions

解决方案


推荐阅读