在 Windows 上使用 CMake、Ninja 和 Clang 进行构建

Building with CMake, Ninja and Clang on Windows

这个问题是 2017 年的,可能已经过时了。请对提供的说明持保留态度,因为现在可能有更好的解决方案。


亲爱的 C++ 程序员,

在使用 Visual Studio 工具链在 windows 上构建一段时间后,我决定尝试一下 Clang 5。

我安装了 LLVM 5.0.0 二进制文件、Ninja 构建环境、VS 2017 工具和 CMake 3.9.3。最终目标是能够使用 VS Code 为 Windows 编译 C 和 C++ 应用程序,CMake 集成为“IDE”,Clang 与 LLD 作为编译器和链接器。

一个简单程序的编译和执行工作得很好 (screenshot of the respective terminal history)。 Clang 自动检测 VS 工具目录中 Windows 的标准库并生成可执行输出。

下一步是使用 Ninja (screenshot of ninja.build file and terminal history) 设置一个简单的构建。构建过程按预期工作并生成了一个工作的可执行文件,就像以前一样。

当我开始将 CMake 集成到流程中时,问题就开始了。我的期望是 CMake 生成一个忍者构建文件并运行它,对吗? 我尝试了以下 CMakeLists 文件

cmake_minimum_required(VERSION 3.9)

project(Test)

add_executable(Test main.c)

并用 cmake -G Ninja 调用了 CMake。 结果输出令人失望,我理解不够,无法自己解决问题。

-- The C compiler identification is Clang 5.0.0
-- The CXX compiler identification is Clang 5.0.0
-- Check for working C compiler: C:/Meine_Programme/LLVM/bin/clang.exe
-- Check for working C compiler: C:/Meine_Programme/LLVM/bin/clang.exe -- broken
CMake Error at C:/Meine_Programme/CMake/share/cmake-3.9/Modules/CMakeTestCCompiler.cmake:51 (message):
  The C compiler "C:/Meine_Programme/LLVM/bin/clang.exe" is not able to
  compile a simple test program.

  It fails with the following output:

   Change Dir: D:/Dateien/Downloads/Test/CMakeFiles/CMakeTmp

  

  Run Build Command:"C:/Meine_Programme/Ninja_Build/ninja.exe" "cmTC_eeb5c"

  [1/2] Building C object CMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj

  FAILED: CMakeFiles/cmTC_eeb5c.dir/testCCompiler.c.obj 

  C:\Meine_Programme\LLVM\bin\clang.exe /nologo /DWIN32 /D_WINDOWS /W3 /MDd
  /Zi /Ob0 /Od /RTC1 /showIncludes
  /FoCMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj
  /FdCMakeFiles\cmTC_eeb5c.dir\ -c testCCompiler.c

  clang.exe: error: no such file or directory: '/nologo'

  clang.exe: error: no such file or directory: '/DWIN32'

  clang.exe: error: no such file or directory: '/D_WINDOWS'

  clang.exe: error: no such file or directory: '/W3'

  clang.exe: error: no such file or directory: '/MDd'

  clang.exe: error: no such file or directory: '/Zi'

  clang.exe: error: no such file or directory: '/Ob0'

  clang.exe: error: no such file or directory: '/Od'

  clang.exe: error: no such file or directory: '/RTC1'

  clang.exe: error: no such file or directory: '/showIncludes'

  clang.exe: error: no such file or directory:
  '/FoCMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj'

  clang.exe: error: no such file or directory:
  '/FdCMakeFiles\cmTC_eeb5c.dir\'

  ninja: build stopped: subcommand failed.

  

  

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:3 (project)


-- Configuring incomplete, errors occurred!
See also "D:/Dateien/Downloads/Test/CMakeFiles/CMakeOutput.log".
See also "D:/Dateien/Downloads/Test/CMakeFiles/CMakeError.log".

我猜这个问题与 CMake 调用 clang 和 VS 样式选项有关,使用斜杠而不是前面有减号,就像 clang 要求的那样。

感谢你们帮助我,我很感激:-)

如果您需要更多信息,请给我留言。

对弗洛里安人的回答post

我尝试了 Florians 命令,但省略了 ninja 的路径以获得更短的符号,结果证明它工作得很好。

cmake -E env LDFLAGS="-fuse-ld=lld"  cmake -H. -G Ninja -Bbuild -DCMAKE_C_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang.exe" -DCMAKE_CXX_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang++.exe" -DCMAKE_C_COMPILER_ID="Clang" -DCMAKE_CXX_COMPILER_ID="Clang" -DCMAKE_SYSTEM_NAME="Generic"

CMake 生成了一个忍者构建文件。

I 运行 ninja all 将可执行文件构建为 Test。我把它重命名为Test.exe,程序执行得很愉快。至此……成功!!!但是比我想象的要复杂得多。

受到来自@Unspongeful 的 "Ways to Compile with Clang on Windows" 博客 post 的启发,并经过一些扩展测试后,以下命令行对我有用(是的,这是一个大命令,我只是分成几行用于更好的可读性):

> cmake -E env LDFLAGS="-fuse-ld=lld-link" PATH="<path\to\ninja>" 
      cmake -H. -G Ninja -Bbuild 
         -DCMAKE_C_COMPILER:PATH="%ProgramFiles(x86)%\LLVM\bin\clang.exe" 
         -DCMAKE_CXX_COMPILER:PATH="%ProgramFiles(x86)%\LLVM\bin\clang.exe" 
         -DCMAKE_C_COMPILER_ID="Clang" 
         -DCMAKE_CXX_COMPILER_ID="Clang" 
         -DCMAKE_SYSTEM_NAME="Generic"

这里是一些背景信息:

  • 我用 LDFLAGS 环境变量注入了你的链接器标志

    Passing compiler options cmake

  • 我减少了 PATH 环境变量以仅指向 ninja 所在的位置,因为 CMake 正在选择我的 MinGW 工具链(我没有希望包含在构建过​​程中)

  • 相关
  • 定义编译器 ID "bypasses the check for working compiler and basic compiler information tests"

    见已过时,但有时有用CMakeForceCompiler module

  • 并且我将 CMAKE_SYSTEM_NAME 设置为 Generic 以避免 CMake

    添加任何额外的平台特定 compiler/linker 标志

    How to partially disabling cmake C/C++ custom compiler checking

目前看来您必须绕过许多 CMake 的自动检查才能使其正常工作。因此,请与 CMake 团队或 raise an issue 联系以获得官方支持。

而带有 Generic 系统的最后一部分可能不是最佳选择,因为它会跳过 Windows 特定设置,例如 .exe 后缀。

但这是唯一真正有效的星座:

-- The C compiler identification is Clang
-- The CXX compiler identification is Clang
-- Check for working C compiler: C:/Program Files (x86)/LLVM/bin/clang.exe
-- Check for working C compiler: C:/Program Files (x86)/LLVM/bin/clang.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)/LLVM/bin/clang.exe
-- Check for working CXX compiler: C:/Program Files (x86)/LLVM/bin/clang.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: build

我在尝试同时使用 clang cmake 和 msvc 2017 时 运行 遇到了类似的问题。至少对于一个非常简单的测试项目,我能够得到所有东西 运行,但我对这些东西很陌生,所以我的解决方案可能无法解决您的问题。

无论如何。据我所知,VS 应该使用 clang-cl.exe 而不是 clang.exe。但是,由于有关 x86 与 x64 库不兼容的一些链接器问题,我在 x86 配置中的构建仍然失败。

所以这是我在 VS 2017 中构建的同时获得 x64 和 x86 配置的解决方案。

  1. http://releases.llvm.org/download.html 下载并安装 BOTH windows clang/llvm 个安装程序。您不必将它们添加到路径中,因为我们稍后会明确指定路径。
  2. 创建一个带有 CMakeLists.txt 的文件夹,然后通过 Open Folder 对话框在 VS 中打开它。
  3. CMake 菜单中,select Change CMake Settings > CMakeLists.txt。这将生成一个 CMakeSettings.json 包含所有构建配置的设置。
  4. cmakeCommandArgs 中为所有配置指定x64/x86 cmake 编译器的路径。我的看起来像这样:

    {    // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
    
    "configurations": [
        {
            "name": "x86-Debug",
            "generator": "Ninja",
            "configurationType": "Debug",
            "inheritEnvironments": [ "msvc_x86" ],
            "buildRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\build\${name}",
            "installRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\install\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5_x86/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x86-Release",
            "generator": "Ninja",
            "configurationType": "RelWithDebInfo",
            "inheritEnvironments": [ "msvc_x86" ],
            "buildRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\build\${name}",
            "installRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\install\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5_x86/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x64-Debug",
            "generator": "Ninja",
            "configurationType": "Debug",
            "inheritEnvironments": [ "msvc_x64" ],
            "buildRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\build\${name}",
            "installRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\install\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x64-Release",
            "generator": "Ninja",
            "configurationType": "RelWithDebInfo",
            "inheritEnvironments": [ "msvc_x64" ],
            "buildRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\build\${name}",
            "installRoot": "${env.USERPROFILE}\CMakeBuilds\${workspaceHash}\install\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        }
    ]
    

    }

现在您应该能够正确构建 x64 和 x86 配置。

我终于找到了一种方法,可以让我满意地使用我喜欢的工具。它并不完美,但它比将系统名称设置为 Generic(我已经使用了一段时间)

的 Florians 方法效果更好

我首先将 VS Code 设置为使用 VS 开发人员终端作为其标准终端。我通过将以下行添加到 VS 代码首选项来做到这一点

"terminal.integrated.shell.windows": "C:\MeineProgramme\Visual_Studio\2017\BuildTools\Common7\Tools\LaunchDevCmd.bat"

在 VS Code 中启动终端后,我需要调用相应的批处理文件来设置所需的环境变量(在我的例子中 vcvars64.bat)。这些可以在

中找到
C:\MeineProgramme\Visual_Studio17\BuildTools\VC\Auxiliary\Build

导航到我的构建目录后,我 运行 CMake 具有以下选项

cmake .. -G Ninja -DCMAKE_CXX_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang-cl.exe" -DCMAKE_LINKER:PATH="C:\MeineProgramme\LLVM\bin\lld-link.exe"

这鼓励 CMake 使用我安装的所有 LLVM 工具。不仅 clanglld(确保使用 lld-link 支持由 / 引导的选项),还有 llvm-arllvm-ranlib.唯一使用的 MS 构建工具是我目前不使用的资源编译器。

到目前为止,我认为是成功的。

如果您还有其他问题,请随时与我联系或在下方发表评论。