9

What can I do to enable WholeProgramOptimization from CMake ?

Here is what I tried:

  • I have CMake 3.10.2 installed
  • I have Visual Studio 2017 15.5.4 installed
  • I created a directory C:\Wpo
  • I created an empty directory C:\Wpo\Build
  • I created a C:\Wpo\Wpo.cpp file containing int main(){return 0;}
  • I created a C:\Wpo\CMakeLists.txt file containing the following:

    CMAKE_MINIMUM_REQUIRED (VERSION 3.10)
    PROJECT(Wpo)
    ADD_EXECUTABLE(Wpo "../Wpo.cpp")
    TARGET_COMPILE_OPTIONS(Wpo PRIVATE "$<$<CONFIG:Release>:/GL>")
    SET_TARGET_PROPERTIES(Wpo PROPERTIES LINK_FLAGS_RELEASE "/LTCG")
    
  • I openned a command line and created my Visual Studio solution:

    cd C:\Wpo\Build
    cmake ..
    

But when I open my solution in Visual Studio, Whole program Optimization is not set. Interestingly enough, there is a WholeProgramOptimization in the vcxproj file:

      <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
        <ClCompile>
          <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
          <AssemblerListingLocation>Release/</AssemblerListingLocation>
          <CompileAs>CompileAsCpp</CompileAs>
          <ExceptionHandling>Sync</ExceptionHandling>
          <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
          <Optimization>MaxSpeed</Optimization>
          <PrecompiledHeader>NotUsing</PrecompiledHeader>
          <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
          <RuntimeTypeInfo>true</RuntimeTypeInfo>
          <WarningLevel>Level3</WarningLevel>

          <WholeProgramOptimization>true</WholeProgramOptimization>

          <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
          <ObjectFileName>$(IntDir)</ObjectFileName>
          <DebugInformationFormat></DebugInformationFormat>
        </ClCompile>
      </ItemDefinitionGroup>

If I manually select Whole Program Optimizations from the Properties of the Project, an entry is added in another part of the vcxproj file:

      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
        <ConfigurationType>Application</ConfigurationType>
        <CharacterSet>MultiByte</CharacterSet>
        <PlatformToolset>v141</PlatformToolset>

        <WholeProgramOptimization>true</WholeProgramOptimization>

      </PropertyGroup>
  • Is it a bug from CMake ? It looks like it is adding this WholeProgramOptimization section in the wrong place.
  • Is it a bug from Visual Studio ? It could be a regression too.
  • Am I employing a deprecated way of doing this ? This happens a lot with CMake ;-)

Any help would be greatly appreciated.

Arnaud
  • 3,765
  • 3
  • 39
  • 69
  • According to [msdn](https://msdn.microsoft.com/en-us/library/0zza0de8.aspx), *compiler flag* `/GL` should be accompanied with **linker flag** `/LTCG`. Have you tried to set the linker flag too? `set_target_properties(Wpo PROPERTIES LINK_FLAGS "$<$:/LTCG>")`. – Tsyvarev Jan 24 '18 at 21:59
  • @Tsyvarev You are correct, the goal was to also have LTCG set. I updated my question accordingly. BTW, it was always set during my tests. – Arnaud Jan 24 '18 at 22:04
  • Can you try to generate project for VS2015 and open with your VS2017? And check whether it is set after upgrade. Looks like cmake issue - in project generated for VS2015 it is located in same section as in your sample. – Ation Jan 24 '18 at 22:19

2 Answers2

9

There are 3 places in a Visual Studio project where Whole Program Optimization settings come into picture -

1) At Project level (Project → General tab)

WholeProgramOptimization

This is a convenience meta-setting to enable Whole Program Optimization.

In the project XML it's located at<PropertyGroup>/<WholeProgramOptimization>

2) At compiler level (C/C++ → Optimization tab)

WholeProgramOptimization /GL

This is the actual /GL setting, it defaults to the project-level setting.

In the project XML it's located at<ItemDefinitionGroup>/<ClCompile>/<WholeProgramOptimization>

3) At linker level (Linker → Optimization tab)

Link-Time Code Generation /LTGC

This is the actual /LTCG setting, it defaults to the project-level setting.

In the project XML it's located at <ItemDefinitionGroup>/<Link>/<LinkTimeCodeGeneration>

The following CMake commands won't set WholeProgramOptimization at project level, but at compiler and linker level. That's why the "convenience" setting in the General tab is blank. The net effect, however, is the same. WholeProgramOptimization is on.

set_target_properties(Wpo PROPERTIES COMPILE_FLAGS "$<$<CONFIG:Release>:/GL>")
set_target_properties(Wpo PROPERTIES LINK_FLAGS "$<$<CONFIG:Release>:/LTCG>")
rustyx
  • 80,671
  • 25
  • 200
  • 267
  • Does this mean that values set through 2) and 3) override any value that is set through 1)? What is the point in even offering option 1) then? – Kaiserludi Feb 26 '20 at 17:01
  • Option 1 is the convenience meta-option that drives *both* 2) and 3) *together* when they're unset, which is normally the case. So normally WholeProgramOptimization is enabled at one place, which is simply convenient. – rustyx May 25 '20 at 14:31
  • `COMPILE_FLAGS` has been superseded by `COMPILE_OPTIONS`. Also note, when adding multiple options, you have to separate them using semicolons, e.g., `set_target_properties(Wpo PROPERTIES COMPILE_OPTIONS "$<$:/GL>;$<$:/Oi>")`. For the linker flags, there is also a method without generators: `set_target_properties(Wpo PROPERTIES LINK_FLAGS_RELEASE "/LTCG")` – Corylus Jul 25 '22 at 09:29
2

To use this feature you need to add compiler option /GL(whole program optimization) and linker option /LTCG (Link-time Code Generation).

SET_TARGET_PROPERTIES(Wpo PROPERTIES COMPILE_FLAGS "/GL")
SET_TARGET_PROPERTIES(Wpo PROPERTIES LINK_FLAGS "/LTCG")
Ation
  • 731
  • 7
  • 16
  • Unfortunately, it does not work with my configuration. Which Visual Studio versions and CMake versions do you have ? – Arnaud Jan 24 '18 at 22:08
  • cmake 3.4 + VS 2015 – Ation Jan 24 '18 at 22:08
  • which flag is not set? – Ation Jan 24 '18 at 22:09
  • /GL is not set. – Arnaud Jan 24 '18 at 22:10
  • If you edit the vcxproj, were is the WholeProgramOptimization line ? – Arnaud Jan 24 '18 at 22:10
  • How do you know /GL is not set? Can you post the cl command that is executed? – rustyx Jan 24 '18 at 22:21
  • @rustyx I thought I kenw it because the option was not set in the properties of the project furthermore, the "Whole Program Optimization" Property sheet was missing but the command line does indeed contain a /GL: `/GS /TP /GL /analyze- /W3 /Zc:wchar_t /Gm- /O2 /Ob2 /Fd"Wpo.dir\Release\vc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "CMAKE_INTDIR=\"Release\"" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /GR /Gd /Oy- /MD /Fa"Release/" /EHsc /nologo /Fo"Wpo.dir\Release\" /Fp"Wpo.dir\Release\Wpo.pch" /diagnostics:classic` – Arnaud Jan 24 '18 at 22:44
  • @rustyx Please add an answer stating that the option is really set. Visual studio does not display it in its Properties dialog but it is passed to the compiler anyway. You deserve the credits for this. – Arnaud Jan 24 '18 at 23:08