Today's changes:

2022-08-09  Bruno Haible  <br...@clisp.org>

        gnulib-tool.py: Finish implementing option --conditional-dependencies.
        * gnulib-tool.py (main) Accept options --conditional-dependencies,
        --no-conditional-dependencies.
        * pygnulib/GLModuleSystem.py (GLModuleTable.addConditional): Use
        str(module), not module, as key. Fix logic bug.
        (GLModuleTable.getCondition): Simplify.
        (GLModuleTable.transitive_closure): Show a warning when there are
        duplicate dependencies. Fix logic bug.
        (GLModuleTable.transitive_closure_separately): Simplify.
        (GLModuleTable.add_dummy): Ignore tests modules. Cope with multiple
        lib_SOURCES augmentation lines. Cope with comments at the end of a
        lib_SOURCES augmentation line. Add the dummy module at the end of the
        modules list.
        * pygnulib/GLTestDir.py (GLTestDir.execute): Remove the code that forces
        the dummy module to the end of the list.
        * pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Add code to
        terminate the shell functions. Add code for the dependencies from the
        unconditional to the conditional modules. Don't emit AM_CONDITIONAL for
        unconditional modules.

        gnulib-tool.py: Don't do license replacements in the autoconf snippets.
        * pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Remove fileassistant
        argument. Don't invoke the 'aux' transformer here. Don't produce Windows
        CR-LFs on Windows.
        (GLEmiter.autoconfSnippets): Remove fileassistant argument.
        * pygnulib/GLImport.py (GLImport.gnulib_comp): Update all callers.
        * pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.

        gnulib-tool.py: Fix some code generation details.
        * pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): When removing a
        lib_LDFLAGS line, remove also the newline. Fix regex that matches
        lib_SOMETHING. Add a newline after each '## begin gnulib module' line.
        Don't emit 'endif' lines without corresponding 'if'. When emitting a
        '+=' augmentation, make sure it does not get emitted a second time.
        Don't emit a blank line when there is no AM_CPPFLAGS augmentation.
        Update after getLink() changed. In the value of DEFAULT_TEXT_DOMAIN,
        backslash-escape the double-quotes. Don't produce Windows CR-LFs on
        Windows. Simplify.
        (GLEmiter.tests_Makefile_am): When removing a lib_LDFLAGS line, remove
        also the newline. Fix regex that matches lib_SOMETHING. Don't remove a
        blank line before EXTRA_DIST. Add a newline after each
        '## begin gnulib module' line. Set uses_subdirs also when there is a .c
        file in a subdir of tests/. When emitting a '+=' augmentation, make sure
        it does not get emitted a second time. Don't produce Windows CR-LFs on
        Windows. Simplify.
        * pygnulib/GLImport.py (GLImport.execute): Update after getLink()
        changed.

        gnulib-tool.py: Fixes for conditional dependencies.
        * pygnulib/GLModuleSystem.py (GLModule.shell_id_chars): New constant.
        (GLModule.getShellFunc): Don't use md5 just because of an '_' character.
        (GLModule.getShellVar): Likewise.
        (GLModule.getConditionalName): Include a newline in the md5 input.
        * pygnulib/constants.py (ALPHANUMERIC): Remove constant.

        gnulib-tool.py: Refactor.
        * pygnulib/GLModuleSystem.py (GLModule.getLicense): Separate the warning
        logic from the result logic.

>From d0e094317bbf34413e458f9551543335b6eb8cef Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Mon, 8 Aug 2022 18:42:45 +0200
Subject: [PATCH 1/5] gnulib-tool.py: Refactor.

* pygnulib/GLModuleSystem.py (GLModule.getLicense): Separate the warning
logic from the result logic.
---
 ChangeLog                  |  6 ++++++
 pygnulib/GLModuleSystem.py | 21 +++++++++++----------
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5dc57dc4f8..596f629316 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2022-08-09  Bruno Haible  <br...@clisp.org>
+
+	gnulib-tool.py: Refactor.
+	* pygnulib/GLModuleSystem.py (GLModule.getLicense): Separate the warning
+	logic from the result logic.
+
 2022-08-09  Paul Eggert  <egg...@cs.ucla.edu>
 
 	largefile, year2038: simplify if Autoconf 2.72
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 19d13d213b..13d6a72231 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -651,23 +651,24 @@ class GLModule(object):
 
         Get license and warn user if module lacks a license.'''
         if 'license' not in self.cache:
-            result = None
+            license = self.getLicense_Raw().strip()
+            # Warn if the License field is missing.
+            if not self.isTests():
+                if not license:
+                    if self.config['errors']:
+                        raise GLError(18, str(self))
+                    else:  # if not self.config['errors']
+                        sys.stderr.write('gnulib-tool: warning: module %s lacks a License\n' % str(self))
             if str(self) == 'parse-datetime':
                 # This module is under a weaker license only for the purpose of some
                 # users who hand-edit it and don't use gnulib-tool. For the regular
                 # gnulib users they are under a stricter license.
                 result = 'GPL'
             else:
-                license = self.getLicense_Raw().strip()
-                if not self.isTests():
-                    if not license:
-                        if self.config['errors']:
-                            raise GLError(18, str(self))
-                        else:  # if not self.config['errors']
-                            sys.stderr.write('gnulib-tool: warning: module %s lacks a license\n' % str(self))
-                if not license:
-                    license = 'GPL'
                 result = license
+                # The default is GPL.
+                if not result:
+                    result = 'GPL'
             self.cache['license'] = result
         return self.cache['license']
 
-- 
2.34.1

>From 501feeb5d595d8b4cea9a1a8e404277c27d2f5bf Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Mon, 8 Aug 2022 21:22:15 +0200
Subject: [PATCH 2/5] gnulib-tool.py: Fixes for conditional dependencies.

* pygnulib/GLModuleSystem.py (GLModule.shell_id_chars): New constant.
(GLModule.getShellFunc): Don't use md5 just because of an '_' character.
(GLModule.getShellVar): Likewise.
(GLModule.getConditionalName): Include a newline in the md5 input.
* pygnulib/constants.py (ALPHANUMERIC): Remove constant.
---
 ChangeLog                  |  7 ++++
 pygnulib/GLModuleSystem.py | 70 ++++++++++++++++++++------------------
 pygnulib/constants.py      |  3 --
 3 files changed, 44 insertions(+), 36 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 596f629316..091af1f974 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2022-08-09  Bruno Haible  <br...@clisp.org>
 
+	gnulib-tool.py: Fixes for conditional dependencies.
+	* pygnulib/GLModuleSystem.py (GLModule.shell_id_chars): New constant.
+	(GLModule.getShellFunc): Don't use md5 just because of an '_' character.
+	(GLModule.getShellVar): Likewise.
+	(GLModule.getConditionalName): Include a newline in the md5 input.
+	* pygnulib/constants.py (ALPHANUMERIC): Remove constant.
+
 	gnulib-tool.py: Refactor.
 	* pygnulib/GLModuleSystem.py (GLModule.getLicense): Separate the warning
 	logic from the result logic.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 13d6a72231..9bfd5bd266 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -183,6 +183,9 @@ class GLModule(object):
                    + 'Makefile\\.am|Include|Link|License|Maintainer):$',
                    re.M)
 
+    # List of characters allowed in shell identifiers.
+    shell_id_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
+
     def __init__(self, config, path, patched=False):
         '''GLModule.__init__(config, path[, patched]) -> GLModule
 
@@ -329,20 +332,19 @@ class GLModule(object):
 
         Computes the shell function name that will contain the m4 macros for the
         module.'''
-        isalnum = True
         macro_prefix = self.config['macro_prefix']
-        for char in str(module):
-            if char not in constants.ALPHANUMERIC:
-                isalnum = False
+        valid_shell_id = True
+        for char in self.getName():
+            if char not in GLModule.shell_id_chars:
+                valid_shell_id = False
                 break
-        if isalnum:
-            module = str(self)
-        else:  # if not isalnum
-            module = '%s\n' % str(self)
-            if type(module) is str:
-                module = module.encode(ENCS['default'])
-            module = hashlib.md5(module).hexdigest()
-        result = 'func_%s_gnulib_m4code_%s' % (macro_prefix, module)
+        identifier = None
+        if valid_shell_id:
+            identifier = self.getName()
+        else:
+            hash_input = '%s\n' % self.getName()
+            identifier = hashlib.md5(hash_input.encode(ENCS['default'])).hexdigest()
+        result = 'func_%s_gnulib_m4code_%s' % (macro_prefix, identifier)
         return result
 
     def getShellVar(self):
@@ -350,20 +352,19 @@ class GLModule(object):
 
         Compute the shell variable name the will be set to true once the m4 macros
         for the module have been executed.'''
