Skip to content

Commit beb1754

Browse files
authored
Added architecture linker specific flags to toolchains (#18498)
Changelog: Feature: new linker flags autodetected by conan based on profile architecture Docs: omit In #18432 native `asmjs` architecture support was introduced. To enable `asmjs` code generation the `-sWASM=0` flag needs to be passed to the `emscripten linker`. That flag was added in `architecture_flag` without noticing that those flags were being passed to both compiler and linker across all toolchains. This was causing the compiler to throw warnings as this flag is only understood by the linker: ``` em++: warning: linker setting ignored during compilation: 'WASM' [-Wunused-command-line-argument] ``` Having a compilation warning is not desirable as a compilation with warning as errors will result in a build failure: ``` em++: error: linker setting ignored during compilation: 'WASM' [-Wunused-command-line-argument] [-Werror] ``` This PR aims to address this issue by creating a new `architecture_link_flags` which will return the required flags **only** for the linker based on the profile architecture. This function will be called by several toolchains which will bypass the result to the final linker by setting `LD_FLAGS`. #### Tests The current [`test_emcc`](https://github.com/conan-io/conan/blob/92b606909bd4fe04f5b3ea515130d31a8f0481da/test/functional/toolchains/emscripten/test_emcc.py) test suite already tests this new functionality added.
2 parents 1de03c9 + e2130f7 commit beb1754

File tree

6 files changed

+54
-12
lines changed

6 files changed

+54
-12
lines changed

conan/tools/build/flags.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,21 @@ def architecture_flag(conanfile):
6767
"e2k-v6": "-march=elbrus-v6",
6868
"e2k-v7": "-march=elbrus-v7"}.get(arch, "")
6969
elif compiler == "emcc":
70-
# Emscripten default output is WASM since 1.37.x (long time ago)
7170
if arch == "wasm64":
7271
return "-sMEMORY64=1"
72+
return ""
73+
74+
75+
def architecture_link_flag(conanfile):
76+
"""
77+
returns exclusively linker flags specific to the target architecture and compiler
78+
"""
79+
compiler = conanfile.settings.get_safe("compiler")
80+
arch = conanfile.settings.get_safe("arch")
81+
if compiler == "emcc":
82+
# Emscripten default output is WASM since 1.37.x (long time ago)
7383
# Deactivate WASM output forcing asm.js output instead
74-
elif arch == "asm.js":
84+
if arch == "asm.js":
7585
return "-sWASM=0"
7686
return ""
7787

conan/tools/cmake/toolchain/blocks.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from conan.tools.android.utils import android_abi
1111
from conan.tools.apple.apple import is_apple_os, to_apple_arch
1212
from conan.tools.build import build_jobs
13-
from conan.tools.build.flags import architecture_flag, libcxx_flags
13+
from conan.tools.build.flags import architecture_flag, architecture_link_flag, libcxx_flags
1414
from conan.tools.build.cross_building import cross_building
1515
from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME
1616
from conan.tools.cmake.utils import is_multi_configuration
@@ -238,19 +238,26 @@ def context(self):
238238
class ArchitectureBlock(Block):
239239
template = textwrap.dedent("""\
240240
# Define C++ flags, C flags and linker flags from 'settings.arch'
241-
241+
{% if arch_flag %}
242242
message(STATUS "Conan toolchain: Defining architecture flag: {{ arch_flag }}")
243243
string(APPEND CONAN_CXX_FLAGS " {{ arch_flag }}")
244244
string(APPEND CONAN_C_FLAGS " {{ arch_flag }}")
245245
string(APPEND CONAN_SHARED_LINKER_FLAGS " {{ arch_flag }}")
246246
string(APPEND CONAN_EXE_LINKER_FLAGS " {{ arch_flag }}")
247+
{% endif %}
248+
{% if arch_link_flag %}
249+
message(STATUS "Conan toolchain: Defining architecture linker flag: {{ arch_link_flag }}")
250+
string(APPEND CONAN_SHARED_LINKER_FLAGS " {{ arch_link_flag }}")
251+
string(APPEND CONAN_EXE_LINKER_FLAGS " {{ arch_link_flag }}")
252+
{% endif %}
247253
""")
248254

249255
def context(self):
250256
arch_flag = architecture_flag(self._conanfile)
251-
if not arch_flag:
257+
arch_link_flag = architecture_link_flag(self._conanfile)
258+
if not arch_flag and not arch_link_flag:
252259
return
253-
return {"arch_flag": arch_flag}
260+
return {"arch_flag": arch_flag, "arch_link_flag": arch_link_flag}
254261

255262

256263
class LinkerScriptsBlock(Block):

