Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AutotoolsToolchain] Added helpers update_xxxx_args #12884

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 67 additions & 16 deletions conan/tools/gnu/autotoolstoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from conan.tools.env import Environment
from conan.tools.files.files import save_toolchain_args
from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
from conan.tools.microsoft import VCVars, is_msvc, msvc_runtime_flag
from conan.tools.microsoft import VCVars, msvc_runtime_flag
from conans.errors import ConanException
from conans.tools import args_to_string

Expand All @@ -18,10 +18,6 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
self._namespace = namespace
self._prefix = prefix

self.configure_args = self._default_configure_shared_flags() + self._default_configure_install_flags()
self.autoreconf_args = self._default_autoreconf_flags()
self.make_args = []

# Flags
self.extra_cxxflags = []
self.extra_cflags = []
Expand Down Expand Up @@ -55,12 +51,13 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
self.sysroot_flag = None

if cross_building(self._conanfile):
# Host triplet
os_build, arch_build, os_host, arch_host = get_cross_building_settings(self._conanfile)
compiler = self._conanfile.settings.get_safe("compiler")
if not self._host:
self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)
# Build triplet
self._build = _get_gnu_triplet(os_build, arch_build, compiler=compiler)

# Apple Stuff
if os_build == "Macos":
sdk_path = apple_sdk_path(conanfile)
Expand All @@ -74,6 +71,12 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
sysroot = sysroot.replace("\\", "/") if sysroot is not None else None
self.sysroot_flag = "--sysroot {}".format(sysroot) if sysroot else None

self.configure_args = self._default_configure_shared_flags() + \
self._default_configure_install_flags() + \
self._get_triplets()
self.autoreconf_args = self._default_autoreconf_flags()
self.make_args = []

check_using_build_profile(self._conanfile)

def _get_msvc_runtime_flag(self):
Expand Down Expand Up @@ -180,19 +183,67 @@ def _get_argument(argument_name, cppinfo_name):
_get_argument("datarootdir", "resdirs")])
return [el for el in configure_install_flags if el]

def _default_autoreconf_flags(self):
@staticmethod
def _default_autoreconf_flags():
return ["--force", "--install"]

def _get_triplets(self):
triplets = []
for flag, value in (("--host=", self._host), ("--build=", self._build),
("--target=", self._target)):
if value:
triplets.append(f'{flag}{value}')
return triplets

def update_configure_args(self, updated_flags):
"""
Helper to update/prune flags from ``self.configure_args``.

:param updated_flags: ``dict`` with arguments as keys and their argument values.
Notice that if argument value is ``None``, this one will be pruned.
"""
self._update_flags("configure_args", updated_flags)

def update_make_args(self, updated_flags):
"""
Helper to update/prune arguments from ``self.make_args``.

:param updated_flags: ``dict`` with arguments as keys and their argument values.
Notice that if argument value is ``None``, this one will be pruned.
"""
self._update_flags("make_args", updated_flags)

def update_autoreconf_args(self, updated_flags):
"""
Helper to update/prune arguments from ``self.autoreconf_args``.

:param updated_flags: ``dict`` with arguments as keys and their argument values.
Notice that if argument value is ``None``, this one will be pruned.
"""
self._update_flags("autoreconf_args", updated_flags)

# FIXME: Remove all these update_xxxx whenever xxxx_args are dicts or new ones replace them
def _update_flags(self, attr_name, updated_flags):
_new_flags = []
self_args = getattr(self, attr_name)
for index, flag in enumerate(self_args):
flag_name = flag.split("=")[0]
if flag_name in updated_flags:
new_flag_value = updated_flags[flag_name]
# if {"build": None} is passed, then "--build=xxxx" will be pruned
if new_flag_value is None:
continue
elif not new_flag_value:
_new_flags.append(flag_name)
else:
_new_flags.append(f"{flag_name}={new_flag_value}")
else:
_new_flags.append(flag)
# Update the current ones
setattr(self, attr_name, _new_flags)