-        isalnum = True
         macro_prefix = self.config['macro_prefix']
-        for char in str(module):
-            if char not in constants.ALPHANUMERIC:
-                isalnum = False
+        valid_shell_id = True
+        for char in self.getName():
+            if char not in GLModule.shell_id_chars:
+                valid_shell_id = False
                 break
-        if isalnum:
-            module = str(self)
-        else:  # if not isalnum
-            module = '%s\n' % str(self)
-            if type(module) is str:
-                module = module.encode(ENCS['default'])
-            module = hashlib.md5(module).hexdigest()
-        result = '%s_gnulib_enabled_%s' % (macro_prefix, module)
+        identifier = None
+        if valid_shell_id:
+            identifier = self.getName()
+        else:
+            hash_input = '%s\n' % self.getName()
+            identifier = hashlib.md5(hash_input.encode(ENCS['default'])).hexdigest()
+        result = '%s_gnulib_enabled_%s' % (macro_prefix, identifier)
         return result
 
     def getConditionalName(self):
@@ -372,15 +373,18 @@ class GLModule(object):
         Return the automake conditional name.
         GLConfig: macro_prefix.'''
         macro_prefix = self.config['macro_prefix']
-        nonascii = [ char
-                     for char in self.getName()
-                     if char not in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' ]
-        if nonascii:
-            name = self.getName().encode(ENCS['default'])
-            name = hashlib.md5(name).hexdigest()
-            conditional = '%s_GNULIB_ENABLED_%s' % (macro_prefix, name)
-        else:  # if not nonascii
-            result = '%s_GNULIB_ENABLED_%s' % (macro_prefix, name)
+        valid_shell_id = True
+        for char in self.getName():
+            if char not in GLModule.shell_id_chars:
+                valid_shell_id = False
+                break
+        identifier = None
+        if valid_shell_id:
+            identifier = self.getName()
+        else:
+            hash_input = '%s\n' % self.getName()
+            identifier = hashlib.md5(hash_input.encode(ENCS['default'])).hexdigest()
+        result = '%s_GNULIB_ENABLED_%s' % (macro_prefix, identifier)
         return result
 
     def getDescription(self):
diff --git a/pygnulib/constants.py b/pygnulib/constants.py
index ba0ebc9942..ae27d8d41a 100644
--- a/pygnulib/constants.py
+++ b/pygnulib/constants.py
@@ -57,9 +57,6 @@ MODES = dict()  # Modes
 TESTS = dict()  # Tests
 NL = '''
 '''  # Newline character
-ALPHANUMERIC = 'abcdefghijklmnopqrstuvwxyz\
-ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-0123456789'  # Alphanumeric characters
 
 # Set ENCS dictionary
 if not hasattr(interpreter, '__file__'):
-- 
2.34.1

>From 98e7ca354a1108b0b99236e29bedbc6bfbd8593e Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 9 Aug 2022 16:11:09 +0200
Subject: [PATCH 3/5] gnulib-tool.py: Fix some code generation details.

* pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): When removing a
lib_LDFLAGS line, remove also the newline. Fix regex that matches
lib_SOMETHING. Add a newline after each '## begin gnulib module' line.
Don't emit 'endif' lines without corresponding 'if'. When emitting a
'+=' augmentation, make sure it does not get emitted a second time.
Don't emit a blank line when there is no AM_CPPFLAGS augmentation.
Update after getLink() changed. In the value of DEFAULT_TEXT_DOMAIN,
backslash-escape the double-quotes. Don't produce Windows CR-LFs on
Windows. Simplify.
(GLEmiter.tests_Makefile_am): When removing a lib_LDFLAGS line, remove
also the newline. Fix regex that matches lib_SOMETHING. Don't remove a
blank line before EXTRA_DIST. Add a newline after each
'## begin gnulib module' line. Set uses_subdirs also when there is a .c
file in a subdir of tests/. When emitting a '+=' augmentation, make sure
it does not get emitted a second time. Don't produce Windows CR-LFs on
Windows. Simplify.
* pygnulib/GLImport.py (GLImport.execute): Update after getLink()
changed.
---
 ChangeLog            |  20 +++++
 pygnulib/GLEmiter.py | 203 +++++++++++++++++++++----------------------
 pygnulib/GLImport.py |  16 ++--
 3 files changed, 125 insertions(+), 114 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 091af1f974..50ef82d525 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2022-08-09  Bruno Haible  <br...@clisp.org>
 
+	gnulib-tool.py: Fix some code generation details.
+	* pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): When removing a
+	lib_LDFLAGS line, remove also the newline. Fix regex that matches
+	lib_SOMETHING. Add a newline after each '## begin gnulib module' line.
+	Don't emit 'endif' lines without corresponding 'if'. When emitting a
+	'+=' augmentation, make sure it does not get emitted a second time.
+	Don't emit a blank line when there is no AM_CPPFLAGS augmentation.
+	Update after getLink() changed. In the value of DEFAULT_TEXT_DOMAIN,
+	backslash-escape the double-quotes. Don't produce Windows CR-LFs on
+	Windows. Simplify.
+	(GLEmiter.tests_Makefile_am): When removing a lib_LDFLAGS line, remove
+	also the newline. Fix regex that matches lib_SOMETHING. Don't remove a
+	blank line before EXTRA_DIST. Add a newline after each
+	'## begin gnulib module' line. Set uses_subdirs also when there is a .c
+	file in a subdir of tests/. When emitting a '+=' augmentation, make sure
+	it does not get emitted a second time. Don't produce Windows CR-LFs on
+	Windows. Simplify.
+	* pygnulib/GLImport.py (GLImport.execute): Update after getLink()
+	changed.
+
 	gnulib-tool.py: Fixes for conditional dependencies.
 	* pygnulib/GLModuleSystem.py (GLModule.shell_id_chars): New constant.
 	(GLModule.getShellFunc): Don't use md5 just because of an '_' character.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index a02b44bdd5..1a15fc4918 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -655,29 +655,34 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         if libtool:
             libext = 'la'
             perhapsLT = 'LT'
-            LD_flags = False
+            eliminate_LDFLAGS = False
         else:  # if not libtool
             libext = 'a'
             perhapsLT = ''
-            LD_flags = True
+            eliminate_LDFLAGS = True
         if for_test:
             # When creating a package for testing: Attempt to provoke failures,
             # especially link errors, already during "make" rather than during
             # "make check", because "make check" is not possible in a cross-compiling
             # situation. Turn check_PROGRAMS into noinst_PROGRAMS.
-            check_PROGRAMS = True
+            edit_check_PROGRAMS = True
         else:  # if not for_test
-            check_PROGRAMS = False
+            edit_check_PROGRAMS = False
         emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n"
         emit += "## Process this file with automake to produce Makefile.in.\n"
         emit += self.copyright_notice()
         if actioncmd:
+            # The maximum line length (excluding the terminating newline) of
+            # any file that is to be preprocessed by config.status is 3070.
+            # config.status uses awk, and the HP-UX 11.00 awk fails if a line
+            # has length >= 3071; similarly, the IRIX 6.5 awk fails if a line
+            # has length >= 3072.
             if len(actioncmd) <= 3000:
                 emit += "# Reproduce by: %s\n" % actioncmd
         emit += '\n'
         uses_subdirs = False
 
-        # Modify allsnippets variable.
+        # Compute allsnippets variable.
         allsnippets = ''
         for module in modules:
             if not module.isTests():
@@ -685,16 +690,16 @@ AC_DEFUN([%V1%_LIBSOURCES], [
                 amsnippet1 = module.getAutomakeSnippet_Conditional()
                 amsnippet1 = amsnippet1.replace('lib_LIBRARIES', 'lib%_LIBRARIES')
                 amsnippet1 = amsnippet1.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES')
-                if LD_flags:
-                    pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*)$', re.M)
+                if eliminate_LDFLAGS:
+                    pattern = re.compile('^(lib_LDFLAGS[\t ]*\\+=.*$\n)', re.M)
                     amsnippet1 = pattern.sub('', amsnippet1)
-                pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
+                pattern = re.compile('lib_([A-Z][A-Z]*)', re.M)
                 amsnippet1 = pattern.sub('%s_%s_\\1' % (libname, libext),
                                          amsnippet1)
                 amsnippet1 = amsnippet1.replace('$(GNULIB_', '$(' + module_indicator_prefix + '_GNULIB_')
                 amsnippet1 = amsnippet1.replace('lib%_LIBRARIES', 'lib_LIBRARIES')
                 amsnippet1 = amsnippet1.replace('lib%_LTLIBRARIES', 'lib_LTLIBRARIES')
-                if check_PROGRAMS:
+                if edit_check_PROGRAMS:
                     amsnippet1 = amsnippet1.replace('check_PROGRAMS', 'noinst_PROGRAMS')
                 amsnippet1 = amsnippet1.replace('${gl_include_guard_prefix}',
                                                 include_guard_prefix)
@@ -706,29 +711,33 @@ AC_DEFUN([%V1%_LIBSOURCES], [
 
                 # Get unconditional snippet, edit it and save to amsnippet2.
                 amsnippet2 = module.getAutomakeSnippet_Unconditional()
-                pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
+                pattern = re.compile('lib_([A-Z][A-Z]*)', re.M)
                 amsnippet2 = pattern.sub('%s_%s_\\1' % (libname, libext),
                                          amsnippet2)
                 amsnippet2 = amsnippet2.replace('$(GNULIB_',
                                                 '$(' + module_indicator_prefix + '_GNULIB_')
+                # Skip the contents if it's entirely empty.
                 if not (amsnippet1 + amsnippet2).isspace():
-                    allsnippets += '## begin gnulib module %s\n' % str(module)
+                    allsnippets += '## begin gnulib module %s\n\n' % str(module)
                     if conddeps:
                         if moduletable.isConditional(module):
                             name = module.getConditionalName()
                             allsnippets += 'if %s\n' % name
                     allsnippets += amsnippet1
                     if conddeps:
-                        allsnippets += 'endif\n'
+                        if moduletable.isConditional(module):
+                            allsnippets += 'endif\n'
                     allsnippets += amsnippet2
                     allsnippets += '## end   gnulib module %s\n\n' % str(module)
 
                     # Test whether there are some source files in subdirectories.
                     for file in module.getFiles():
-                        if (file.startswith('lib/') and file.endswith('.c')
+                        if (file.startswith('lib/')
+                                and file.endswith('.c')
                                 and file.count('/') > 1):
                             uses_subdirs = True
                             break
+
         if not makefile_name:
             subdir_options = ''
             # If there are source files in subdirectories, prevent collision of the
@@ -762,53 +771,50 @@ AC_DEFUN([%V1%_LIBSOURCES], [
             emit += 'MAINTAINERCLEANFILES =\n'
 
         # Execute edits that apply to the Makefile.am being generated.
-        current_edit = int()
-        makefile_am_edits = makefiletable.count()
-        while current_edit != makefile_am_edits:
+        for current_edit in range(0, makefiletable.count()):
             dictionary = makefiletable[current_edit]
             if dictionary['var']:
-                paths = list()
-                paths += [joinpath(dictionary['dir'], 'Makefile.am')]
-                paths += [os.path.normpath('./%s/Makefile.am' % dictionary['dir'])]
-                paths = sorted(set(paths))
-                if destfile in paths:
-                    emit += '%s += %s\n' % (dictionary['var'],
-                                            dictionary['val'])
-            current_edit += 1
+                if destfile == joinpath(dictionary['dir'], 'Makefile.am'):
+                    emit += '%s += %s\n' % (dictionary['var'], dictionary['val'])
+                    dictionary.pop('var')
 
         # Define two parts of cppflags variable.
-        emit += '\n'
         cppflags_part1 = ''
-        cppflags_part2 = ''
         if witness_c_macro:
             cppflags_part1 = ' -D%s=1' % witness_c_macro
+        cppflags_part2 = ''
         if for_test:
             cppflags_part2 = ' -DGNULIB_STRICT_CHECKING=1'
         cppflags = '%s%s' % (cppflags_part1, cppflags_part2)
         if not makefile_name:
+            emit += '\n'
             emit += 'AM_CPPFLAGS =%s\n' % cppflags
             emit += 'AM_CFLAGS =\n'
         else:  # if makefile_name
             if cppflags:
+                emit += '\n'
                 emit += 'AM_CPPFLAGS +=%s\n' % cppflags
         emit += '\n'
 
-        # One of the snippets or the user's Makefile.am already specifies an
+        # Test if one of the snippets or the user's Makefile.am already specifies an
         # installation location for the library. Don't confuse automake by saying
         # it should not be installed.
         # First test if allsnippets already specify an installation location.
-        insnippets = False
-        inmakefile = False
+        lib_gets_installed = False
         regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s\\.%s' % (perhapsLT, libname, libext)
         pattern = re.compile(regex, re.M)
-        insnippets = bool(pattern.findall(allsnippets))
-        # Then test if $sourcebase/Makefile.am (if it exists) specifies it.
-        path = joinpath(sourcebase, 'Makefile.am')
-        if makefile_name and isfile(path):
-            with codecs.open(path, 'rb', 'UTF-8') as file:
-                data = file.read()
-            inmakefile = bool(pattern.findall(data))
-        if not any([insnippets, inmakefile]):
+        if pattern.findall(allsnippets):
+            lib_gets_installed = True
+        else:
+            # Then test if $sourcebase/Makefile.am (if it exists) specifies it.
+            if makefile_name:
+                path = joinpath(sourcebase, 'Makefile.am')
+                if isfile(path):
+                    with codecs.open(path, 'rb', 'UTF-8') as file:
+                        data = file.read()
+                    if pattern.findall(data):
+                        lib_gets_installed = True
+        if not lib_gets_installed:
             # By default, the generated library should not be installed.
             emit += 'noinst_%sLIBRARIES += %s.%s\n' % (perhapsLT, libname, libext)
 
@@ -824,22 +830,22 @@ AC_DEFUN([%V1%_LIBSOURCES], [
             emit += '%s_%s_LDFLAGS += -no-undefined\n' % (libname, libext)
             # Synthesize an ${libname}_${libext}_LDFLAGS augmentation by combining
             # the link dependencies of all modules.
-            links = [module.getLink()
-                     for module in modules if not module.isTests()]
-            ulinks = list()
-            for link in links:
-                for lib in link:
-                    lib = constants.nlremove(lib)
-                    position = lib.find(' when linking with libtool')
-                    if position != -1:
-                        lib = lib[:position]
-                    ulinks += [lib]
-            ulinks = sorted(set(ulinks))
-            for link in ulinks:
-                emit += '%s_%s_LDFLAGS += %s\n' % (libname, libext, link)
+            links = [ module.getLink()
+                      for module in modules
+                      if not module.isTests() ]
+            lines = [ line
+                      for link in links
+                      for line in link.split('\n')
+                      if line != '' ]
+            pattern = re.compile(' when linking with libtool.*')
+            lines = [ pattern.sub('', line)
+                      for line in lines ]
+            lines = sorted(set(lines))
+            for line in lines:
+                emit += '%s_%s_LDFLAGS += %s\n' % (libname, libext, line)
         emit += '\n'
         if pobase:
-            emit += 'AM_CPPFLAGS += -DDEFAULT_TEXT_DOMAIN="%s-gnulib"\n' % podomain
+            emit += 'AM_CPPFLAGS += -DDEFAULT_TEXT_DOMAIN=\\"%s-gnulib\\"\n' % podomain
             emit += '\n'
         allsnippets = allsnippets.replace('$(top_srcdir)/build-aux/',
                                           '$(top_srcdir)/%s/' % auxdir)
@@ -852,7 +858,6 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         emit += '\t  fi; \\\n'
         emit += '\tdone; \\\n'
         emit += '\t:\n'
-        emit = constants.nlconvert(emit)
         result = tuple([emit, uses_subdirs])
         return result
 
@@ -913,19 +918,19 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         if libtool:
             libext = 'la'
             perhapsLT = 'LT'
-            LD_flags = False
+            eliminate_LDFLAGS = False
         else:  # if not libtool
             libext = 'a'
             perhapsLT = ''
-            LD_flags = True
+            eliminate_LDFLAGS = True
         if for_test:
             # When creating a package for testing: Attempt to provoke failures,
             # especially link errors, already during "make" rather than during
             # "make check", because "make check" is not possible in a cross-compiling
             # situation. Turn check_PROGRAMS into noinst_PROGRAMS.
-            check_PROGRAMS = True
+            edit_check_PROGRAMS = True
         else:  # if not for_test
-            check_PROGRAMS = False
+            edit_check_PROGRAMS = False
 
         # Calculate testsbase_inverse
         counter = int()
@@ -945,22 +950,22 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         longrun_snippets = ''
         for module in modules:
             if for_test and not single_configure:
-                flag = module.isTests()
+                accept = module.isTests()
             else:  # if for_test and not single_configure
-                flag = True
-            if flag:
+                accept = True
+            if accept:
                 snippet = module.getAutomakeSnippet()
                 snippet = snippet.replace('lib_LIBRARIES', 'lib%_LIBRARIES')
                 snippet = snippet.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES')
-                if LD_flags:
-                    pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*)$', re.M)
-                    snippet = pattern.sub('', snippet)
-                pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
+                if eliminate_LDFLAGS:
+                    pattern = re.compile('^(lib_LDFLAGS[\t ]*\\+=.*$\n)', re.M)
+                    amsnippet1 = pattern.sub('', snippet)
+                pattern = re.compile('lib_([A-Z][A-Z]*)', re.M)
                 snippet = pattern.sub('libtests_a_\\1', snippet)
                 snippet = snippet.replace('$(GNULIB_', '$(' + module_indicator_prefix + '_GNULIB_')
                 snippet = snippet.replace('lib%_LIBRARIES', 'lib_LIBRARIES')
                 snippet = snippet.replace('lib%_LTLIBRARIES', 'lib_LTLIBRARIES')
-                if check_PROGRAMS:
+                if edit_check_PROGRAMS:
                     snippet = snippet.replace('check_PROGRAMS', 'noinst_PROGRAMS')
                 snippet = snippet.replace('${gl_include_guard_prefix}',
                                           include_guard_prefix)
@@ -970,28 +975,20 @@ AC_DEFUN([%V1%_LIBSOURCES], [
                     snippet += 'libtests_a_DEPENDENCIES += @%sALLOCA@\n' % perhapsLT
 
                 # Skip the contents if it's entirely empty.
-                if snippet.strip():
-                    # Check status of the module.
-                    statuses = module.getStatuses()
-                    islongrun = False
-                    for word in statuses:
-                        if word == 'longrunning-test':
-                            islongrun = True
-                            break
-                    if not islongrun:
-                        snippet = snippet.replace('\n\nEXTRA_DIST', '\nEXTRA_DIST')
-                        main_snippets += '## begin gnulib module %s\n' % str(module)
-                        main_snippets += snippet
-                        main_snippets += '## end   gnulib module %s\n\n' % str(module)
-                    else:  # if islongrunning
-                        snippet = snippet.replace('\n\nEXTRA_DIST', '\nEXTRA_DIST')
-                        longrun_snippets += '## begin gnulib module %s\n' % str(module)
+                if not snippet.isspace():
+                    snippet = ('## begin gnulib module %s\n\n' % str(module)
+                               + snippet
+                               + '## end   gnulib module %s\n\n' % str(module))
+                    # Mention long-running tests at the end.
+                    if 'longrunning-test' in module.getStatuses():
                         longrun_snippets += snippet
-                        longrun_snippets += '## end gnulib module %s\n' % str(module)
+                    else:
+                        main_snippets += snippet
 
                     # Test whether there are some source files in subdirectories.
                     for file in module.getFiles():
-                        if (file.startswith('lib/') and file.endswith('.c')
+                        if ((file.startswith('lib/') or file.startswith('tests/'))
+                                and file.endswith('.c')
                                 and file.count('/') > 1):
                             uses_subdirs = True
                             break
@@ -1031,7 +1028,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         #  * https://debbugs.gnu.org/11030
         # So we need this workaround.
         pattern = re.compile('^pkgdata_DATA *\\+=', re.M)
-        if bool(pattern.findall(main_snippets)) or bool(pattern.findall(longrun_snippets)):
+        if pattern.findall(main_snippets) or pattern.findall(longrun_snippets):
             emit += 'pkgdata_DATA =\n'
 
         emit += 'EXTRA_DIST =\n'
@@ -1044,20 +1041,12 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         emit += 'MAINTAINERCLEANFILES =\n'
 
         # Execute edits that apply to the Makefile.am being generated.
-        # Execute edits that apply to the Makefile.am being generated.
-        current_edit = int()
-        makefile_am_edits = makefiletable.count()
-        while current_edit != makefile_am_edits:
+        for current_edit in range(0, makefiletable.count()):
             dictionary = makefiletable[current_edit]
             if dictionary['var']:
-                paths = list()
-                paths += [joinpath(dictionary['dir'], 'Makefile.am')]
-                paths += [os.path.normpath('./%s/Makefile.am' % dictionary['dir'])]
-                paths = sorted(set(paths))
-                if destfile in paths:
-                    emit += '%s += %s\n' % (dictionary['var'],
-                                            dictionary['val'])
-            current_edit += 1
+                if destfile == joinpath(dictionary['dir'], 'Makefile.am'):
+                    emit += '%s += %s\n' % (dictionary['var'], dictionary['val'])
+                    dictionary.pop('var')
 
         emit += '\nAM_CPPFLAGS = \\\n'
         if for_test:
@@ -1071,6 +1060,8 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         emit += '  -I%s/%s -I$(srcdir)/%s/%s\n' % (testsbase_inverse, sourcebase, testsbase_inverse, sourcebase)
         emit += '\n'
 
+        ldadd_before = ''
+        ldadd_after = ''
         if libtests:
             # All test programs need to be linked with libtests.a.
             # It needs to be passed to the linker before ${libname}.${libext},
@@ -1081,11 +1072,13 @@ AC_DEFUN([%V1%_LIBSOURCES], [
             # voluntarily omitted).
             # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, it
             # does not matter.
-            emit += 'LDADD = libtests.a %s/%s/%s.%s libtests.a %s/%s/%s.%s libtests.a $(LIBTESTS_LIBDEPS)\n\n' \
-                    % (testsbase_inverse, sourcebase, libname, libext,
-                       testsbase_inverse, sourcebase, libname, libext)
-        else:
-            emit += 'LDADD = %s/%s/%s.%s\n\n' % (testsbase_inverse, sourcebase, libname, libext)
+            ldadd_before = ' libtests.a'
+            ldadd_after = ' libtests.a $(LIBTESTS_LIBDEPS)'
+        emit += 'LDADD =%s %s/%s/%s.%s libtests.a %s/%s/%s.%s%s\n\n' \
+                % (ldadd_before,
+                   testsbase_inverse, sourcebase, libname, libext,
+                   testsbase_inverse, sourcebase, libname, libext,
+                   ldadd_after)
         if libtests:
             emit += 'libtests_a_SOURCES =\n'
             # Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However,
@@ -1099,11 +1092,10 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         # EXEEXT is defined by AC_PROG_CC through autoconf.
         # srcdir is defined by autoconf and automake.
         emit += "TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'\n\n"
-        main_snippets = main_snippets.replace('$(top_srcdir)/build-aux/',
-                                              '$(top_srcdir)/%s/' % auxdir)
-        longrun_snippets = longrun_snippets.replace('$(top_srcdir)/build-aux/',
-                                                    '$(top_srcdir)/%s/' % auxdir)
-        emit += main_snippets + longrun_snippets
+        all_snippets = main_snippets + longrun_snippets
+        all_snippets = all_snippets.replace('$(top_srcdir)/build-aux/',
+                                            '$(top_srcdir)/%s/' % auxdir)
+        emit += all_snippets
         emit += '# Clean up after Solaris cc.\n'
         emit += 'clean-local:\n'
         emit += '\trm -rf SunWS_cache\n\n'
@@ -1114,6 +1106,5 @@ AC_DEFUN([%V1%_LIBSOURCES], [
         emit += '\t  fi; \\\n'
         emit += '\tdone; \\\n'
         emit += '\t:\n'
-        emit = constants.nlconvert(emit)
         result = tuple([emit, uses_subdirs])
         return result
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 87d85c5181..0197e0671d 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -1398,18 +1398,18 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
         # Get link directives.
         links = [ module.getLink()
                   for module in self.moduletable['main'] ]
-        ulinks = list()
-        for link in links:
-            for lib in link:
-                ulinks += [lib]
-        ulinks = sorted(set(ulinks))
-        if ulinks:
+        lines = [ line
+                  for link in links
+                  for line in link.split('\n')
+                  if line != '' ]
+        lines = sorted(set(lines))
+        if lines:
             print('''
 You may need to use the following Makefile variables when linking.
 Use them in <program>_LDADD when linking a program, or
 in <library>_a_LDFLAGS or <library>_la_LDFLAGS when linking a library.''')
-            for link in ulinks:
-                print('  %s' % link)
+            for line in lines:
+                print('  %s' % line)
 
         # Print reminders.
         print('')
-- 
2.34.1

>From bc3d94bb2df6fa0c766f6226814c2fc2a55ee049 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 9 Aug 2022 23:59:40 +0200
Subject: [PATCH 4/5] gnulib-tool.py: Don't do license replacements in the
 autoconf snippets.

* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Remove fileassistant
argument. Don't invoke the 'aux' transformer here. Don't produce Windows
CR-LFs on Windows.
(GLEmiter.autoconfSnippets): Remove fileassistant argument.
* pygnulib/GLImport.py (GLImport.gnulib_comp): Update all callers.
* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
---
 ChangeLog             |  8 +++++++
 pygnulib/GLEmiter.py  | 51 ++++++++++++-------------------------------
 pygnulib/GLImport.py  |  4 ++--
 pygnulib/GLTestDir.py | 10 ++++-----
 4 files changed, 29 insertions(+), 44 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 50ef82d525..642a7363e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2022-08-09  Bruno Haible  <br...@clisp.org>
 
+	gnulib-tool.py: Don't do license replacements in the autoconf snippets.
+	* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Remove fileassistant
+	argument. Don't invoke the 'aux' transformer here. Don't produce Windows
+	CR-LFs on Windows.
+	(GLEmiter.autoconfSnippets): Remove fileassistant argument.
+	* pygnulib/GLImport.py (GLImport.gnulib_comp): Update all callers.
+	* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
+
 	gnulib-tool.py: Fix some code generation details.
 	* pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): When removing a
 	lib_LDFLAGS line, remove also the newline. Fix regex that matches
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 1a15fc4918..9b54d5009e 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -95,18 +95,15 @@ class GLEmiter(object):
 # Generated by gnulib-tool.\n"""
         return constants.nlconvert(emit)
 
-    def autoconfSnippet(self, module, fileassistant, toplevel,
+    def autoconfSnippet(self, module, toplevel,
                         disable_libtool, disable_gettext, replace_auxdir, indentation):
         '''GLEmiter.autoconfSnippet(module, toplevel,
-          disable_libtool, disable_gettext, replace_auxdir,
-          indentation) -> str
+          disable_libtool, disable_gettext, replace_auxdir, indentation) -> str
 
         Emit the autoconf snippet of a module.
         GLConfig: include_guard_prefix.
 
         module is a GLModule instance, which is processed.
