diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py index 296ba885a29..e5b48cbf0c0 100644 --- a/conan/tools/gnu/autotoolstoolchain.py +++ b/conan/tools/gnu/autotoolstoolchain.py @@ -6,7 +6,7 @@ from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, build_type_link_flags, libcxx_flags from conan.tools.env import Environment from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet -from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path +from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc from conan.errors import ConanException from conans.model.pkg_type import PackageType @@ -49,6 +49,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"): self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile) self.fpic = self._conanfile.options.get_safe("fPIC") self.msvc_runtime_flag = self._get_msvc_runtime_flag() + self.msvc_extra_flags = self._msvc_extra_flags() # Cross build triplets self._host = self._conanfile.conf.get("tools.gnu:host_triplet") @@ -103,6 +104,15 @@ def _get_msvc_runtime_flag(self): flag = "-{}".format(flag) return flag + def _msvc_extra_flags(self): + if is_msvc(self._conanfile) and check_min_vs(self._conanfile, "180", raise_invalid=False): + return ["-FS"] + return [] + + def _add_msvc_flags(self, flags): + # This is to avoid potential duplicate with users recipes -FS (alreday some in ConanCenter) + return [f for f in self.msvc_extra_flags if f not in flags] + @staticmethod def _filter_list_empty_fields(v): return list(filter(bool, v)) @@ -114,7 +124,8 @@ def cxxflags(self): self.sysroot_flag] apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag] conf_flags = self._conanfile.conf.get("tools.build:cxxflags", default=[], check_type=list) - ret = ret + self.build_type_flags + apple_flags + self.extra_cxxflags + conf_flags + vs_flag = self._add_msvc_flags(self.extra_cxxflags) + ret = ret + self.build_type_flags + apple_flags + self.extra_cxxflags + vs_flag + conf_flags return self._filter_list_empty_fields(ret) @property @@ -123,7 +134,8 @@ def cflags(self): ret = [self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag] apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag] conf_flags = self._conanfile.conf.get("tools.build:cflags", default=[], check_type=list) - ret = ret + self.build_type_flags + apple_flags + self.extra_cflags + conf_flags + vs_flag = self._add_msvc_flags(self.extra_cflags) + ret = ret + self.build_type_flags + apple_flags + self.extra_cflags + vs_flag + conf_flags return self._filter_list_empty_fields(ret) @property @@ -134,7 +146,8 @@ def ldflags(self): check_type=list) conf_flags.extend(self._conanfile.conf.get("tools.build:exelinkflags", default=[], check_type=list)) - linker_scripts = self._conanfile.conf.get("tools.build:linker_scripts", default=[], check_type=list) + linker_scripts = self._conanfile.conf.get("tools.build:linker_scripts", default=[], + check_type=list) conf_flags.extend(["-T'" + linker_script + "'" for linker_script in linker_scripts]) ret = ret + self.build_type_link_flags + apple_flags + self.extra_ldflags + conf_flags return self._filter_list_empty_fields(ret) @@ -147,7 +160,8 @@ def defines(self): def environment(self): env = Environment() - compilers_by_conf = self._conanfile.conf.get("tools.build:compiler_executables", default={}, check_type=dict) + compilers_by_conf = self._conanfile.conf.get("tools.build:compiler_executables", default={}, + check_type=dict) if compilers_by_conf: compilers_mapping = {"c": "CC", "cpp": "CXX", "cuda": "NVCC", "fortran": "FC"} for comp, env_var in compilers_mapping.items(): diff --git a/conans/test/functional/toolchains/gnu/autotools/test_basic.py b/conans/test/functional/toolchains/gnu/autotools/test_basic.py index 3d0206658f0..b94911f0979 100644 --- a/conans/test/functional/toolchains/gnu/autotools/test_basic.py +++ b/conans/test/functional/toolchains/gnu/autotools/test_basic.py @@ -9,6 +9,7 @@ from conan.tools.env.environment import environment_wrap_command from conans.model.recipe_ref import RecipeReference from conans.test.assets.autotools import gen_makefile_am, gen_configure_ac, gen_makefile +from conans.test.assets.genconanfile import GenConanfile from conans.test.assets.sources import gen_function_cpp from conans.test.functional.utils import check_exe_run, check_vs_runtime from conans.test.utils.tools import TestClient, TurboTestClient @@ -383,3 +384,43 @@ def package_info(self): client.run("test test_package mylib/1.0@") assert "mylib/1.0: Hello World Release!" in client.out + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Only MSVC") +def test_msvc_extra_flag(): + profile = textwrap.dedent(""" + [settings] + os=Windows + compiler=msvc + compiler.version=193 + compiler.runtime=dynamic + arch=x86_64 + build_type=Release + """) + client = TestClient() + conanfile = GenConanfile().with_settings("os", "arch", "compiler", "build_type")\ + .with_generator("AutotoolsToolchain") + client.save({"conanfile.py": conanfile, + "profile": profile}) + client.run("install . --profile:build=profile --profile:host=profile") + toolchain = client.load("conanautotoolstoolchain{}".format('.bat')) + assert 'set "CXXFLAGS=%CXXFLAGS% -MD -O2 -Ob2 -FS"' in toolchain + assert 'set "CFLAGS=%CFLAGS% -MD -O2 -Ob2 -FS"' in toolchain + + # now verify not duplicated + conanfile = textwrap.dedent(""" + from conan import ConanFile + from conan.tools.gnu import AutotoolsToolchain + class Pkg(ConanFile): + settings = "os", "arch", "compiler", "build_type" + def generate(self): + tc = AutotoolsToolchain(self) + tc.extra_cxxflags.append("-FS") + tc.extra_cflags.append("-FS") + tc.generate() + """) + client.save({"conanfile.py": conanfile}) + client.run("install . --profile:build=profile --profile:host=profile") + toolchain = client.load("conanautotoolstoolchain{}".format('.bat')) + assert 'set "CXXFLAGS=%CXXFLAGS% -MD -O2 -Ob2 -FS"' in toolchain + assert 'set "CFLAGS=%CFLAGS% -MD -O2 -Ob2 -FS"' in toolchain