diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py index 9d6478d40db..45b6018bc1a 100644 --- a/conan/tools/meson/toolchain.py +++ b/conan/tools/meson/toolchain.py @@ -39,8 +39,9 @@ class MesonToolchain(object): {% endfor %} [binaries] - {% if c %}c = '{{c}}'{% endif %} - {% if cpp %}cpp = '{{cpp}}'{% endif %} + {% if c %}c = {{c}}{% endif %} + {% if cpp %}cpp = {{cpp}}{% endif %} + {% if ld %}ld = {{ld}}{% endif %} {% if is_apple_system %} {% if objc %}objc = '{{objc}}'{% endif %} {% if objcpp %}objcpp = '{{objcpp}}'{% endif %} @@ -190,13 +191,17 @@ def __init__(self, conanfile, backend=None): self.c = compilers_by_conf.get("c") or build_env.get("CC") or default_comp #: Defines the Meson ``cpp`` variable. Defaulted to ``CXX`` build environment value self.cpp = compilers_by_conf.get("cpp") or build_env.get("CXX") or default_comp_cpp + #: Defines the Meson ``ld`` variable. Defaulted to ``LD`` build environment value + self.ld = build_env.get("LD") # FIXME: Should we use the new tools.build:compiler_executables and avoid buildenv? - #: Defines the Meson ``c_ld`` variable. Defaulted to ``CC_LD`` or ``LD`` build + # Issue related: https://github.com/mesonbuild/meson/issues/6442 + # PR related: https://github.com/mesonbuild/meson/pull/6457 + #: Defines the Meson ``c_ld`` variable. Defaulted to ``CC_LD`` #: environment value - self.c_ld = build_env.get("CC_LD") or build_env.get("LD") - #: Defines the Meson ``cpp_ld`` variable. Defaulted to ``CXX_LD`` or ``LD`` build + self.c_ld = build_env.get("CC_LD") + #: Defines the Meson ``cpp_ld`` variable. Defaulted to ``CXX_LD`` #: environment value - self.cpp_ld = build_env.get("CXX_LD") or build_env.get("LD") + self.cpp_ld = build_env.get("CXX_LD") #: Defines the Meson ``ar`` variable. Defaulted to ``AR`` build environment value self.ar = build_env.get("AR") #: Defines the Meson ``strip`` variable. Defaulted to ``STRIP`` build environment value @@ -354,6 +359,12 @@ def _filter_list_empty_fields(v): return list(filter(bool, v)) def _context(self): + def _sanitize_format(v): + if v is None or isinstance(v, list): + return v + ret = [x.strip() for x in v.split() if x] + return f"'{ret[0]}'" if len(ret) == 1 else ret + apple_flags = self.apple_isysroot_flag + self.apple_arch_flag + self.apple_min_version_flag extra_flags = self._get_extra_flags() @@ -380,11 +391,11 @@ def _context(self): # https://mesonbuild.com/Machine-files.html#project-specific-options "project_options": {k: to_meson_value(v) for k, v in self.project_options.items()}, # https://mesonbuild.com/Builtin-options.html#directories - # TODO : we don't manage paths like libdir here (yet?) # https://mesonbuild.com/Machine-files.html#binaries # https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables - "c": self.c, - "cpp": self.cpp, + "c": _sanitize_format(self.c), + "cpp": _sanitize_format(self.cpp), + "ld": _sanitize_format(self.ld), "objc": self.objc, "objcpp": self.objcpp, "c_ld": self.c_ld, diff --git a/conans/test/functional/toolchains/meson/test_meson_build_require.py b/conans/test/functional/toolchains/meson/test_meson_build_require.py deleted file mode 100644 index c875fc95e7f..00000000000 --- a/conans/test/functional/toolchains/meson/test_meson_build_require.py +++ /dev/null @@ -1,48 +0,0 @@ -from conans.test.assets.genconanfile import GenConanfile -from conans.test.utils.tools import TestClient - - -def test_env_vars_from_build_require(): - br = str(GenConanfile().with_name("hello_compiler").with_version("1.0").with_import("import os")) - br += """ - def package_info(self): - {} - """ - vs = ["CC", "CC_LD", "CXX", "CXX_LD", "AR", "STRIP", "AS", "WINDRES", "PKG_CONFIG", "LD"] - lines = "\n ".join(['self.buildenv_info.define("{var}", "{var}_VALUE")'.format(var=var) - for var in vs]) - cf = br.format(lines) - - client = TestClient() - client.save({"conanfile.py": cf}) - client.run("create .") - - conanfile = GenConanfile().with_settings("os", "arch", "compiler", "build_type")\ - .with_name("consumer").with_version("1.0").with_generator("MesonToolchain")\ - .with_tool_requirement("hello_compiler/1.0") - client.save({"conanfile.py": conanfile}) - client.run("install . -pr:h=default -pr:b=default") - content = client.load("conan_meson_native.ini") - assert "c = 'CC_VALUE'" in content - assert "cpp = 'CXX_VALUE'" in content - assert "c_ld = 'CC_LD_VALUE'" in content - assert "cpp_ld = 'CXX_LD_VALUE'" in content - assert "ar = 'AR_VALUE'" in content - assert "strip = 'STRIP_VALUE'" in content - assert "as = 'AS_VALUE'" in content - assert "windres = 'WINDRES_VALUE'" in content - assert "pkgconfig = 'PKG_CONFIG_VALUE'" in content - - # Now change the build require to declare only LD - lines = '\n self.buildenv_info.define("LD", "LD_VALUE")' - cf = br.format(lines) - client = TestClient() - client.save({"conanfile.py": cf}) - client.run("create .") - - # Create the consumer again, now the LD env var will be applied - client.save({"conanfile.py": conanfile}) - client.run("install . -pr:h=default -pr:b=default") - content = client.load("conan_meson_native.ini") - assert "c_ld = 'LD_VALUE'" in content - assert "cpp_ld = 'LD_VALUE'" in content diff --git a/conans/test/integration/toolchains/meson/test_mesontoolchain.py b/conans/test/integration/toolchains/meson/test_mesontoolchain.py index 004640aa945..02afaba2ceb 100644 --- a/conans/test/integration/toolchains/meson/test_mesontoolchain.py +++ b/conans/test/integration/toolchains/meson/test_mesontoolchain.py @@ -4,6 +4,7 @@ import pytest from conan.tools.meson import MesonToolchain +from conans.test.assets.genconanfile import GenConanfile from conans.test.utils.tools import TestClient @@ -205,3 +206,80 @@ def test_clang_cl_vscrt(build_type, runtime, vscrt): t.run("install . -pr:h=profile -pr:b=profile") content = t.load(MesonToolchain.native_filename) assert f"b_vscrt = '{vscrt}'" in content + + +def test_env_vars_from_build_require(): + conanfile = textwrap.dedent(""" + from conan import ConanFile + import os + + class HelloConan(ConanFile): + name = 'hello_compiler' + version = '1.0' + def package_info(self): + self.buildenv_info.define("CC", "CC_VALUE") + self.buildenv_info.define("CC_LD", "CC_LD_VALUE") + self.buildenv_info.define("CXX", "CXX_VALUE") + self.buildenv_info.define("CXX_LD", "CXX_LD_VALUE") + self.buildenv_info.define("AR", "AR_VALUE") + self.buildenv_info.define("STRIP", "STRIP_VALUE") + self.buildenv_info.define("AS", "AS_VALUE") + self.buildenv_info.define("WINDRES", "WINDRES_VALUE") + self.buildenv_info.define("PKG_CONFIG", "PKG_CONFIG_VALUE") + self.buildenv_info.define("LD", "LD_VALUE") + """) + client = TestClient() + client.save({"conanfile.py": conanfile}) + client.run("create .") + + conanfile = textwrap.dedent(""" + from conan import ConanFile + class HelloConan(ConanFile): + name = 'consumer' + version = '1.0' + generators = "MesonToolchain" + settings = "os", "arch", "compiler", "build_type" + + def requirements(self): + self.tool_requires("hello_compiler/1.0", ) + """) + # Now, let's check how all the build env variables are applied at consumer side + client.save({"conanfile.py": conanfile}) + client.run("install . -pr:h=default -pr:b=default") + content = client.load("conan_meson_native.ini") + assert "c = 'CC_VALUE'" in content + assert "cpp = 'CXX_VALUE'" in content + assert "ld = 'LD_VALUE'" in content + assert "c_ld = 'CC_LD_VALUE'" in content + assert "cpp_ld = 'CXX_LD_VALUE'" in content + assert "ar = 'AR_VALUE'" in content + assert "strip = 'STRIP_VALUE'" in content + assert "as = 'AS_VALUE'" in content + assert "windres = 'WINDRES_VALUE'" in content + assert "pkgconfig = 'PKG_CONFIG_VALUE'" in content + + +def test_check_c_cpp_ld_list_formats(): + # Issue related: https://github.com/conan-io/conan/issues/14028 + profile = textwrap.dedent(""" + [settings] + os=Windows + arch=x86_64 + compiler=gcc + compiler.version=9 + compiler.cppstd=17 + compiler.libcxx=libstdc++11 + build_type=Release + [buildenv] + CC=aarch64-poky-linux-gcc -mcpu=cortex-a53 -march=armv8-a+crc+crypto + CXX=aarch64-poky-linux-g++ -mcpu=cortex-a53 -march=armv8-a+crc+crypto + LD=aarch64-poky-linux-ld --sysroot=/opt/sysroots/cortexa53-crypto-poky-linux + """) + t = TestClient() + t.save({"conanfile.txt": "[generators]\nMesonToolchain", + "profile": profile}) + t.run("install . -pr:h=profile -pr:b=profile") + content = t.load(MesonToolchain.native_filename) + assert "c = ['aarch64-poky-linux-gcc', '-mcpu=cortex-a53', '-march=armv8-a+crc+crypto']" in content + assert "cpp = ['aarch64-poky-linux-g++', '-mcpu=cortex-a53', '-march=armv8-a+crc+crypto']" in content + assert "ld = ['aarch64-poky-linux-ld', '--sysroot=/opt/sysroots/cortexa53-crypto-poky-linux']" in content