-        fileassistant is a GLFileAssistant instance, which is used to get temporary
-          directories and sed transformer.
         toplevel is a bool variable, False means a subordinate use of pygnulib.
         disable_libtool is a bool variable; it tells whether to disable libtool
           handling even if it has been specified through the GLConfig class.
@@ -115,13 +112,9 @@ class GLEmiter(object):
         replace_auxdir is a bool variable; it tells whether to replace
           'build-aux' directory in AC_CONFIG_FILES.
         indentation is a string which contain spaces to prepend on each line.'''
-        emit = ''
         if type(module) is not GLModule:
             raise TypeError('module must be a GLModule, not %s'
                             % type(module).__name__)
-        if type(fileassistant) is not GLFileAssistant:
-            raise TypeError('fileassistant must be a GLFileAssistant, not %s'
-                            % type(fileassistant).__name__)
         if type(toplevel) is not bool:
             raise TypeError('toplevel must be a bool, not %s'
                             % type(toplevel).__name__)
@@ -139,6 +132,7 @@ class GLEmiter(object):
         auxdir = self.config['auxdir']
         libtool = self.config['libtool']
         include_guard_prefix = self.config['include_guard_prefix']
+        emit = ''
         if str(module) in ['gnumakefile', 'maintainer-makefile']:
             # These modules are meant to be used only in the top-level directory.
             flag = toplevel
@@ -152,18 +146,8 @@ class GLEmiter(object):
                       for line in snippet.split('\n')
                       if line.strip() ]
             snippet = '%s\n' % '\n'.join(lines)
-            transformer = fileassistant.transformers.get('aux', '')
             pattern = re.compile('^(.*)$', re.M)
             snippet = pattern.sub('%s\\1' % indentation, snippet)
-            if transformer:
-                args = ['sed', '-e', transformer]
-                path = fileassistant.tmpfilename('snippet')
-                with codecs.open(path, 'wb', 'UTF-8') as file:
-                    file.write(snippet)
-                stdin = codecs.open(path, 'rb', 'UTF-8')
-                snippet = sp.check_output(args, stdin=stdin, shell=False)
-                snippet = snippet.decode("UTF-8")
-                os.remove(path)
             if disable_libtool:
                 snippet = snippet.replace('$gl_cond_libtool', 'false')
                 snippet = snippet.replace('gl_libdeps', 'gltests_libdeps')
@@ -181,23 +165,21 @@ class GLEmiter(object):
                 emit += "LTALLOCA=`echo \"$ALLOCA\" | sed -e 's/\\.[^.]* /.lo /g;s/\\.[^.]*$/.lo/'`\n"
                 emit += 'changequote([, ])dnl\n'
                 emit += 'AC_SUBST([LTALLOCA])'
-        if replace_auxdir:
-            regex = 'AC_CONFIG_FILES\\(\\[(.*)\\:build-aux/(.*)\\]\\)'
-            repl = 'AC_CONFIG_FILES([\\1:%s/\\2])' % auxdir
-            pattern = re.compile(regex, re.M)
-            emit = pattern.sub(repl, emit)
+            if replace_auxdir:
+                regex = 'AC_CONFIG_FILES\\(\\[(.*)\\:build-aux/(.*)\\]\\)'
+                repl = 'AC_CONFIG_FILES([\\1:%s/\\2])' % auxdir
+                pattern = re.compile(regex, re.M)
+                emit = pattern.sub(repl, emit)
         lines = [ line
                   for line in emit.split('\n')
                   if line.strip() ]
         emit = '%s\n' % '\n'.join(lines)
-        emit = constants.nlconvert(emit)
         return emit
 
-    def autoconfSnippets(self, modules, moduletable, fileassistant,
+    def autoconfSnippets(self, modules, moduletable,
                          verifier, toplevel, disable_libtool, disable_gettext, replace_auxdir):
-        '''GLEmiter.autoconfSnippets(modules, fileassistant,
-          verifier, toplevel, disable_libtool, disable_gettext,
-          replace_auxdir) -> str
+        '''GLEmiter.autoconfSnippets(modules,
+          verifier, toplevel, disable_libtool, disable_gettext, replace_auxdir) -> str
 
         Collect and emit the autoconf snippets of a set of modules.
         GLConfig: conddeps.
@@ -209,8 +191,6 @@ class GLEmiter(object):
           be a GLModule instance.
         moduletable is a GLModuleTable instance, which contains necessary
           information about dependencies of the modules.
-        fileassistant is a GLFileAssistant instance, which is used to get temporary
-          directories and sed transformers.
         verifier is an integer, which can be 0, 1 or 2.
           if verifier == 0, then process every module;
           if verifier == 1, then process only non-tests modules;
@@ -229,9 +209,6 @@ class GLEmiter(object):
         if type(moduletable) is not GLModuleTable:
             raise TypeError('moduletable must be a GLFileAssistant, not %s'
                             % type(moduletable).__name__)
-        if type(fileassistant) is not GLFileAssistant:
-            raise TypeError('fileassistant must be a GLFileAssistant, not %s'
-                            % type(fileassistant).__name__)
         if type(verifier) is not int:
             raise TypeError('verifier must be an int, not %s'
                             % type(verifier).__name__)
@@ -262,7 +239,7 @@ class GLEmiter(object):
                 elif verifier == 2:
                     solution = module.isTests()
                 if solution:
-                    emit += self.autoconfSnippet(module, fileassistant, toplevel,
+                    emit += self.autoconfSnippet(module, toplevel,
                                                  disable_libtool, disable_gettext, replace_auxdir, '  ')
         else:  # if conddeps
             # Emit the autoconf code for the unconditional modules.
@@ -275,7 +252,7 @@ class GLEmiter(object):
                     solution = module.isTests()
                 if solution:
                     if not moduletable.isConditional(module):
-                        emit += self.autoconfSnippet(module, fileassistant, toplevel,
+                        emit += self.autoconfSnippet(module, toplevel,
                                                      disable_libtool, disable_gettext, replace_auxdir, '  ')
             # Initialize the shell variables indicating that the modules are enabled.
             for module in modules:
@@ -306,7 +283,7 @@ class GLEmiter(object):
                         emit += '  %s ()\n' % shellfunc
                         emit += '  {\n'
                         emit += '    if ! $%s; then\n' % shellvar
-                        emit += self.autoconfSnippet(module, fileassistant, toplevel,
+                        emit += self.autoconfSnippet(module, toplevel,
                                                      disable_libtool, disable_gettext, replace_auxdir, '      ')
                         emit += '      %s=true\n' % shellvar
                         depmodules = module.getDependenciesWithoutConditions()
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 0197e0671d..114605dd8a 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -636,7 +636,7 @@ AC_DEFUN([%s_INIT],
             emit += '  m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [%s])\n' % witness_c_macro
         # Emit main autoconf snippets.
         emit += self.emiter.autoconfSnippets(moduletable['main'],
-                                             moduletable, assistant, 0, True, False, True, replace_auxdir)
+                                             moduletable, 0, True, False, True, replace_auxdir)
         if witness_c_macro:
             emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
         emit += '  # End of code from modules\n'
@@ -659,7 +659,7 @@ AC_DEFUN([%s_INIT],
         emit += '[$gl_module_indicator_condition])\n'
         # Emit tests autoconf snippets.
         emit += self.emiter.autoconfSnippets(moduletable['tests'],
-                                             moduletable, assistant, 0, True, True, True, replace_auxdir)
+                                             moduletable, 0, True, True, True, replace_auxdir)
         emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
         emit += self.emiter.initmacro_end('%stests' % macro_prefix)
         # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 746b815b49..3c4ad0b9dc 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -496,11 +496,11 @@ class GLTestDir(object):
                 # those of the tests.
                 emit += "gl_source_base='../%s'\n" % sourcebase
                 emit += self.emiter.autoconfSnippets(modules,
-                                                     moduletable, self.assistant, 1, False, False, False,
+                                                     moduletable, 1, False, False, False,
                                                      replace_auxdir)
                 emit += "gl_source_base='.'"
                 emit += self.emiter.autoconfSnippets(modules,
-                                                     moduletable, self.assistant, 2, False, False, False,
+                                                     moduletable, 2, False, False, False,
                                                      replace_auxdir)
                 emit += self.emiter.initmacro_end(macro_prefix)
                 # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
@@ -614,10 +614,10 @@ class GLTestDir(object):
         emit += 'gl_source_base=\'%s\'\n' % sourcebase
         if single_configure:
             emit += self.emiter.autoconfSnippets(main_modules, moduletable,
-                                                 self.assistant, 0, False, False, False, replace_auxdir)
+                                                 0, False, False, False, replace_auxdir)
         else:  # if not single_configure
             emit += self.emiter.autoconfSnippets(modules, moduletable,
-                                                 self.assistant, 1, False, False, False, replace_auxdir)
+                                                 1, False, False, False, replace_auxdir)
         emit += self.emiter.initmacro_end(macro_prefix)
         if single_configure:
             emit += '  gltests_libdeps=\n'
@@ -631,7 +631,7 @@ class GLTestDir(object):
             emit += '  m4_pushdef([gl_MODULE_INDICATOR_CONDITION], '
             emit += '[$gl_module_indicator_condition])\n'
             snippets = self.emiter.autoconfSnippets(tests_modules, moduletable,
-                                                    self.assistant, 1, True, False, False, replace_auxdir)
+                                                    1, True, False, False, replace_auxdir)
             emit += snippets.strip()
             emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
             emit += self.emiter.initmacro_end('%stests' % macro_prefix)
-- 
2.34.1

>From 62fa8fc7b2c9db14d8c24d6ec5beedecb27b4802 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Wed, 10 Aug 2022 00:51:59 +0200
Subject: [PATCH 5/5] gnulib-tool.py: Finish implementing option
 --conditional-dependencies.

* gnulib-tool.py (main) Accept options --conditional-dependencies,
--no-conditional-dependencies.
* pygnulib/GLModuleSystem.py (GLModuleTable.addConditional): Use
str(module), not module, as key. Fix logic bug.
(GLModuleTable.getCondition): Simplify.
(GLModuleTable.transitive_closure): Show a warning when there are
duplicate dependencies. Fix logic bug.
(GLModuleTable.transitive_closure_separately): Simplify.
(GLModuleTable.add_dummy): Ignore tests modules. Cope with multiple
lib_SOURCES augmentation lines. Cope with comments at the end of a
lib_SOURCES augmentation line. Add the dummy module at the end of the
modules list.
* pygnulib/GLTestDir.py (GLTestDir.execute): Remove the code that forces
the dummy module to the end of the list.
* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Add code to
terminate the shell functions. Add code for the dependencies from the
unconditional to the conditional modules. Don't emit AM_CONDITIONAL for
unconditional modules.
---
 ChangeLog                  |  20 ++++++++
 gnulib-tool.py             |  13 ++++-
 gnulib-tool.py.TODO        |   7 +--
 pygnulib/GLEmiter.py       |  44 +++++++++++++---
 pygnulib/GLImport.py       |   3 +-
 pygnulib/GLModuleSystem.py | 100 +++++++++++++++++++++++++++----------
 pygnulib/GLTestDir.py      |  24 +--------
 7 files changed, 148 insertions(+), 63 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 642a7363e3..0dfcb7cdd7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2022-08-09  Bruno Haible  <br...@clisp.org>
 
+	gnulib-tool.py: Finish implementing option --conditional-dependencies.
+	* gnulib-tool.py (main) Accept options --conditional-dependencies,
+	--no-conditional-dependencies.
+	* pygnulib/GLModuleSystem.py (GLModuleTable.addConditional): Use
+	str(module), not module, as key. Fix logic bug.
+	(GLModuleTable.getCondition): Simplify.
+	(GLModuleTable.transitive_closure): Show a warning when there are
+	duplicate dependencies. Fix logic bug.
+	(GLModuleTable.transitive_closure_separately): Simplify.
+	(GLModuleTable.add_dummy): Ignore tests modules. Cope with multiple
+	lib_SOURCES augmentation lines. Cope with comments at the end of a
+	lib_SOURCES augmentation line. Add the dummy module at the end of the
+	modules list.
+	* pygnulib/GLTestDir.py (GLTestDir.execute): Remove the code that forces
+	the dummy module to the end of the list.
+	* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Add code to
+	terminate the shell functions. Add code for the dependencies from the
+	unconditional to the conditional modules. Don't emit AM_CONDITIONAL for
+	unconditional modules.
+
 	gnulib-tool.py: Don't do license replacements in the autoconf snippets.
 	* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Remove fileassistant
 	argument. Don't invoke the 'aux' transformer here. Don't produce Windows
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 9988c84de9..71ef1c4f2c 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -298,6 +298,15 @@ def main():
                         default=None,
                         action='append',
                         nargs=1)
+    # conditional-dependencies
+    parser.add_argument('--conditional-dependencies',
+                        dest='cond_dependencies',
+                        default=None,
+                        action="store_true")
+    parser.add_argument('--no-conditional-dependencies',
+                        dest='cond_dependencies',
+                        default=None,
+                        action="store_false")
     # libtool
     parser.add_argument('--libtool',
                         dest='libtool',
@@ -659,6 +668,7 @@ def main():
         lgpl = lgpl[-1]
         if lgpl == None:
             lgpl = True
+    cond_dependencies = cmdargs.cond_dependencies
     libtool = cmdargs.libtool
     makefile_name = cmdargs.makefile_name
     if makefile_name != None:
@@ -682,7 +692,6 @@ def main():
     lsymlink = cmdargs.lsymlink == True
     single_configure = cmdargs.single_configure
     docbase = None
-    conddeps = None
 
     # Create pygnulib configuration.
     config = classes.GLConfig(
@@ -702,7 +711,7 @@ def main():
         lgpl=lgpl,
         makefile_name=makefile_name,
         libtool=libtool,
-        conddeps=conddeps,
+        conddeps=cond_dependencies,
         macro_prefix=macro_prefix,
         podomain=podomain,
         witness_c_macro=witness_c_macro,
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index be6a2e2b10..da6df2ab90 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -15,15 +15,9 @@ The following commits to gnulib-tool have not yet been reflected in
 
 --------------------------------------------------------------------------------
 
-Inline all 'sed' invocations.
-
---------------------------------------------------------------------------------
-
 Implement the options:
   --extract-recursive-dependencies
   --extract-recursive-link-directive
-  --conditional-dependencies
-  --no-conditional-dependencies
   --gnu-make
   --tests-makefile-name
   --automake-subdir
@@ -37,6 +31,7 @@ Remove exit() in GLImport.py.
 
 Optimize:
   - os.chdir around subprocess creation -> cwd=... argument instead.
+  - Inline all 'sed' invocations.
 
 --------------------------------------------------------------------------------
 
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 9b54d5009e..c0fd053077 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -202,7 +202,6 @@ class GLEmiter(object):
           AM_GNU_GETTEXT invocations.
         replace_auxdir is a bool variable; it tells whether to replace
           'build-aux' directory in AC_CONFIG_FILES.'''
