diff --git a/conan/tools/cmake/toolchain.py b/conan/tools/cmake/toolchain.py index 5f11eb28dd4..4af99509955 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/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 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)