首页 > 解决方案 > 使用 cmake 和 msvc 构建 C++ - `/permissive-` 标志被删除

问题描述

我有一个非常大的项目,由于逻辑运算符关键字的替代拼写,我无法在 Windows 上编译。

我将我的问题分解为这个最小的示例:它包含以下两个文件:

main.cpp

#include <iostream>

int main() {
  int a = 0;
  int b = 1;
  if (a == b or a-1 == 1) {
    std::cout << "a and b are close\n";
  }
  return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(example VERSION 1.0)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # The behaviour is the same setting this flag to ON or OFF

set(CXXFLAGS "${CXXFLAGS} /permissive-")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /permissive-")

add_compile_options(/permissive-)

add_executable(example main.cpp)
target_compile_options(example PUBLIC /permissive-)

set_target_properties(example PROPERTIES C_ISO_COMPLIANT ON)
message(STATUS "CXX FLAGS ARE ${CMAKE_CXX_FLAGS}")
message(STATUS "CXX FLAGS ARE ${CMAKE_CXX_FLAGS_RELEASE}")

我在 Windows 系统上编译它们,如下所示:

C:\tmp>cmake -E env CXXFLAGS="/foo /permissive-" cmake -H. -Bbuild -G "Visual Studio 15 2017 Win64" -LA
-- The C compiler identification is MSVC 19.11.25547.0
-- The CXX compiler identification is MSVC 19.11.25547.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx86/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx86/x64/cl.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)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx86/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx86/x64/cl.exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- CXX FLAGS ARE /foo /permissive-  /DWIN32 /D_WINDOWS /W3 /GR /EHsc /permissive-
-- CXX FLAGS ARE /MD /O2 /Ob2 /DNDEBUG /permissive-
-- Configuring done
-- Generating done
-- Build files have been written to: C:/gtmp/build
-- Cache values
CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo
CMAKE_CXX_FLAGS:STRING=/foo /permissive-  /DWIN32 /D_WINDOWS /W3 /GR /EHsc
CMAKE_CXX_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3
CMAKE_C_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
CMAKE_EXE_LINKER_FLAGS:STRING=/machine:x64
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
CMAKE_INSTALL_PREFIX:PATH=C:/Program Files/example
CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx86/x64/link.exe
CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:x64
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
CMAKE_MT:FILEPATH=C:/Program Files (x86)/Windows Kits/10/bin/10.0.16299.0/x64/mt.exe
CMAKE_RC_COMPILER:FILEPATH=C:/Program Files (x86)/Windows Kits/10/bin/10.0.16299.0/x64/rc.exe
CMAKE_RC_FLAGS:STRING=-DWIN32
CMAKE_RC_FLAGS_DEBUG:STRING=-D_DEBUG
CMAKE_RC_FLAGS_MINSIZEREL:STRING=
CMAKE_RC_FLAGS_RELEASE:STRING=
CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:x64
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
CMAKE_SKIP_RPATH:BOOL=NO
CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:x64
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE

C:\tmp>cmake --build build --config Release --verbose
Microsoft (R)-Buildmodul, Version 15.4.8.50001 für .NET Framework
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

Der Buildvorgang wurde am 26.08.2021 13:00:43 gestartet.
Projekt "C:\tmp\build\ALL_BUILD.vcxproj" auf Knoten "1" (Standardziele).
Das Projekt "C:\tmp\build\ALL_BUILD.vcxproj" (1) erstellt "C:\tmp\build\ZERO_CHECK.vcxproj" (2) auf Knoten "1" (Standardziele).
PrepareForBuild:
  Das Verzeichnis "x64\Release\ZERO_CHECK\" wird erstellt.
  Das Verzeichnis "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\" wird erstellt.
InitializeBuildStatus:
  "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" wird erstellt, da "AlwaysCreate" angegeben wurde.
CustomBuild:
  Checking Build System
FinalizeBuildStatus:
  Die Datei "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" wird gelöscht.
  Aktualisieren des Timestamps von "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\ZERO_CHECK.lastbuildstate".
Die Erstellung von Projekt "C:\tmp\build\ZERO_CHECK.vcxproj" ist abgeschlossen (Standardziele).

Das Projekt "C:\tmp\build\ALL_BUILD.vcxproj" (1) erstellt "C:\tmp\build\example.vcxproj" (3) auf Knoten "1" (Standardziele).
PrepareForBuild:
  Das Verzeichnis "example.dir\Release\" wird erstellt.
  Das Verzeichnis "C:\tmp\build\Release\" wird erstellt.
  Das Verzeichnis "example.dir\Release\example.tlog\" wird erstellt.
InitializeBuildStatus:
  "example.dir\Release\example.tlog\unsuccessfulbuild" wird erstellt, da "AlwaysCreate" angegeben wurde.