-        emit = ''
         for module in modules:
             if type(module) is not GLModule:
                 raise TypeError('each module must be a GLModule instance')
@@ -229,6 +228,7 @@ class GLEmiter(object):
         auxdir = self.config['auxdir']
         conddeps = self.config['conddeps']
         macro_prefix = self.config['macro_prefix']
+        emit = ''
         if not conddeps:
             # Ignore the conditions, and enable all modules unconditionally.
             for module in modules:
@@ -290,7 +290,39 @@ class GLEmiter(object):
                         # Intersect dependencies with the modules list.
                         depmodules = [ dep
                                        for dep in depmodules
-                                       if dep in modules ]
+                                       if dep in modules ]   # TODO should this be basemodules or modules?
+                        for depmodule in depmodules:
+                            if moduletable.isConditional(depmodule):
+                                shellfunc = depmodule.getShellFunc()
+                                condition = moduletable.getCondition(module, depmodule)
+                                if condition != None:
+                                    emit += '  if %s; then\n' % condition
+                                    emit += '    %s\n' % shellfunc
+                                    emit += '  fi\n'
+                                else:  # if condition == None
+                                    emit += '  %s\n' % shellfunc
+                            # if not moduletable.isConditional(depmodule)
+                            else:
+                                # The autoconf code for $dep has already been emitted above and
+                                # therefore is already executed when this code is run.
+                                pass
+                        emit += '    fi\n'
+                        emit += '  }\n'
+            # Emit the dependencies from the unconditional to the conditional modules.
+            for module in modules:
+                if verifier == 0:
+                    solution = True
+                elif verifier == 1:
+                    solution = module.isNonTests()
+                elif verifier == 2:
+                    solution = module.isTests()
+                if solution:
+                    if not moduletable.isConditional(module):
+                        depmodules = module.getDependenciesWithoutConditions()
+                        # Intersect dependencies with the modules list.
+                        depmodules = [ dep
+                                       for dep in depmodules
+                                       if dep in modules ]   # TODO should this be basemodules or modules?
                         for depmodule in depmodules:
                             if moduletable.isConditional(depmodule):
                                 shellfunc = depmodule.getShellFunc()
