Repository: conan-io/conan (Python)

Issue:
[bug] CMakeToolchain always enables CMAKE_POSITION_INDEPENDENT_CODE
### Steps to reproduce (Include if Applicable)

Using the CMakeToolchain generator, run `conan install` and disable `fPIC` option.
The generated CMakeToolchain file will contain `CMAKE_POSITION_INDEPENDENT_CODE=ON`.


This is obviously due to a typo fixed by #9752




Discussion:

Patch:
diff --git a/conan/tools/cmake/toolchain.py b/conan/tools/cmake/toolchain.py
index 60248a5a962..3caf3e647bf 100644
--- a/conan/tools/cmake/toolchain.py
+++ b/conan/tools/cmake/toolchain.py
@@ -134,8 +134,10 @@ def context(self):
 
 class FPicBlock(Block):
     template = textwrap.dedent("""
-        message(STATUS "Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE=ON (options.fPIC)")
-        set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+        {% if fpic %}
+        message(STATUS "Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE={{ fpic }} (options.fPIC)")
+        set(CMAKE_POSITION_INDEPENDENT_CODE {{ fpic }})
+        {% endif %}
         """)
 
     def context(self):
@@ -151,7 +153,7 @@ def context(self):
             self._conanfile.output.warn("Toolchain: Ignoring fPIC option defined "
                                         "for a shared library")
             return None
-        return {"fpic": fpic}
+        return {"fpic": "ON" if fpic else "OFF"}
 
 
 class GLibCXXBlock(Block):
diff --git a/contributors.txt b/contributors.txt
index fbed23aad5e..6206bb0a648 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -24,3 +24,4 @@ Many thanks to all of them!
 - Ries, Uilian (uilianries@gmail.com, @uilianries)
 - Sechet, Olivier (osechet@gmail.com)
 - Sturm, Fabian (f@rtfs.org, @sturmf)
+- Williams, Jordan (jordan@jwillikers.com)


Test patch:
diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
index d609c17cb42..f96cf1460b6 100644
--- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -22,6 +22,7 @@ def conanfile():
     c.settings.arch = "x86"
     c.settings.compiler = "gcc"
     c.settings.compiler.libcxx = "libstdc++"
+    c.settings.os = "Windows"
     c.conf = Conf()
     c.folders.set_base_generators(".")
     c._conan_node = Mock()
@@ -192,3 +193,133 @@ def test_toolset(conanfile_msvc):
     assert 'Visual Studio 17 2022' in toolchain.generator
     assert 'CMAKE_CXX_STANDARD 20' in toolchain.content
 
+
+@pytest.fixture
+def conanfile_linux():
+    c = ConanFile(Mock(), None)
+    c.settings = "os", "compiler", "build_type", "arch"
+    c.initialize(Settings({"os": ["Linux"],
+                           "compiler": {"gcc": {"version": ["11"], "cppstd": ["20"]}},
+                           "build_type": ["Release"],
+                           "arch": ["x86_64"]}), EnvValues())
+    c.settings.build_type = "Release"
+    c.settings.arch = "x86_64"
+    c.settings.compiler = "gcc"
+    c.settings.compiler.version = "11"
+    c.settings.compiler.cppstd = "20"
+    c.settings.os = "Linux"
+    c.conf = Conf()
+    c.folders.set_base_generators(".")
+    c._conan_node = Mock()
+    c._conan_node.dependencies = []
+    return c
+
+
+def test_no_fpic_when_not_an_option(conanfile_linux):
+    toolchain = CMakeToolchain(conanfile_linux)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' not in content
+
+
+@pytest.fixture
+def conanfile_linux_shared():
+    c = ConanFile(Mock(), None)
+    c.settings = "os", "compiler", "build_type", "arch"
+    c.options = {
+        "fPIC": [True, False],
+        "shared": [True, False],
+    }
+    c.default_options = {"fPIC": False, "shared": True, }
+    c.initialize(Settings({"os": ["Linux"],
+                           "compiler": {"gcc": {"version": ["11"], "cppstd": ["20"]}},
+                           "build_type": ["Release"],
+                           "arch": ["x86_64"]}), EnvValues())
+    c.settings.build_type = "Release"
+    c.settings.arch = "x86_64"
+    c.settings.compiler = "gcc"
+    c.settings.compiler.version = "11"
+    c.settings.compiler.cppstd = "20"
+    c.settings.os = "Linux"
+    c.conf = Conf()
+    c.folders.set_base_generators(".")
+    c._conan_node = Mock()
+    c._conan_node.dependencies = []
+    return c
+
+
+def test_no_fpic_when_shared(conanfile_linux_shared):
+    toolchain = CMakeToolchain(conanfile_linux_shared)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' not in content
+
+
+def test_fpic_when_not_shared(conanfile_linux_shared):
+    conanfile_linux_shared.options.shared = False
+    toolchain = CMakeToolchain(conanfile_linux_shared)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' in content
+
+
+@pytest.fixture
+def conanfile_windows_fpic():
+    c = ConanFile(Mock(), None)
+    c.settings = "os", "compiler", "build_type", "arch"
+    c.options = {"fPIC": [True, False], }
+    c.default_options = {"fPIC": True, }
+    c.initialize(Settings({"os": ["Windows"],
+                           "compiler": {"gcc": {"libcxx": ["libstdc++"]}},
+                           "build_type": ["Release"],
+                           "arch": ["x86"]}), EnvValues())
+    c.settings.build_type = "Release"
+    c.settings.arch = "x86"
+    c.settings.compiler = "gcc"
+    c.settings.compiler.libcxx = "libstdc++"
+    c.settings.os = "Windows"
+    c.conf = Conf()
+    c.folders.set_base_generators(".")
+    c._conan_node = Mock()
+    c._conan_node.dependencies = []
+    return c
+
+
+def test_no_fpic_on_windows(conanfile_windows_fpic):
+    toolchain = CMakeToolchain(conanfile_windows_fpic)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' not in content
+
+
+@pytest.fixture
+def conanfile_linux_fpic():
+    c = ConanFile(Mock(), None)
+    c.settings = "os", "compiler", "build_type", "arch"
+    c.options = {"fPIC": [True, False], }
+    c.default_options = {"fPIC": False, }
+    c.initialize(Settings({"os": ["Linux"],
+                           "compiler": {"gcc": {"version": ["11"], "cppstd": ["20"]}},
+                           "build_type": ["Release"],
+                           "arch": ["x86_64"]}), EnvValues())
+    c.settings.build_type = "Release"
+    c.settings.arch = "x86_64"
+    c.settings.compiler = "gcc"
+    c.settings.compiler.version = "11"
+    c.settings.compiler.cppstd = "20"
+    c.settings.os = "Linux"
+    c.conf = Conf()
+    c.folders.set_base_generators(".")
+    c._conan_node = Mock()
+    c._conan_node.dependencies = []
+    return c
+
+
+def test_fpic_disabled(conanfile_linux_fpic):
+    conanfile_linux_fpic.options.fPIC = False
+    toolchain = CMakeToolchain(conanfile_linux_fpic)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE OFF' in content
+
+
+def test_fpic_enabled(conanfile_linux_fpic):
+    conanfile_linux_fpic.options.fPIC = True
+    toolchain = CMakeToolchain(conanfile_linux_fpic)
+    content = toolchain.content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE ON' in content