ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 在跨平台cmake项目中设置编译器标志的现代方法

2019-09-18 23:15:06  阅读:339  来源: 互联网

标签:c cmake cl clang mingw


我想编写一个cmake文件,在调试和发布版本中为clang,g和MSVC设置不同的编译器选项.
我目前正在做的事情看起来像这样:

if(MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /W4")
    # Default debug flags are OK 
    set(CMAKE_CXX_FLAGS_RELEASE "{CMAKE_CXX_FLAGS_RELEASE} /O2")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall -Wextra -Werror")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} some other flags")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")

    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
    else()
        # nothing special for gcc at the moment
    endif()
endif()

但我有几个问题:

>首先是微不足道的:是不是没有像appen这样的命令允许我用附加(CMAKE_CXX_FLAGS“Foo”)替换set(CMAKE_CXX_FLAGS“${CMAKE_CXX_FLAGS} Foo”)?
>我已多次阅读,首先不应手动设置CMAKE_CXX_FLAGS和类似变量,但我不确定使用哪种其他机制.
>最重要的是:我在这里的方式,我需要为每个编译器和配置单独的构建目录理想情况下,我想将其转换为同一目录中的多个目标,以便我可以例如调用make foo_debug_clang.

所以我的问题是

> a)有没有更好的方法来编写解决我的“痛点”的cmake脚本?
解决上述问题?
> b)是否有类似于如何建立此类项目的现代最佳实践?

我在互联网上找到的大多数参考资料要么过时,要么只显示一些简单的例子.我目前正在使用cmake3.8,但如果这有什么不同,我对更新版本的答案更感兴趣.

解决方法:

你的方法 – 正如@Tsyvarev评论的那样 – 绝对没问题,因为你在CMake中要求“新”方法就是你的代码将转化为:

cmake_minimum_required(VERSION 3.8)

project(HelloWorld)

string(
    APPEND _opts
    "$<IF:$<CXX_COMPILER_ID:MSVC>,"
        "/W4;$<$<CONFIG:RELEASE>:/O2>,"
        "-Wall;-Wextra;-Werror;"
            "$<$<CONFIG:RELEASE>:-O3>"
            "$<$<CXX_COMPILER_ID:Clang>:-stdlib=libc++>"
    ">"
)

add_compile_options("${_opts}")

add_executable(HelloWorld "main.cpp")

target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)

你拿add_compile_options()和 – 作为@ Al.G.评论说 – “使用脏generator expressions”.

生成器表达式有一些缺点:

>非常有用的$< IF:...,...,...>表达式仅适用于CMake版本> = 3.8
>你必须把它写在一行.为了避免这种情况,我使用了string(APPEND ...),您也可以使用它来“优化”您的设置(CMAKE_CXX_FLAGS“${CMAKE_CXX_FLAGS} …”.
>这很难阅读和理解.例如.需要分号才能使其成为编译选项列表(否则CMake会引用它).

因此,使用add_compile_options()更好地使用更具可读性和向后兼容性的方法:

if(MSVC)
    add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
else()
    add_compile_options("-Wall" "-Wextra" "-Werror" "$<$<CONFIG:RELEASE>:-O3>")
    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        add_compile_options("-stdlib=libc++")
    else()
        # nothing special for gcc at the moment
    endif()
endif()

是的,您不再明确指定C标准,您只需将C++ feature命名为您的代码/目标依赖于target_compile_features()调用.

对于这个例子,我选择了cxx_lambda_init_captures,例如较旧的GCC编译器会出现以下错误(例如,如果编译器不支持此功能,会发生什么情况):

The compiler feature "cxx_lambda_init_captures" is not known to CXX compiler

"GNU"

version 4.8.4.

并且您需要编写一个包装器脚本来使用“single configuration” makefile generator构建多个配置或使用“multi configuration” IDE作为Visual Studio.

以下是对示例的引用:

> Does CMake always generate configurations for all possible project configurations?
> How do I tell CMake to use Clang on Windows?
> How to Add Linux Compilation to Cmake Project in Visual Studio

所以我使用Open Folder Visual Studio 2017 CMake支持测试了以下内容,在此示例中结合了,编译器:

Configurations

CMakeSettings.json

{
    // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
    "configurations": [
        {
            "name": "x86-Debug",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "x86-Release",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "Clang-Debug",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "cmakeCommandArgs": "-T\"LLVM-vs2014\"",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "Clang-Release",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "cmakeCommandArgs": "-T\"LLVM-vs2014\"",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "GNU-Debug",
            "generator": "MinGW Makefiles",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "variables": [
                {
                    "name": "CMAKE_MAKE_PROGRAM",
                    "value": "${projectDir}\\mingw32-make.cmd"
                }
            ]
        },
        {
            "name": "GNU-Release",
            "generator": "Unix Makefiles",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "variables": [
                {
                    "name": "CMAKE_MAKE_PROGRAM",
                    "value": "${projectDir}\\mingw32-make.cmd"
                }
            ]
        }
    ]
}

mingw32的-make.cmd

@echo off
mingw32-make.exe %~1 %~2 %~3 %~4

因此,您可以在Visual Studio 2017中使用任何CMake生成器,有一些不健康的引用(2017年9月,可能稍后修复)需要mingw32-make.cmd中间人(删除引号).

标签:c,cmake,cl,clang,mingw
来源: https://codeday.me/bug/20190918/1811855.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有