def generate_args(self):
configure_args = []
configure_args.extend(self.configure_args)
user_args_str = args_to_string(self.configure_args)
for flag, var in (("host", self._host), ("build", self._build), ("target", self._target)):
if var and flag not in user_args_str:
configure_args.append('--{}={}'.format(flag, var))

args = {"configure_args": args_to_string(configure_args),
args = {"configure_args": args_to_string(self.configure_args),
"make_args": args_to_string(self.make_args),
"autoreconf_args": args_to_string(self.autoreconf_args)}

save_toolchain_args(args, namespace=self._namespace)
67 changes: 67 additions & 0 deletions conans/test/unittests/tools/gnu/autotoolschain_test.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
from unittest.mock import patch

import pytest

from conan.tools.gnu import AutotoolsToolchain
from conans.errors import ConanException
from conans.model.conf import Conf
from conans.test.utils.mocks import ConanFileMock, MockSettings
from conans.tools import args_to_string


@pytest.fixture()
def cross_building_conanfile():
settings_build = MockSettings({"os": "Linux",
"arch": "x86_64",
"compiler": "gcc",
"compiler.version": "11",
"compiler.libcxx": "libstdc++",
"build_type": "Release"})
settings_target = MockSettings({"os": "Android", "arch": "armv8"})
settings = MockSettings({"os": "Emscripten", "arch": "wasm"})
conanfile = ConanFileMock()
conanfile.settings = settings
conanfile.settings_build = settings_build
conanfile.settings_target = settings_target
return conanfile


def test_get_gnu_triplet_for_cross_building():
Expand Down Expand Up @@ -139,3 +159,50 @@ def test_linker_scripts():
env = autotoolschain.environment().vars(conanfile)
assert "-T'path_to_first_linker_script'" in env["LDFLAGS"]
assert "-T'path_to_second_linker_script'" in env["LDFLAGS"]


@patch("conan.tools.gnu.autotoolstoolchain.save_toolchain_args")
def test_check_configure_args_overwriting_and_deletion(save_args, cross_building_conanfile):
# Issue: https://github.com/conan-io/conan/issues/12642
at = AutotoolsToolchain(cross_building_conanfile)
at.configure_args.extend([
"--with-cross-build=my_path",
"--something-host=my_host"
])
at.generate_args()
configure_args = save_args.call_args[0][0]['configure_args']
assert "--build=x86_64-linux-gnu" in configure_args
assert "--host=wasm32-local-emscripten" in configure_args
assert "--with-cross-build=my_path" in configure_args
assert "--something-host=my_host" in configure_args
# https://github.com/conan-io/conan/issues/12431
at.configure_args.remove("--build=x86_64-linux-gnu")
at.configure_args.remove("--host=wasm32-local-emscripten")
at.generate_args()
configure_args = save_args.call_args[0][0]['configure_args']
assert "--build=x86_64-linux-gnu" not in configure_args # removed
assert "--host=wasm32-local-emscripten" not in configure_args # removed
assert "--with-cross-build=my_path" in configure_args
assert "--something-host=my_host" in configure_args


def test_update_or_prune_any_args(cross_building_conanfile):
at = AutotoolsToolchain(cross_building_conanfile)
at.configure_args.append("--enable-flag1=false")
at.make_args.append("--complex-flag=complex-value")
# Update configure_args
at.update_configure_args({"--prefix": "/my/other/prefix",
"--build": None, # prune value
"--enable-flag1": ""})
new_configure_args = args_to_string(at.configure_args)
assert "--prefix=/my/other/prefix" in new_configure_args
assert "--build=" not in new_configure_args # pruned
assert "--enable-flag1" in new_configure_args # flag without value
# Update autoreconf_args
at.update_autoreconf_args({"--force": None})
new_autoreconf_args = args_to_string(at.autoreconf_args)
assert "'--force" not in new_autoreconf_args
# Update make_args
at.update_make_args({"--complex-flag": "new-value"})
new_make_args = args_to_string(at.make_args)
assert "--complex-flag=new-value" in new_make_args