Hi Bruno,
Here is a patch with some updates now that I looked into the issue a
bit more. I've also added the comments and fixed the build-aux issue
you noticed.
On 3/21/24 3:20 PM, Collin Funk wrote:
> This is
> because filter_filelist can return a non-empty list with an empty
> string:
This isn't fully accurate. The real reason this problem exists is
that filter_filelist will join an empty list. In
GLModule.getAutomakeSnippet_Unconditional we split by the same
separator which results in a list with an empty string.
In other words, we basically do this:
print('\n'.join([]).split('\n'))
['']
To fix this I have made the following change to filter_filelist:
- result = separator.join(listing)
+ # Return an empty string if no files were matched, else combine them
+ # with the given separator.
+ if listing:
+ result = separator.join(listing)
+ else:
+ result = ''
return result
Still not the prettiest code, but maybe I will think of something
better later...
Collin
From 8f0946720b61407b5628aeadc224addc71a4dcfe Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Fri, 22 Mar 2024 02:15:24 -0700
Subject: [PATCH] gnulib-tool.py: Fix unconditional Automake snippets for
non-tests.
* pygnulib/GLModuleSystem.py
(GLModule.getAutomakeSnippet_Unconditional): Fix the file lookups used
to determine the EXTRA_DIST and EXTRA_lib_SOURCES Automake variables.
Update comment to match gnulib-tool.sh.
* pygnulib/constants.py (filter_filelist): Fix misleading return type in
docstring. Return an empty string if no files were found.
---
ChangeLog | 10 ++++++
pygnulib/GLModuleSystem.py | 71 +++++++++++++++++++++-----------------
pygnulib/constants.py | 9 +++--
3 files changed, 57 insertions(+), 33 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 46379c5a4c..82e998ed25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-03-22 Collin Funk <collin.fu...@gmail.com>
+
+ gnulib-tool.py: Fix unconditional Automake snippets for non-tests.
+ * pygnulib/GLModuleSystem.py
+ (GLModule.getAutomakeSnippet_Unconditional): Fix the file lookups used
+ to determine the EXTRA_DIST and EXTRA_lib_SOURCES Automake variables.
+ Update comment to match gnulib-tool.sh.
+ * pygnulib/constants.py (filter_filelist): Fix misleading return type in
+ docstring. Return an empty string if no files were found.
+
2024-03-21 Collin Funk <collin.fu...@gmail.com>
gnulib-tool.sh: Avoid a redundant space in gl_AVOID in gnulib-cache.m4.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index bfef6e692b..c0d9b0365a 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -649,52 +649,61 @@ class GLModule(object):
result = ''
if 'makefile-unconditional' not in self.cache:
if self.getName().endswith('-tests'):
+ # *-tests module live in tests/, not lib/.
+ # Synthesize an EXTRA_DIST augmentation.
files = self.getFiles()
extra_files = filter_filelist(constants.NL, files,
- 'tests/', '', 'tests/', '').split(constants.NL)
- if extra_files:
- result += 'EXTRA_DIST += %s' % ' '.join(extra_files)
+ 'tests/', '', 'tests/', '')
+ if extra_files != '':
+ result += 'EXTRA_DIST += %s' % ' '.join(extra_files.split(constants.NL))
result += constants.NL * 2
else: # if not tests module
- # TODO: unconditional automake snippet for nontests modules
+ # Synthesize an EXTRA_DIST augmentation.
snippet = self.getAutomakeSnippet_Conditional()
snippet = constants.combine_lines(snippet)
- pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*)$', re.M)
- mentioned_files = pattern.findall(snippet)
- if mentioned_files != list():
- mentioned_files = mentioned_files[-1].split(' ')
- mentioned_files = [ f.strip()
- for f in mentioned_files ]
- mentioned_files = [ f
- for f in mentioned_files
- if f != '' ]
- mentioned_files = sorted(set(mentioned_files))
+ pattern = re.compile(r'^lib_SOURCES[\t ]*\+=[\t ]*(.*)$', re.MULTILINE)
+ mentioned_files = set(pattern.findall(snippet))
+ if mentioned_files:
+ # Get all the file names from 'lib_SOURCES += ...'.
+ mentioned_files = { filename
+ for line in mentioned_files
+ for filename in line.split() }
all_files = self.getFiles()
lib_files = filter_filelist(constants.NL, all_files,
- 'lib/', '', 'lib/', '').split(constants.NL)
- extra_files = [ f
- for f in lib_files
- if f not in mentioned_files ]
- extra_files = sorted(set(extra_files))
- if extra_files != [''] and extra_files:
+ 'lib/', '', 'lib/', '')
+ if lib_files != '':
+ lib_files = set(lib_files.split(constants.NL))
+ else:
+ lib_files = set()
+ # Remove mentioned_files from lib_files.
+ extra_files = sorted(lib_files.difference(mentioned_files))
+ if extra_files:
result += 'EXTRA_DIST += %s' % ' '.join(extra_files)
result += '\n\n'
- # Synthesize also an EXTRA_lib_SOURCES augmentation
+ # Synthesize also an EXTRA_lib_SOURCES augmentation.
+ # This is necessary so that automake can generate the right list of
+ # dependency rules.
+ # A possible approach would be to use autom4te --trace of the redefined
+ # AC_LIBOBJ and AC_REPLACE_FUNCS macros when creating the Makefile.am
+ # (use autom4te --trace, not just grep, so that AC_LIBOBJ invocations
+ # inside autoconf's built-in macros are not missed).
+ # But it's simpler and more robust to do it here, based on the file list.
+ # If some .c file exists and is not used with AC_LIBOBJ - for example,
+ # a .c file is preprocessed into another .c file for BUILT_SOURCES -,
+ # automake will generate a useless dependency; this is harmless.
if str(self) != 'relocatable-prog-wrapper' and str(self) != 'pt_chown':
extra_files = filter_filelist(constants.NL, extra_files,
- '', '.c', '', '').split(constants.NL)
- extra_files = sorted(set(extra_files))
- if extra_files != ['']:
- result += 'EXTRA_lib_SOURCES += %s' % ' '.join(extra_files)
+ '', '.c', '', '')
+ if extra_files != '':
+ result += 'EXTRA_lib_SOURCES += %s' % ' '.join(sorted(set(extra_files.split(constants.NL))))
result += '\n\n'
# Synthesize an EXTRA_DIST augmentation also for the files in build-aux
buildaux_files = filter_filelist(constants.NL, all_files,
- 'build-aux/', '', 'build-aux/', '').split(constants.NL)
- buildaux_files = sorted(set(buildaux_files))
- if buildaux_files != ['']:
- buildaux_files = ''.join(buildaux_files)
- buildaux_files = joinpath('$(top_srcdir)', auxdir, buildaux_files)
- result += 'EXTRA_DIST += %s' % buildaux_files
+ 'build-aux/', '', 'build-aux/', '')
+ if buildaux_files != '':
+ buildaux_files = [ joinpath('$(top_srcdir)', auxdir, filename)
+ for filename in sorted(set(buildaux_files.split(constants.NL))) ]
+ result += 'EXTRA_DIST += %s' % ' '.join(buildaux_files)
result += '\n\n'
result = constants.nlconvert(result)
self.cache['makefile-unconditional'] = result
diff --git a/pygnulib/constants.py b/pygnulib/constants.py
index b7434155d8..c3a5aeae09 100644
--- a/pygnulib/constants.py
+++ b/pygnulib/constants.py
@@ -447,7 +447,7 @@ def hardlink(src: str, dest: str) -> None:
def filter_filelist(separator, filelist,
prefix, suffix, removed_prefix, removed_suffix,
added_prefix='', added_suffix=''):
- '''filter_filelist(*args) -> list
+ '''filter_filelist(*args) -> str
Filter the given list of files. Filtering: Only the elements starting with
prefix and ending with suffix are considered. Processing: removed_prefix
@@ -461,7 +461,12 @@ def filter_filelist(separator, filelist,
result = pattern.sub('%s\\1%s'
% (added_prefix, added_suffix), filename)
listing += [result]
- result = separator.join(listing)
+ # Return an empty string if no files were matched, else combine them
+ # with the given separator.
+ if listing:
+ result = separator.join(listing)
+ else:
+ result = ''
return result
--
2.44.0