@@ -316,14 +348,14 @@ class GLEmiter(object):
                 elif verifier == 2:
                     solution = module.isTests()
                 if solution:
-                    condname = module.getConditionalName()
-                    shellvar = module.getShellVar()
-                    emit += '  AM_CONDITIONAL([%s], [$%s])\n' % (condname, shellvar)
+                    if moduletable.isConditional(module):
+                        condname = module.getConditionalName()
+                        shellvar = module.getShellVar()
+                        emit += '  AM_CONDITIONAL([%s], [$%s])\n' % (condname, shellvar)
         lines = [ line
                   for line in emit.split('\n')
                   if line.strip() ]
         emit = '%s\n' % '\n'.join(lines)
-        emit = constants.nlconvert(emit)
         return emit
 
     def preEarlyMacros(self, require, indentation, modules):
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 114605dd8a..5dd73fa8bd 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -831,9 +831,10 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
         if libtests:
             self.config.setLibtests(True)
 
-        # Add dummy package if it is needed.
+        # Add the dummy module to the main module list if needed.
         main_modules = self.moduletable.add_dummy(main_modules)
         if libtests:  # if we need to use libtests.a
+            # Add the dummy module to the tests-related module list if needed.
             tests_modules = self.moduletable.add_dummy(tests_modules)
 
         # Check license incompatibilities.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 9bfd5bd266..f9b47a64a5 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -705,6 +705,18 @@ class GLModuleTable(object):
         inc_all_indirect_tests = True if all kinds of problematic unit tests
                                     among the unit tests of the dependencies
                                     should be included
