Skip to content

Commit

Permalink
[AutotoolsToolchain] Added helpers update_xxxx_args (#12884)
Browse files Browse the repository at this point in the history
* Fixed bad overwriting of configuration arguments

* Added target calculation and let users configure them

* Minor changes

* Added update_xxxx_args to add/prune flags effortlessly

* Typo

* Improved helpers

* Removed target triplet

* Fixed test
  • Loading branch information
franramirez688 authored Jan 11, 2023
1 parent 8894507 commit b0b6ab2
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 16 deletions.
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

0 comments on commit b0b6ab2

Please sign in to comment.