Reconciling default Visual Studio 2022 .vcxproj file vs CMake generated .vcxproj file in Release mode | x64

Hello,

I am trying to reconcile the .vcxproj file generated by native Visual Studio for Release build x64 architecture with the equivalent file generated by CMake when the generator is set to Visual Studio.

The native VS generated .vcxproj file I generated using VS2022 is available at Default Visual Studio .vcxproj file (github.com)

The CMake generated .vcxproj file is available at Default CMake generated .vcxproj file when generator is set to Visual Studio (github.com)

The latter was generated with a minimal CMakeLists.txt file which looks so:

cmake_minimum_required (VERSION 3.8)
project ("CMakeProject" LANGUAGES C CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
message(STATUS "System: ${CMAKE_SYSTEM}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Compiler version: ${CMAKE_CXX_COMPILER_VERSION}")
add_executable (CMakeProject Main.cpp)

CMakeSettings.json looks so:

{
  "configurations": [
    {
      "name": "x64-Debug",
      "generator": "Visual Studio 17 2022 Win64",
      "configurationType": "Debug",
      "inheritEnvironments": [ "msvc_x64_x64" ],
      "buildRoot": "${projectDir}\\cmake\\windows\\build\\${name}",
      "installRoot": "${projectDir}\\cmake\\windows\\install\\${name}",
      "cmakeCommandArgs": "",
      "buildCommandArgs": "",
      "ctestCommandArgs": ""
    },
    {
      "name": "x64-Release",
      "generator": "Visual Studio 17 2022 Win64",
      "configurationType": "Release",
      "inheritEnvironments": [ "msvc_x64_x64" ],
      "buildRoot": "${projectDir}\\cmake\\windows\\build\\${name}",
      "installRoot": "${projectDir}\\cmake\\windows\\install\\${name}",
      "cmakeCommandArgs": "",
      "buildCommandArgs": "",
      "ctestCommandArgs": ""
    }
  ]
}

In particular, the release x64 properties under native VS build has the following

    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>

The compiling and linking properties of the CMake generated .vcxproj contain the following:

    <ClCompile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ExceptionHandling>Sync</ExceptionHandling>
      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
      <Optimization>MaxSpeed</Optimization>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <RuntimeTypeInfo>true</RuntimeTypeInfo>
      <UseFullPaths>false</UseFullPaths>
      <WarningLevel>Level3</WarningLevel>
      <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <DebugInformationFormat>
      </DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
    </ResourceCompile>
    <Midl>
      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
      <HeaderFileName>%(Filename).h</HeaderFileName>
      <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
      <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
      <ProxyFileName>%(Filename)_p.c</ProxyFileName>
    </Midl>
    <Link>
      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalOptions>%(AdditionalOptions) /machine:x64</AdditionalOptions>
      <GenerateDebugInformation>false</GenerateDebugInformation>
      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
      <ImportLibrary>D:/TryerGit/DefaultVSProjectViaCMake/cmake/windows/build/x64-Release/Release/CMakeProject.lib</ImportLibrary>
      <ProgramDataBaseFile>D:/TryerGit/DefaultVSProjectViaCMake/cmake/windows/build/x64-Release/Release/CMakeProject.pdb</ProgramDataBaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
    <ProjectReference>
      <LinkLibraryDependencies>false</LinkLibraryDependencies>
    </ProjectReference>

Why does CMake deem some of the native VS settings, for instance those pertaining to SDLCheck, ConformanceMode, EnableCOMDATFolding, amongst others, to be sufficiently unnecessary so as not to warrant any mention in its generated .vcxproj file? Likewise, vice versa, there are some settings that CMake deems important enough in Release mode such as RuntimeTypeInfo, amongst others, which appear in its .vcxproj file which VS does not deem important enough. I would like to understand the underlying reason for this divergence in default Release mode settings. My overall goal is to make sure my application runs in Release mode as fast as possible and ensure that the settings via native VS .vcxproj file or via CMake generated .vcxproj file do not lead to any significant difference in running times.

Thank you.

I think you may want the VS_USER_PROPS target property here. However, much of this is derived via a flag translation tables. Some properties may not have settings without the appropriate flags being specified. For example, SDLCheck seems to be set via the -sdl flag’s presence (-sdl- turning it off).

As for the differences, Visual Studio knows its defaults while CMake can’t reliably track that. So it tries to specify as much as it can based on the flags and other settings it has available. Anything not specified is left to the compiler defaults (which may differ from Visual Studio defaults, but I doubt that).

1 Like