+
+        Methods for conditional dependencies:
+        - addUnconditional(B)
+          notes the presence of B as an unconditional module.
+        - addConditional(A, B. cond)
+          notes the presence of a conditional dependency from module A to module B,
+          subject to the condition that A is enabled and cond is true.
+        - isConditional(B)
+          tests whether module B is conditional.
+        - getCondition(A, B)
+          returns the condition when B should be enabled as a dependency of A,
+          once the m4 code for A has been executed.
         '''
         self.dependers = dict()  # Dependencies
         self.conditionals = dict()  # Conditional modules
@@ -765,9 +777,11 @@ class GLModuleTable(object):
             raise TypeError('condition must be a string or True, not %s'
                             % type(condition).__name__)
         if not str(module) in self.unconditionals:
+            # No unconditional dependency to the given module is known at this point.
             if str(module) not in self.dependers:
-                self.dependers[module] = list()
-            self.dependers[module] += [module]
+                self.dependers[str(module)] = list()
+            if str(parent) not in self.dependers[str(module)]:
+                self.dependers[str(module)].append(str(parent))
             key = '%s---%s' % (str(parent), str(module))
             self.conditionals[key] = condition
 
@@ -778,9 +792,9 @@ class GLModuleTable(object):
         if type(module) is not GLModule:
             raise TypeError('module must be a GLModule, not %s'
                             % type(module).__name__)
+        self.unconditionals[str(module)] = True
         if str(module) in self.dependers:
             self.dependers.pop(str(module))
-        self.unconditionals[str(module)] = True
 
     def isConditional(self, module):
         '''GLModuleTable.isConditional(module) -> bool
