Repository: conan-io/conan
Pull request #12889 (2023-01-11 15:05:44)

[AutotoolsToolchain] Improve `update_xxxxx_args` behavior
Changelog: Feature: AutotoolsToolchain helper functions: `update_configure_args`, `update_make_args`, and `update_autoreconf_args` can also add new values
Docs: https://github.com/conan-io/docs/pull/2895

Summary: before this change, it was only possible to update/remove existing values. Now, you could add new ones. Trying to avoid weird situations like:

```python
        tc = AutotoolsToolchain(self)
        tc.configure_args.extend([
            "--datarootdir=${prefix}/lib", # do not use share
            "--disable-layoutex",
            "--disable-layout"])
        tc.update_configure_args({"--force": None})
```
After my change, then it could be reduced to:
```python
        tc = AutotoolsToolchain(self)
        tc.update_configure_args({
            "--force": None,
            "--datarootdir": "${prefix}/lib", # do not use share
            "--disable-layoutex": "",
            "--disable-layout": ""})
```

Both are working, but I think the latest one could be the expected behavior. WDYT?


Patch:
diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py
index 61e159ea4..b870bd5b0 100644
--- a/conan/tools/gnu/autotoolstoolchain.py
+++ b/conan/tools/gnu/autotoolstoolchain.py
@@ -224,23 +224,28 @@ class AutotoolsToolchain:
 
     # 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)
+
+        def _list_to_dict(flags):
+            ret = {}
+            for flag in flags:
+                # Only splitting if "=" is there
+                option = flag.split("=", 1)
+                if len(option) == 2:
+                    ret[option[0]] = option[1]
                 else:
-                    _new_flags.append(f"{flag_name}={new_flag_value}")
-            else:
-                _new_flags.append(flag)
+                    ret[option[0]] = ""
+            return ret
+
+        def _dict_to_list(flags):
+            return [f"{k}={v}" if v else k for k, v in flags.items() if v is not None]
+
+        self_args = getattr(self, attr_name)
+        # FIXME: if xxxxx_args -> dict-type at some point, all these lines could be removed
+        options = _list_to_dict(self_args)
+        # Add/update/remove the current xxxxx_args with the new flags given
+        options.update(updated_flags)
         # Update the current ones
-        setattr(self, attr_name, _new_flags)
+        setattr(self, attr_name, _dict_to_list(options))
 
     def generate_args(self):
         args = {"configure_args": args_to_string(self.configure_args),


Test patch:
diff --git a/conans/test/unittests/tools/gnu/autotoolschain_test.py b/conans/test/unittests/tools/gnu/autotoolschain_test.py
index 026acc933..61a20034a 100644
--- a/conans/test/unittests/tools/gnu/autotoolschain_test.py
+++ b/conans/test/unittests/tools/gnu/autotoolschain_test.py
@@ -189,20 +189,22 @@ def test_check_configure_args_overwriting_and_deletion(save_args, cross_building
 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": ""})
+                              "--enable-flag1": "",  # without value
+                              "-NEW-FLAG": "no"  # new flag
+                              })
     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
+    assert "-NEW-FLAG=no" in new_configure_args  # new flag
     # 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"})
+    # Add new value to make_args
+    at.update_make_args({"--new-complex-flag": "new-value"})
     new_make_args = args_to_string(at.make_args)
-    assert "--complex-flag=new-value" in new_make_args
+    assert "--new-complex-flag=new-value" in new_make_args