diff --git a/conan/tools/apple/xcodetoolchain.py b/conan/tools/apple/xcodetoolchain.py index 76d8c79180a..d46dca4cd17 100644 --- a/conan/tools/apple/xcodetoolchain.py +++ b/conan/tools/apple/xcodetoolchain.py @@ -51,7 +51,8 @@ def generate(self): save(self._agreggated_xconfig_filename, self._agreggated_xconfig_content) save(self._vars_xconfig_filename, self._vars_xconfig_content) if self._check_if_extra_flags: - save(self._flags_xcconfig_filename, self._flags_xcconfig_content) + save(self._flags_props_xconfig_filename, self._flags_xcconfig_content) + save(self._flags_xcconfig_filename, self._flags_xcconfig_aggregated_content) save(GLOBAL_XCCONFIG_FILENAME, self._global_xconfig_content) @property @@ -118,13 +119,28 @@ def _check_if_extra_flags(self): @property def _flags_xcconfig_content(self): - defines = "GCC_PREPROCESSOR_DEFINITIONS = $(inherited) {}".format(" ".join(self._global_defines)) if self._global_defines else "" - cflags = "OTHER_CFLAGS = $(inherited) {}".format(" ".join(self._global_cflags)) if self._global_cflags else "" - cppflags = "OTHER_CPLUSPLUSFLAGS = $(inherited) {}".format(" ".join(self._global_cxxflags)) if self._global_cxxflags else "" - ldflags = "OTHER_LDFLAGS = $(inherited) {}".format(" ".join(self._global_ldflags)) if self._global_ldflags else "" + # Conditioned like the vars props file, so flags from different installed + # (config, arch, sdk) combinations don't overwrite each other. + condition = _xcconfig_conditional(self._conanfile.settings, self.configuration) + defines = "GCC_PREPROCESSOR_DEFINITIONS{} = $(inherited) {}".format(condition, " ".join(self._global_defines)) if self._global_defines else "" + cflags = "OTHER_CFLAGS{} = $(inherited) {}".format(condition, " ".join(self._global_cflags)) if self._global_cflags else "" + cppflags = "OTHER_CPLUSPLUSFLAGS{} = $(inherited) {}".format(condition, " ".join(self._global_cxxflags)) if self._global_cxxflags else "" + ldflags = "OTHER_LDFLAGS{} = $(inherited) {}".format(condition, " ".join(self._global_ldflags)) if self._global_ldflags else "" ret = self._flags_xconfig.format(defines=defines, cflags=cflags, cppflags=cppflags, ldflags=ldflags) return ret + @property + def _flags_props_xconfig_filename(self): + return "conan_global_flags{}{}".format(_xcconfig_settings_filename(self._conanfile.settings, + self.configuration), + self.extension) + + @property + def _flags_xcconfig_aggregated_content(self): + return _add_includes_to_file_or_create(self._flags_xcconfig_filename, + self._agreggated_xconfig, + [self._flags_props_xconfig_filename]) + @property def _flags_xcconfig_filename(self): return "conan_global_flags" + self.extension diff --git a/test/integration/toolchains/apple/test_xcodetoolchain.py b/test/integration/toolchains/apple/test_xcodetoolchain.py index 8941f162beb..4f8c2844175 100644 --- a/test/integration/toolchains/apple/test_xcodetoolchain.py +++ b/test/integration/toolchains/apple/test_xcodetoolchain.py @@ -58,31 +58,52 @@ def test_toolchain_files(configuration, os_version, cppstd, libcxx, arch, sdk_ve assert 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(condition, clang_cppstd) in toolchain_vars +@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS") def test_toolchain_flags(): client = TestClient() client.save({"conanfile.txt": "[generators]\nXcodeToolchain\n"}) - cmd = "install . -c 'tools.build:cxxflags=[\"flag1\"]' " \ - "-c 'tools.build:defines=[\"MYDEFINITION\"]' " \ - "-c 'tools.build:cflags=[\"flag2\"]' " \ - "-c 'tools.build:sharedlinkflags=[\"flag3\"]' " \ - "-c 'tools.build:exelinkflags=[\"flag4\"]'" + cmd = "install . -s build_type=Release -s arch=x86_64 " \ + "-c 'tools.build:cxxflags=[\"cxxflags_release\"]' " \ + "-c 'tools.build:defines=[\"defines_release\"]' " \ + "-c 'tools.build:cflags=[\"cflags_release\"]' " \ + "-c 'tools.build:sharedlinkflags=[\"sharedlinkflags_release\"]' " \ + "-c 'tools.build:exelinkflags=[\"exelinkflags_release\"]'" client.run(cmd) + filename = _get_filename("Release", "x86_64", None) + condition = _condition("Release", "x86_64", None) + + conan_global_flags_props = client.load("conan_global_flags{}.xcconfig".format(filename)) + assert "GCC_PREPROCESSOR_DEFINITIONS{} = $(inherited) defines_release".format(condition) in conan_global_flags_props + assert "OTHER_CFLAGS{} = $(inherited) cflags_release".format(condition) in conan_global_flags_props + assert "OTHER_CPLUSPLUSFLAGS{} = $(inherited) cxxflags_release".format(condition) in conan_global_flags_props + assert "OTHER_LDFLAGS{} = $(inherited) sharedlinkflags_release exelinkflags_release".format(condition) in conan_global_flags_props + + # A second install, for a different configuration, must not overwrite the + # first one's flags -- each stays reachable under its own condition. + client.run("install . -s build_type=Debug -s arch=x86_64 -c 'tools.build:cxxflags=[\"cxxflags_debug\"]'") + debug_filename = _get_filename("Debug", "x86_64", None) + debug_flags = client.load("conan_global_flags{}.xcconfig".format(debug_filename)) + assert "cxxflags_debug" in debug_flags + assert "cxxflags_release" not in debug_flags + conan_global_flags = client.load("conan_global_flags.xcconfig") - assert "GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MYDEFINITION" in conan_global_flags - assert "OTHER_CFLAGS = $(inherited) flag2" in conan_global_flags - assert "OTHER_CPLUSPLUSFLAGS = $(inherited) flag1" in conan_global_flags - assert "OTHER_LDFLAGS = $(inherited) flag3 flag4" in conan_global_flags + assert '#include "conan_global_flags{}.xcconfig"'.format(filename) in conan_global_flags + assert '#include "conan_global_flags{}.xcconfig"'.format(debug_filename) in conan_global_flags conan_global_file = client.load("conan_config.xcconfig") assert '#include "conan_global_flags.xcconfig"' in conan_global_file +@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS") def test_flags_generated_if_only_defines(): # https://github.com/conan-io/conan/issues/16422 client = TestClient() client.save({"conanfile.txt": "[generators]\nXcodeToolchain\n"}) - client.run("install . -c 'tools.build:defines=[\"MYDEFINITION\"]'") - conan_global_flags = client.load("conan_global_flags.xcconfig") - assert "GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MYDEFINITION" in conan_global_flags + client.run("install . -s build_type=Release -s arch=x86_64 -c 'tools.build:defines=[\"MYDEFINITION\"]'") + filename = _get_filename("Release", "x86_64", None) + condition = _condition("Release", "x86_64", None) + + conan_global_flags_props = client.load("conan_global_flags{}.xcconfig".format(filename)) + assert "GCC_PREPROCESSOR_DEFINITIONS{} = $(inherited) MYDEFINITION".format(condition) in conan_global_flags_props conan_global_file = client.load("conan_config.xcconfig") assert '#include "conan_global_flags.xcconfig"' in conan_global_file