@@ -804,9 +818,7 @@ class GLModuleTable(object):
             raise TypeError('module must be a GLModule, not %s'
                             % type(module).__name__)
         key = '%s---%s' % (str(parent), str(module))
-        result = None
-        if key in self.conditionals:
-            result = self.conditionals[key]
+        result = self.conditionals.get(key, None)
         return result
 
     def transitive_closure(self, modules):
@@ -823,6 +835,11 @@ class GLModuleTable(object):
         for module in modules:
             if type(module) is not GLModule:
                 raise TypeError('each module must be a GLModule instance')
+        # In order to process every module only once (for speed), process an
+        # "input list" of modules, producing an "output list" of modules. During
+        # each round, more modules can be queued in the input list. Once a
+        # module on the input list has been processed, it is added to the
+        # "handled list", so we can avoid to process it again.
         inc_all_tests = self.inc_all_direct_tests
         handledmodules = list()
         inmodules = modules
@@ -833,7 +850,7 @@ class GLModuleTable(object):
                     self.addUnconditional(module)
         while inmodules:
             inmodules_this_round = inmodules
-            inmodules = list()
+            inmodules = list()               # Accumulator, queue for next round
             for module in inmodules_this_round:
                 if module not in self.avoids:
                     outmodules += [module]
@@ -842,6 +859,13 @@ class GLModuleTable(object):
                             module.getAutomakeSnippet_Conditional()
                         pattern = re.compile('^if', re.M)
                         if not pattern.findall(automake_snippet):