conan/tools/gnu/autotoolstoolchain.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags
77
from conan.tools.build import cmd_args_to_string, save_toolchain_args
88
from conan.tools.build.cross_building import cross_building
9-
from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
9+
from conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \
1010
build_type_link_flags, libcxx_flags, cstd_flag, llvm_clang_front
1111
from conan.tools.env import Environment, VirtualBuildEnv
1212
from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
@@ -52,6 +52,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
5252
self.cppstd = cppstd_flag(self._conanfile)
5353
self.cstd = cstd_flag(self._conanfile)
5454
self.arch_flag = architecture_flag(self._conanfile)
55+
self.arch_ld_flag = architecture_link_flag(self._conanfile)
5556
self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)
5657
self.fpic = self._conanfile.options.get_safe("fPIC")
5758
self.msvc_runtime_flag = self._get_msvc_runtime_flag()
@@ -223,7 +224,7 @@ def cflags(self):
223224

224225
@property
225226
def ldflags(self):
226-
ret = [self.arch_flag, self.sysroot_flag]
227+
ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag]
227228
apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
228229
apple_flags += self.apple_extra_flags
229230
conf_flags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[],

conan/tools/gnu/gnutoolchain.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags
66
from conan.tools.build import cmd_args_to_string, save_toolchain_args
77
from conan.tools.build.cross_building import cross_building
8-
from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
8+
from conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \
99
build_type_link_flags, \
1010
libcxx_flags, llvm_clang_front
1111
from conan.tools.env import Environment, VirtualBuildEnv
@@ -57,6 +57,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
5757

5858
self.cppstd = cppstd_flag(self._conanfile)
5959
self.arch_flag = architecture_flag(self._conanfile)
60+
self.arch_ld_flag = architecture_link_flag(self._conanfile)
6061
self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)
6162
self.fpic = self._conanfile.options.get_safe("fPIC")
6263
self.msvc_runtime_flag = self._get_msvc_runtime_flag()
@@ -288,7 +289,7 @@ def cflags(self):
288289

289290
@property
290291
def ldflags(self):
291-
ret = [self.arch_flag, self.sysroot_flag]
292+
ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag]
292293
apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
293294
apple_flags += self.apple_extra_flags
294295
conf_flags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[],

conan/tools/meson/toolchain.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from conan.tools.apple.apple import is_apple_os, apple_min_version_flag, \
1010
resolve_apple_flags, apple_extra_flags
1111
from conan.tools.build.cross_building import cross_building
12-
from conan.tools.build.flags import libcxx_flags, architecture_flag
12+
from conan.tools.build.flags import architecture_link_flag, libcxx_flags, architecture_flag
1313
from conan.tools.env import VirtualBuildEnv
1414
from conan.tools.meson.helpers import *
1515
from conan.tools.meson.helpers import get_apple_subsystem
@@ -216,6 +216,8 @@ def __init__(self, conanfile, backend=None, native=False):
216216
self.extra_defines = []
217217
#: Architecture flag deduced by Conan and added to ``c_args``, ``cpp_args``, ``c_link_args`` and ``cpp_link_args``
218218
self.arch_flag = architecture_flag(self._conanfile) # https://github.com/conan-io/conan/issues/17624
219+
#: Architecture link flag deduced by Conan and added to ``c_link_args`` and ``cpp_link_args``
220+
self.arch_link_flag = architecture_link_flag(self._conanfile)
219221
#: Dict-like object that defines Meson ``properties`` with ``key=value`` format
220222
self.properties = {}
221223
#: Dict-like object that defines Meson ``project options`` with ``key=value`` format
@@ -459,7 +461,7 @@ def _get_extra_flags(self):
459461
return {
460462
"cxxflags": [self.arch_flag] + cxxflags + sys_root + self.extra_cxxflags,
461463
"cflags": [self.arch_flag] + cflags + sys_root + self.extra_cflags,
462-
"ldflags": [self.arch_flag] + ld,
464+
"ldflags": [self.arch_flag] + [self.arch_link_flag] + ld,
463465
"defines": [f"-D{d}" for d in (defines + self.extra_defines)]
464466
}
465467

test/unittests/client/toolchain/autotools/autotools_toolchain_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,27 @@ def test_architecture_flag(config):
285285
assert expected in env["LDFLAGS"]
286286
assert "-debug" not in env["LDFLAGS"]
287287

288+
@pytest.mark.parametrize("config", [
289+
("gcc", "x86_64", ""),
290+
("emcc", "wasm", ""),
291+
("emcc", "wasm64", ""),
292+
("emcc", "asm.js", "-sWASM=0")])
293+
def test_architecture_link_flag(config):
294+
compiler, arch, expected = config
295+
conanfile = ConanFileMock()
296+
conanfile.settings = MockSettings(
297+
{"build_type": "Release",
298+
"os": "Emscripten",
299+
"compiler": compiler,
300+
"arch": arch})
301+
conanfile.settings_build = conanfile.settings
302+
be = AutotoolsToolchain(conanfile)
303+
assert be.arch_ld_flag == expected
304+
env = be.vars()
305+
assert "" in env["CXXFLAGS"]
306+
assert "" in env["CFLAGS"]
307+
assert expected in env["LDFLAGS"]
308+
288309

289310
@pytest.mark.parametrize("compiler", ['msvc'])
290311
def test_build_type_flag(compiler):

0 commit comments

Comments
 (0)