diff --git a/conan/tools/build/flags.py b/conan/tools/build/flags.py index 441aca0afd5..49156c5edf4 100644 --- a/conan/tools/build/flags.py +++ b/conan/tools/build/flags.py @@ -67,11 +67,21 @@ def architecture_flag(conanfile): "e2k-v6": "-march=elbrus-v6", "e2k-v7": "-march=elbrus-v7"}.get(arch, "") elif compiler == "emcc": - # Emscripten default output is WASM since 1.37.x (long time ago) if arch == "wasm64": return "-sMEMORY64=1" + return "" + + +def architecture_link_flag(conanfile): + """ + returns exclusively linker flags specific to the target architecture and compiler + """ + compiler = conanfile.settings.get_safe("compiler") + arch = conanfile.settings.get_safe("arch") + if compiler == "emcc": + # Emscripten default output is WASM since 1.37.x (long time ago) # Deactivate WASM output forcing asm.js output instead - elif arch == "asm.js": + if arch == "asm.js": return "-sWASM=0" return "" diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py index 2df118716f6..d2a77fda62b 100644 --- a/conan/tools/cmake/toolchain/blocks.py +++ b/conan/tools/cmake/toolchain/blocks.py @@ -10,7 +10,7 @@ from conan.tools.android.utils import android_abi from conan.tools.apple.apple import is_apple_os, to_apple_arch from conan.tools.build import build_jobs -from conan.tools.build.flags import architecture_flag, libcxx_flags +from conan.tools.build.flags import architecture_flag, architecture_link_flag, libcxx_flags from conan.tools.build.cross_building import cross_building from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME from conan.tools.cmake.utils import is_multi_configuration @@ -238,19 +238,26 @@ def context(self): class ArchitectureBlock(Block): template = textwrap.dedent("""\ # Define C++ flags, C flags and linker flags from 'settings.arch' - + {% if arch_flag %} message(STATUS "Conan toolchain: Defining architecture flag: {{ arch_flag }}") string(APPEND CONAN_CXX_FLAGS " {{ arch_flag }}") string(APPEND CONAN_C_FLAGS " {{ arch_flag }}") string(APPEND CONAN_SHARED_LINKER_FLAGS " {{ arch_flag }}") string(APPEND CONAN_EXE_LINKER_FLAGS " {{ arch_flag }}") + {% endif %} + {% if arch_link_flag %} + message(STATUS "Conan toolchain: Defining architecture linker flag: {{ arch_link_flag }}") + string(APPEND CONAN_SHARED_LINKER_FLAGS " {{ arch_link_flag }}") + string(APPEND CONAN_EXE_LINKER_FLAGS " {{ arch_link_flag }}") + {% endif %} """) def context(self): arch_flag = architecture_flag(self._conanfile) - if not arch_flag: + arch_link_flag = architecture_link_flag(self._conanfile) + if not arch_flag and not arch_link_flag: return - return {"arch_flag": arch_flag} + return {"arch_flag": arch_flag, "arch_link_flag": arch_link_flag} class LinkerScriptsBlock(Block): diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py index bb3168df459..1b2ecd3c9b1 100644 --- a/conan/tools/gnu/autotoolstoolchain.py +++ b/conan/tools/gnu/autotoolstoolchain.py @@ -6,7 +6,7 @@ from conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags from conan.tools.build import cmd_args_to_string, save_toolchain_args from conan.tools.build.cross_building import cross_building -from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \ +from conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \ build_type_link_flags, libcxx_flags, cstd_flag, llvm_clang_front from conan.tools.env import Environment, VirtualBuildEnv from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet @@ -52,6 +52,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"): self.cppstd = cppstd_flag(self._conanfile) self.cstd = cstd_flag(self._conanfile) self.arch_flag = architecture_flag(self._conanfile) + self.arch_ld_flag = architecture_link_flag(self._conanfile) 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() @@ -223,7 +224,7 @@ def cflags(self): @property def ldflags(self): - ret = [self.arch_flag, self.sysroot_flag] + ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag] apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag] apple_flags += self.apple_extra_flags conf_flags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[], diff --git a/conan/tools/gnu/gnutoolchain.py b/conan/tools/gnu/gnutoolchain.py index d7cd0a3848f..3a478d96242 100644 --- a/conan/tools/gnu/gnutoolchain.py +++ b/conan/tools/gnu/gnutoolchain.py @@ -5,7 +5,7 @@ from conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags from conan.tools.build import cmd_args_to_string, save_toolchain_args from conan.tools.build.cross_building import cross_building -from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \ +from conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \ build_type_link_flags, \ libcxx_flags, llvm_clang_front from conan.tools.env import Environment, VirtualBuildEnv @@ -57,6 +57,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"): self.cppstd = cppstd_flag(self._conanfile) self.arch_flag = architecture_flag(self._conanfile) + self.arch_ld_flag = architecture_link_flag(self._conanfile) 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() @@ -288,7 +289,7 @@ def cflags(self): @property def ldflags(self): - ret = [self.arch_flag, self.sysroot_flag] + ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag] apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag] apple_flags += self.apple_extra_flags conf_flags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[], diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py index 8dd569ee4d4..c1f1e79edf7 100644 --- a/conan/tools/meson/toolchain.py +++ b/conan/tools/meson/toolchain.py @@ -9,7 +9,7 @@ from conan.tools.apple.apple import is_apple_os, apple_min_version_flag, \ resolve_apple_flags, apple_extra_flags from conan.tools.build.cross_building import cross_building -from conan.tools.build.flags import libcxx_flags, architecture_flag +from conan.tools.build.flags import architecture_link_flag, libcxx_flags, architecture_flag from conan.tools.env import VirtualBuildEnv from conan.tools.meson.helpers import * from conan.tools.meson.helpers import get_apple_subsystem @@ -216,6 +216,8 @@ def __init__(self, conanfile, backend=None, native=False): self.extra_defines = [] #: Architecture flag deduced by Conan and added to ``c_args``, ``cpp_args``, ``c_link_args`` and ``cpp_link_args`` self.arch_flag = architecture_flag(self._conanfile) # https://github.com/conan-io/conan/issues/17624 + #: Architecture link flag deduced by Conan and added to ``c_link_args`` and ``cpp_link_args`` + self.arch_link_flag = architecture_link_flag(self._conanfile) #: Dict-like object that defines Meson ``properties`` with ``key=value`` format self.properties = {} #: Dict-like object that defines Meson ``project options`` with ``key=value`` format @@ -459,7 +461,7 @@ def _get_extra_flags(self): return { "cxxflags": [self.arch_flag] + cxxflags + sys_root + self.extra_cxxflags, "cflags": [self.arch_flag] + cflags + sys_root + self.extra_cflags, - "ldflags": [self.arch_flag] + ld, + "ldflags": [self.arch_flag] + [self.arch_link_flag] + ld, "defines": [f"-D{d}" for d in (defines + self.extra_defines)] } diff --git a/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py b/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py index 7576aa6dd62..ca6dcde783d 100644 --- a/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py +++ b/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py @@ -285,6 +285,27 @@ def test_architecture_flag(config): assert expected in env["LDFLAGS"] assert "-debug" not in env["LDFLAGS"] +@pytest.mark.parametrize("config", [ + ("gcc", "x86_64", ""), + ("emcc", "wasm", ""), + ("emcc", "wasm64", ""), + ("emcc", "asm.js", "-sWASM=0")]) +def test_architecture_link_flag(config): + compiler, arch, expected = config + conanfile = ConanFileMock() + conanfile.settings = MockSettings( + {"build_type": "Release", + "os": "Emscripten", + "compiler": compiler, + "arch": arch}) + conanfile.settings_build = conanfile.settings + be = AutotoolsToolchain(conanfile) + assert be.arch_ld_flag == expected + env = be.vars() + assert "" in env["CXXFLAGS"] + assert "" in env["CFLAGS"] + assert expected in env["LDFLAGS"] + @pytest.mark.parametrize("compiler", ['msvc']) def test_build_type_flag(compiler):