+                            # A module whose Makefile.am snippet contains a
+                            # reference to an automake conditional. If we were
+                            # to use it conditionally, we would get an error
+                            #   configure: error: conditional "..." was never defined.
+                            # because automake 1.11.1 does not handle nested
+                            # conditionals correctly. As a workaround, make the
+                            # module unconditional.
                             self.addUnconditional(module)
                         conditional = self.isConditional(module)
                     dependencies = module.getDependenciesWithConditions()
@@ -849,6 +873,16 @@ class GLModuleTable(object):
                                    for pair in dependencies ]
                     conditions = [ pair[1]
                                    for pair in dependencies ]
+                    # Duplicate dependencies are harmless, but Jim wants a warning.
+                    duplicate_depmodules = [ depmodule
+                                             for depmodule in set(depmodules)
+                                             if depmodules.count(depmodule) > 1 ]
+                    if duplicate_depmodules:
+                        duplicate_depmodule_names = [ str(depmodule)
+                                                      for depmodule in duplicate_depmodules ]
+                        message = ('gnulib-tool: warning: module %s has duplicated dependencies: %s\n'
+                                   % (module, duplicate_depmodule_names))
+                        sys.stderr.write(message)
                     if self.config.checkInclTestCategory(TESTS['tests']):
                         testsname = module.getTestsName()
                         if self.modulesystem.exists(testsname):
@@ -856,6 +890,7 @@ class GLModuleTable(object):
                             depmodules += [testsmodule]
                             conditions += [None]
                     for depmodule in depmodules:
+                        # Determine whether to include the dependency or tests module.
                         include = True
                         statuses = depmodule.getStatuses()
                         for word in statuses:
@@ -890,15 +925,15 @@ class GLModuleTable(object):
                             if self.config['conddeps']:
                                 index = depmodules.index(depmodule)
                                 condition = conditions[index]
+                                if condition == True:
+                                    condition = None
                                 if condition:
                                     self.addConditional(module, depmodule, condition)
                                 else:  # if condition
                                     if conditional:
                                         self.addConditional(module, depmodule, True)
                                     else:  # if not conditional
-                                        self.addUnconditional(module)
-            listing = list()  # Create empty list
-            inmodules = sorted(set(inmodules))
+                                        self.addUnconditional(depmodule)
             handledmodules = sorted(set(handledmodules + inmodules_this_round))
             # Remove handledmodules from inmodules.
             inmodules = [module
@@ -934,17 +969,24 @@ class GLModuleTable(object):
         for module in finalmodules:
             if type(module) is not GLModule:
                 raise TypeError('each module must be a GLModule instance')
+        # Determine main module list.
         saved_inctests = self.config.checkInclTestCategory(TESTS['tests'])
         self.config.disableInclTestCategory(TESTS['tests'])
         main_modules = self.transitive_closure(basemodules)
         self.config.setInclTestCategory(TESTS['tests'], saved_inctests)
+        # Determine tests-related module list.
         tests_modules = \
             [ m
               for m in finalmodules
-              if m not in main_modules ] \
-            + [ m
-                for m in main_modules
-                if m.getApplicability() != 'main' ]
+              if not (m in main_modules and m.getApplicability() == 'main') ]
+        # Note: Since main_modules is (hopefully) a subset of finalmodules, this
+        # ought to be the same as
+        #   [ m
+        #     for m in finalmodules
+        #     if m not in main_modules ] \
+        #   + [ m
+        #       for m in main_modules
+        #       if m.getApplicability() != 'main' ]
         tests_modules = sorted(set(tests_modules))
         result = tuple([main_modules, tests_modules])
         return result
@@ -957,24 +999,30 @@ class GLModuleTable(object):
         GLConfig: auxdir, ac_version.'''
         auxdir = self.config['auxdir']
         ac_version = self.config['ac_version']
-        have_lib_sources = False
         for module in modules:
             if type(module) is not GLModule:
                 raise TypeError('each module must be a GLModule instance')
-            snippet = module.getAutomakeSnippet()
-            snippet = constants.remove_backslash_newline(snippet)
-            pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*)$', re.M)
-            files = pattern.findall(snippet)
-            if files:  # if source files were found
-                files = files[-1].split(' ')
-                for file in files:
-                    if not file.endswith('.h'):
-                        have_lib_sources = True
-                        break
+        # Determine whether any module provides a lib_SOURCES augmentation.
+        have_lib_sources = False
+        for module in modules:
+            if not module.isTests():
+                snippet = module.getAutomakeSnippet()
+                # Extract the value of "lib_SOURCES += ...".
+                snippet = constants.remove_backslash_newline(snippet)
+                pattern = re.compile('^lib_SOURCES[\t ]*\\+=([^#]*).*$', re.M)
+                for matching_rhs in pattern.findall(snippet):
+                    files = matching_rhs.split(' ')
+                    for file in files:
+                        # Ignore .h files since they are not compiled.
+                        if not file.endswith('.h'):
+                            have_lib_sources = True
+                            break
+        # Add the dummy module, to make sure the library will be non-empty.
         if not have_lib_sources:
             dummy = self.modulesystem.find('dummy')
             if dummy not in self.avoids:
-                modules = sorted(set(modules + [dummy]))
+                if dummy not in modules:
+                    modules = sorted(set(modules)) + [dummy]
         return list(modules)
 
     def filelist(self, modules):
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 3c4ad0b9dc..bf00099283 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -265,33 +265,13 @@ class GLTestDir(object):
                 self.config.setLibtests(True)
 
         if single_configure:
-            # Add dummy package if it is needed.
+            # Add the dummy module to the main module list if needed.
             main_modules = moduletable.add_dummy(main_modules)
-            if 'dummy' in [ str(module)
-                            for module in main_modules ]:
-                main_modules = [ m
-                                 for m in main_modules
-                                 if str(m) != 'dummy' ]
-                dummy = self.modulesystem.find('dummy')
-                main_modules = sorted(set(main_modules)) + [dummy]
             if libtests:  # if we need to use libtests.a
+                # Add the dummy module to the tests-related module list if needed.
                 tests_modules = moduletable.add_dummy(tests_modules)
-                if 'dummy' in [ str(module)
-                                for module in tests_modules ]:
-                    tests_modules = [ m
-                                      for m in tests_modules
-                                      if str(m) != 'dummy' ]
-                    dummy = self.modulesystem.find('dummy')
-                    tests_modules = sorted(set(tests_modules)) + [dummy]
         else:  # if not single_configure
             modules = moduletable.add_dummy(modules)
-            if 'dummy' in [ str(module)
-                            for module in modules ]:
-                modules = [ m
-                            for m in modules
-                            if str(m) != 'dummy' ]
-                dummy = self.modulesystem.find('dummy')
-                modules = sorted(set(modules)) + [dummy]
 
         # Show banner notice of every module.
         if single_configure:
-- 
2.34.1

Reply via email to