CustomBuild:
  Building Custom Rule C:/gtmp/CMakeLists.txt
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX86\x64\CL.exe /c /nologo /W3 /WX- /diagnostics:classic /O2 /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Release\"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /std:c++14 /Fo"example.dir\Release\\" /Fd"example.dir\Release\vc141.pdb" /Gd /TP /errorReport:queue  /foo C:\tmp\main.cpp
cl : Command line warning D9002: ignoring unknown option '/foo' [C:\tmp\build\example.vcxproj]
  main.cpp
C:\tmp\main.cpp(7): error C2146: syntax error: missing ')' before identifier 'or' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(7): error C2065: 'or': undeclared identifier [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(7): error C2146: syntax error: missing ';' before identifier 'a' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(7): error C2059: syntax error: ')' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(8): error C2059: syntax error: ';' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(10): error C2059: syntax error: 'return' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(11): error C2059: syntax error: '}' [C:\tmp\build\example.vcxproj]
C:\tmp\main.cpp(11): error C2143: syntax error: missing ';' before '}' [C:\tmp\build\example.vcxproj]
Die Erstellung des Projekts "C:\tmp\build\example.vcxproj" ist abgeschlossen (Standardziele) -- FEHLER.

Die Erstellung des Projekts "C:\tmp\build\ALL_BUILD.vcxproj" ist abgeschlossen (Standardziele) -- FEHLER.


Fehler beim Buildvorgang.

"C:\tmp\build\ALL_BUILD.vcxproj" (Standardziel) (1) ->
"C:\tmp\build\example.vcxproj" (Standardziel) (3) ->
(ClCompile Ziel) ->
  cl : Command line warning D9002: ignoring unknown option '/foo' [C:\tmp\build\example.vcxproj]


"C:\tmp\build\ALL_BUILD.vcxproj" (Standardziel) (1) ->
"C:\tmp\build\example.vcxproj" (Standardziel) (3) ->
(ClCompile Ziel) ->
  C:\tmp\main.cpp(7): error C2146: syntax error: missing ')' before identifier 'or' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(7): error C2065: 'or': undeclared identifier [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(7): error C2146: syntax error: missing ';' before identifier 'a' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(7): error C2059: syntax error: ')' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(8): error C2059: syntax error: ';' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(10): error C2059: syntax error: 'return' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(11): error C2059: syntax error: '}' [C:\tmp\build\example.vcxproj]
  C:\tmp\main.cpp(11): error C2143: syntax error: missing ';' before '}' [C:\tmp\build\example.vcxproj]

    1 Warnung(en)
    8 Fehler

Verstrichene Zeit 00:00:00.89

C:\tmp>:

它失败并抱怨orin的错误main.cpp。要接受此行为,需要使用/permissive-标志 ( ref ) 调用编译器。看到我通过它几乎发疯了。请注意,该\foo标志确实已通过环境变量传递给编译器,但是该\permissive-标志已被删除。

健全性检查:如果我使用生成的编译命令并/permissive-手动添加标志,它编译得很好:

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX86\x64\CL.exe" /c /nologo /W3 /WX- /diagnostics:classic /O2 /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Release\"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /std:c++14 /Fo"example.dir\Release\\" /Fd"example.dir\Release\vc141.pdb" /Gd /TP /errorReport:queue /permissive- /foo C:\tmp\main.cpp

C:\tmp\build>"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX86\x64\CL.exe" /c /nologo /W3 /WX- /diagnostics:classic /O2 /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Release\"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /std:c++14 /Fo"example.dir\Release\\" /Fd"example.dir\Release\vc141.pdb" /Gd /TP /errorReport:queue /permissive- /foo C:\Jenkins\workspace\SCIPOptSuite_windows_libs_release\tmp\main.cpp
cl : Command line warning D9002 : ignoring unknown option '/foo'
main.cpp

C:\tmp\build>

如何说服 CMake 不要将此标志放到编译命令中?

标签: c++windowscmakecompilation

解决方案


事实证明,从 15.4 到 15.9 的更新起到了作用,显然该选项是在 15.5 版中引入的:https ://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view= msvc-140

C:\tmp>cmake -H. -Bbuild -G "Visual Studio 15 2017 Win64"
-- The C compiler identification is MSVC 19.16.27045.0
-- The CXX compiler identification is MSVC 19.16.27045.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.ex
e
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.ex
e - 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)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.
exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.
exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- CXX FLAGS ARE /DWIN32 /D_WINDOWS /W3 /GR /EHsc /permissive-
-- CXX FLAGS ARE /MD /O2 /Ob2 /DNDEBUG /permissive-
-- Configuring done
-- Generating done
-- Build files have been written to: C:/tmp/build

C:\tmp>cmake --build build --config Release
Microsoft (R)-Build-Engine, Version 15.9.21+g9802d43bc3 für .NET Framework
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

  Checking Build System
  Building Custom Rule C:/tmp/CMakeLists.txt
  main.cpp
  example.vcxproj -> C:\tmp\build\Release\example.exe
  Building Custom Rule C:/tmp/CMakeLists.txt

C:\tmp>

推荐阅读