Repository: conan-io/conan-center-index

Issue:
[package] lcms/2.11 static library compiled with LTO (Visual Studio 2019)
lcms built with Visual Studio is compiled with LTO/program optimization ([`/GL`](https://docs.microsoft.com/en-us/cpp/build/reference/gl-whole-program-optimization?view=msvc-160)) without an option to disable it.
The following warning is shown when linking an executable using lcms:
```
lcms2_static.lib(cmsio0.obj) : MSIL .netmodule or module compiled with /GL found; restarting link w
  ith /LTCG; add /LTCG to the link command line to improve linker performance
```
A library should be compiled with LTO only when `/GL` is added to `CFLAGS`/`CXXFLAGS`.

I think the correct way of action is to patch lcms to remove adding the `/GL` compile flag.

### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **lcms/2.11**
  * Operating System+version: **Windows**
  * Compiler+version: **Visual Studio 2019**
  * Python version: **Python 3.9.6**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
os=Windows
os_build=Windows
arch=x86_64
arch_build=x86_64
compiler=Visual Studio
compiler.version=16
build_type=Release
[build_requires]
[options]
[env]
```


### Steps to reproduce (Include if Applicable)
Build a simple executable and link with lcms




Discussion:
> A library should be compiled with LTO only when /GL is added to CFLAGS/CXXFLAGS.

Agree, we should never allow upstream build system to add LTO itself in static libs (and even in shared libs maybe, unless it has no dependency), it should come from conan profile.
Why test package doesn't fail?
> Agree, we should never allow upstream build system to add LTO itself in static libs (and even in shared libs maybe, unless it has no dependency), it should come from conan profile.

is `/LTO` hard-coded somewhere in makefiles? or do we have this option silently activated in recipe?
for the first case, I regret that it may require some patches....

> Why test package doesn't fail?

it's not a hard error, not even warning, linker just restarts without LTO.

> > Agree, we should never allow upstream build system to add LTO itself in static libs (and even in shared libs maybe, unless it has no dependency), it should come from conan profile.
> 
> is `/LTO` hard-coded somewhere in makefiles? or do we have this option silently activated in recipe?
> for the first case, I regret that it may require some patches....

LTO is hardcoded in vcxproj files using `<WholeProgramOptimization>true</WholeProgramOptimization>`.

> 
> > Why test package doesn't fail?
> 
> it's not a hard error, not even warning, linker just restarts without LTO.

It's not an error indeed. The linker restarts with LTO enabled.
LTO'ing executables/libraries takes more time.
So it should only be done when asked.



Resolving patch:
diff --git a/recipes/lcms/all/conanfile.py b/recipes/lcms/all/conanfile.py
--- a/recipes/lcms/all/conanfile.py
+++ b/recipes/lcms/all/conanfile.py
@@ -1,6 +1,7 @@
 from conans import ConanFile, tools, AutoToolsBuildEnvironment, MSBuild
 from conans.tools import Version
 import os
+import re
 import shutil
 
 required_conan_version = ">=1.33.0"
@@ -72,9 +73,13 @@ def _build_visual_studio(self):
         with tools.chdir(os.path.join(self._source_subfolder, "Projects", vc_sln_subdir )):
             target = "lcms2_DLL" if self.options.shared else "lcms2_static"
             upgrade_project = Version(self.settings.compiler.version) > "12"
+            properties = {
+                # Enable LTO when CFLAGS contains -GL
+                "WholeProgramOptimization": "true" if any(re.finditer("(^| )[/-]GL($| )", tools.get_env("CFLAGS", ""))) else "false",
+            }
             # run build
             msbuild = MSBuild(self)
-            msbuild.build("lcms2.sln", targets=[target], platforms={"x86": "Win32"}, upgrade_project=upgrade_project)
+            msbuild.build("lcms2.sln", targets=[target], platforms={"x86": "Win32"}, upgrade_project=upgrade_project, properties=properties)
 
     def _configure_autotools(self):
         if self._autotools:


Test patch: