mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-08-27 12:06:59 +00:00
1103 lines
45 KiB
Python
1103 lines
45 KiB
Python
#!/usr/bin/python
|
|
# encoding: UTF-8
|
|
"""gnulib generators API"""
|
|
|
|
|
|
|
|
import os as _os
|
|
import re as _re
|
|
import codecs as _codecs
|
|
import subprocess as _sp
|
|
from datetime import datetime as _datetime
|
|
|
|
|
|
from .config import BaseConfig as _BaseConfig
|
|
from .config import LGPLv2_LICENSE as _LGPLv2_LICENSE
|
|
from .config import LGPLv3_LICENSE as _LGPLv3_LICENSE
|
|
from .config import GPLv2_LICENSE as _GPLv2_LICENSE
|
|
from .config import LGPL_LICENSES as _LGPL_LICENSES
|
|
from .misc import Executable as _Executable
|
|
from .module import BaseModule as _BaseModule
|
|
from .module import Database as _Database
|
|
|
|
|
|
|
|
_LGPL = {
|
|
tuple(sorted(_LGPLv2_LICENSE)): "2",
|
|
tuple(sorted(_LGPLv3_LICENSE)): "3",
|
|
tuple(sorted(_LGPL_LICENSES)): "yes",
|
|
tuple(sorted(_GPLv2_LICENSE | _LGPLv3_LICENSE)): "3orGPLv2",
|
|
}
|
|
__DISCLAIMER = (
|
|
"## DO NOT EDIT! GENERATED AUTOMATICALLY!",
|
|
"#",
|
|
"# This file is free software; you can redistribute it and/or modify",
|
|
"# it under the terms of the GNU General Public License as published by",
|
|
"# the Free Software Foundation; either version 3 of the License, or",
|
|
"# (at your option) any later version.",
|
|
"#",
|
|
"# This file is distributed in the hope that it will be useful,",
|
|
"# but WITHOUT ANY WARRANTY; without even the implied warranty of",
|
|
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
|
"# GNU General Public License for more details.",
|
|
"#",
|
|
"# You should have received a copy of the GNU General Public License",
|
|
"# along with this file. If not, see <http://www.gnu.org/licenses/>.",
|
|
"#",
|
|
"# As a special exception to the GNU General Public License,",
|
|
"# this file may be distributed as part of a program that",
|
|
"# contains a configuration script generated by Autoconf, under",
|
|
"# the same distribution terms as the rest of that program.",
|
|
"#",
|
|
"# Generated by gnulib-tool.",
|
|
)
|
|
_ITERABLES = frozenset((list, tuple, set, frozenset, type({}.keys()), type({}.values())))
|
|
|
|
|
|
|
|
__PO_MAKE_VARS = (
|
|
"# These options get passed to xgettext.",
|
|
"XGETTEXT_OPTIONS = \\",
|
|
" --keyword=_ --flag=_:1:pass-c-format \\",
|
|
" --keyword=N_ --flag=N_:1:pass-c-format \\",
|
|
" --keyword='proper_name:1,\"This is a proper name. See the gettext manual, section Names.\"' \\",
|
|
" --keyword='proper_name_utf8:1,\"This is a proper name. See the gettext manual, section Names.\"' \\",
|
|
" --flag=error:3:c-format --flag=error_at_line:5:c-format",
|
|
"",
|
|
"# This is the copyright holder that gets inserted into the header of the",
|
|
"# $(DOMAIN).pot file. gnulib is copyrighted by the FSF.",
|
|
"COPYRIGHT_HOLDER = Free Software Foundation, Inc.",
|
|
"",
|
|
"# This is the email address or URL to which the translators shall report",
|
|
"# bugs in the untranslated strings:",
|
|
"# - Strings which are not entire sentences, see the maintainer guidelines",
|
|
"# in the GNU gettext documentation, section 'Preparing Strings'.",
|
|
"# - Strings which use unclear terms or require additional context to be",
|
|
"# understood.",
|
|
"# - Strings which make invalid assumptions about notation of date, time or",
|
|
"# money.",
|
|
"# - Pluralisation problems.",
|
|
"# - Incorrect English spelling.",
|
|
"# - Incorrect formatting.",
|
|
"# It can be your email address, or a mailing list address where translators",
|
|
"# can write to without being subscribed, or the URL of a web page through",
|
|
"# which the translators can contact you.",
|
|
"MSGID_BUGS_ADDRESS = bug-gnulib@gnu.org",
|
|
"",
|
|
"# This is the list of locale categories, beyond LC_MESSAGES, for which the",
|
|
"# message catalogs shall be used. It is usually empty.",
|
|
"EXTRA_LOCALE_CATEGORIES =",
|
|
"",
|
|
"# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'",
|
|
"# context. Possible values are \"yes\" and \"no\". Set this to yes if the",
|
|
"# package uses functions taking also a message context, like pgettext(), or",
|
|
"# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.",
|
|
"USE_MSGCTXT = no"
|
|
)
|
|
|
|
def po_make_vars(config, **override):
|
|
"""Generate PO Makefile parameterization."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
|
|
po_base = config.po_base
|
|
po_domain = comnfig.po_domain
|
|
for line in __DISCLAIMER:
|
|
yield line
|
|
yield "# Usually the message domain is the same as the package name."
|
|
yield "# But here it has a '-gnulib' suffix."
|
|
yield f"DOMAIN = {po_domain}-gnulib"
|
|
yield ""
|
|
yield "# These two variables depend on the location of this directory."
|
|
yield f"subdir = {po_base}"
|
|
top_builddir = "/".join(".." for _ in config.po_base.split(_os.path.sep))
|
|
yield f"top_builddir = {top_builddir}"
|
|
for line in __PO_MAKE_VARS:
|
|
yield line
|
|
|
|
|
|
|
|
def POTFILES(config, files, **override):
|
|
"""Generate file list to be passed to xgettext."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
|
|
source_base = config.source_base
|
|
for line in __DISCLAIMER:
|
|
yield line
|
|
yield "# List of files which contain translatable strings."
|
|
for file in filter(lambda file: file.startswith("lib/"), files):
|
|
yield _os.path.join(source_base, file[4:])
|
|
|
|
|
|
|
|
def autoconf_snippet(config, module, toplevel, no_libtool, no_gettext, **override):
|
|
"""
|
|
Generate autoconf snippet for a standalone module."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
|
|
gettext = not no_gettext
|
|
if module.name not in ("gnumakefile", "maintainer-makefile") or toplevel:
|
|
snippet = module.autoconf_snippet
|
|
include_guard_prefix = config.include_guard_prefix
|
|
snippet = snippet.replace(r"${gl_include_guard_prefix}", include_guard_prefix)
|
|
if no_libtool:
|
|
table = (
|
|
(r"$gl_cond_libtool", "false"),
|
|
(r"gl_libdeps", "gltests_libdeps"),
|
|
(r"gl_ltlibdeps", "gltests_ltlibdeps"),
|
|
)
|
|
for (src, dst) in table:
|
|
snippet = snippet.replace(src, dst)
|
|
if no_gettext:
|
|
src = "AM_GNU_GETTEXT([external])"
|
|
dst = "dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac.'"
|
|
snippet = snippet.replace(src, dst)
|
|
else:
|
|
# Don't indent AM_GNU_GETTEXT_VERSION line, as that confuses
|
|
# autopoint through at least GNU gettext version 0.18.2.
|
|
snippet = snippet.lstrip()
|
|
lines = filter(lambda line: line.strip(), snippet.split("\n"))
|
|
for line in lines:
|
|
yield line
|
|
if module.name == "alloca" and config.libtool and not no_libtool:
|
|
yield "changequote(,)dnl"
|
|
yield "LTALLOCA=`echo \"$ALLOCA\" | sed -e 's/\\.[^.]* /.lo /g;s/\\.[^.]*$/.lo/'`"
|
|
yield "changequote([, ])dnl"
|
|
yield "AC_SUBST([LTALLOCA])"
|
|
|
|
|
|
|
|
def autoconf_snippets(config, database, modules, toplevel, no_libtool, no_gettext, **override):
|
|
"""Generate an autoconf snippet for multiple modules."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
macro_prefix = config.macro_prefix
|
|
|
|
arguments = {
|
|
"config": config,
|
|
"module": None,
|
|
"toplevel": toplevel,
|
|
"no_libtool": no_libtool,
|
|
"no_gettext": no_gettext,
|
|
}
|
|
if not config.conditionals:
|
|
for module in modules:
|
|
arguments["module"] = module
|
|
for line in autoconf_snippet(**arguments):
|
|
yield f" {line}"
|
|
return
|
|
|
|
conditional = set()
|
|
unconditional = set()
|
|
for dependency in modules:
|
|
if database.conditional(dependency):
|
|
conditional.add(dependency)
|
|
else:
|
|
unconditional.add(dependency)
|
|
conditional = sorted(conditional)
|
|
unconditional = sorted(unconditional)
|
|
|
|
# Emit the autoconf code for the unconditional modules.
|
|
for module in unconditional:
|
|
arguments["module"] = module
|
|
for line in autoconf_snippet(**arguments):
|
|
yield f" {line}"
|
|
|
|
# Initialize the shell variables indicating that the modules are enabled.
|
|
for module in conditional:
|
|
shellvar = module.shell_variable(macro_prefix)
|
|
yield f" {shellvar}=false"
|
|
|
|
# Emit the autoconf code for the conditional modules, each in a separate
|
|
# function. This makes it possible to support cycles among conditional
|
|
# modules.
|
|
for demander in conditional:
|
|
arguments["module"] = demander
|
|
shellvar = demander.shell_variable(macro_prefix)
|
|
shellfunc = demander.shell_function(macro_prefix)
|
|
yield f" {shellfunc} ()"
|
|
yield f" {{"
|
|
yield f" if ! ${shellvar}; then"
|
|
for line in autoconf_snippet(**arguments):
|
|
yield f" {line}"
|
|
yield f" {shellvar}=true"
|
|
for (dependency, condition) in sorted(database.dependencies(demander)):
|
|
if database.conditional(dependency):
|
|
shellfunc = dependency.shell_function(macro_prefix)
|
|
if condition:
|
|
yield f" if {condition}; then"
|
|
yield f" {shellfunc}"
|
|
yield f" fi"
|
|
else:
|
|
yield f" {shellfunc}"
|
|
yield f" fi"
|
|
yield f" }}"
|
|
|
|
# Emit the dependencies from the unconditional to the conditional modules.
|
|
for demander in unconditional:
|
|
for (dependency, condition) in sorted(database.dependencies(demander)):
|
|
if dependency in modules and database.conditional(dependency):
|
|
condname = dependency.conditional_name(macro_prefix)
|
|
shellfunc = dependency.shell_function(macro_prefix)
|
|
if condition:
|
|
yield f" if {condition}; then"
|
|
yield f" {shellfunc}"
|
|
yield f" fi"
|
|
continue
|
|
else:
|
|
yield f" {shellfunc}"
|
|
|
|
# Define the Automake conditionals.
|
|
yield f" m4_pattern_allow([^{macro_prefix}_GNULIB_ENABLED_])"
|
|
for module in conditional:
|
|
condname = module.conditional_name(macro_prefix)
|
|
shellvar = module.shell_variable(macro_prefix)
|
|
yield f" AM_CONDITIONAL([{condname}], [${shellvar}])"
|
|
|
|
|
|
|
|
__INIT_MACRO_HEADER = (
|
|
# Overriding AC_LIBOBJ and AC_REPLACE_FUNCS has the effect of storing
|
|
# platform-dependent object files in ${macro_prefix_arg}_LIBOBJS instead
|
|
# of LIBOBJS. The purpose is to allow several gnulib instantiations under
|
|
# a single configure.ac file. (AC_CONFIG_LIBOBJ_DIR does not allow this
|
|
# flexibility).
|
|
# Furthermore it avoids an automake error like this when a Makefile.am
|
|
# that uses pieces of gnulib also uses $(LIBOBJ):
|
|
# automatically discovered file `error.c' should not be explicitly
|
|
# mentioned.
|
|
" m4_pushdef([AC_LIBOBJ], m4_defn([{macro_prefix}_LIBOBJ]))",
|
|
" m4_pushdef([AC_REPLACE_FUNCS], m4_defn([{macro_prefix}_REPLACE_FUNCS]))",
|
|
|
|
# Overriding AC_LIBSOURCES has the same purpose of avoiding the automake
|
|
# error when a Makefile.am that uses pieces of gnulib also uses $(LIBOBJ):
|
|
# automatically discovered file `error.c' should not be explicitly
|
|
# mentioned
|
|
# We let automake know about the files to be distributed through the
|
|
# EXTRA_lib_SOURCES variable.
|
|
" m4_pushdef([AC_LIBSOURCES], m4_defn([{macro_prefix}_LIBSOURCES]))",
|
|
|
|
# Create data variables for checking the presence of files that are
|
|
# mentioned as AC_LIBSOURCES arguments. These are m4 variables, not shell
|
|
# variables, because we want the check to happen when the configure file is
|
|
# created, not when it is run. ${macro_prefix_arg}_LIBSOURCES_LIST is the
|
|
# list of files to check for. ${macro_prefix_arg}_LIBSOURCES_DIR is the
|
|
# subdirectory in which to expect them.
|
|
" m4_pushdef([{macro_prefix}_LIBSOURCES_LIST], [])",
|
|
" m4_pushdef([{macro_prefix}_LIBSOURCES_DIR], [])",
|
|
" gl_COMMON",
|
|
)
|
|
|
|
def init_macro_header(config, **override):
|
|
"""Generate the first few statements of the gl_INIT macro."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
macro_prefix = config.macro_prefix
|
|
|
|
for line in __INIT_MACRO_HEADER:
|
|
yield line.format(**config)
|
|
|
|
|
|
|
|
__INIT_MACRO_FOOTER = (
|
|
# Check the presence of files that are mentioned as AC_LIBSOURCES
|
|
# arguments. The check is performed only when autoconf is run from the
|
|
# directory where the configure.ac resides; if it is run from a different
|
|
# directory, the check is skipped.
|
|
" m4_ifval({macro_prefix}_LIBSOURCES_LIST, [",
|
|
" m4_syscmd([test ! -d ]m4_defn([{macro_prefix}_LIBSOURCES_DIR])[ ||",
|
|
" for gl_file in ]{macro_prefix}_LIBSOURCES_LIST[ ; do",
|
|
" if test ! -r ]m4_defn([{macro_prefix}_LIBSOURCES_DIR])[/$gl_file ; then",
|
|
" echo \"missing file ]m4_defn([{macro_prefix}_LIBSOURCES_DIR])[/$gl_file\" >&2",
|
|
" exit 1",
|
|
" fi",
|
|
" done])dnl",
|
|
" m4_if(m4_sysval, [0], [],",
|
|
" [AC_FATAL([expected source file, required through AC_LIBSOURCES, not found])])",
|
|
" ])",
|
|
" m4_popdef([{macro_prefix}_LIBSOURCES_DIR])",
|
|
" m4_popdef([{macro_prefix}_LIBSOURCES_LIST])",
|
|
" m4_popdef([AC_LIBSOURCES])",
|
|
" m4_popdef([AC_REPLACE_FUNCS])",
|
|
" m4_popdef([AC_LIBOBJ])",
|
|
" AC_CONFIG_COMMANDS_PRE([",
|
|
" {macro_prefix}_libobjs=",
|
|
" {macro_prefix}_ltlibobjs=",
|
|
" if test -n \"${macro_prefix}_LIBOBJS\"; then",
|
|
" # Remove the extension.",
|
|
" sed_drop_objext='s/\\.o$//;s/\\.obj$//'",
|
|
" for i in `for i in ${macro_prefix}_LIBOBJS; " # comma omitted
|
|
"do echo \"$i\"; done | sed -e \"$sed_drop_objext\" | sort | uniq`; do",
|
|
" {macro_prefix}_libobjs=\"${macro_prefix}_libobjs $i.$ac_objext\"",
|
|
" {macro_prefix}_ltlibobjs=\"${macro_prefix}_ltlibobjs $i.lo\"",
|
|
" done",
|
|
" fi",
|
|
" AC_SUBST([{macro_prefix}_LIBOBJS], [${macro_prefix}_libobjs])",
|
|
" AC_SUBST([{macro_prefix}_LTLIBOBJS], [${macro_prefix}_ltlibobjs])",
|
|
" ])",
|
|
)
|
|
|
|
def init_macro_footer(config, **override):
|
|
"""Generate the last few statements of the gl_INIT macro."""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
macro_prefix = config.macro_prefix
|
|
|
|
for line in __INIT_MACRO_FOOTER:
|
|
yield line.format(**config)
|
|
|
|
|
|
|
|
__INIT_MACRO_DONE = (
|
|
"",
|
|
"# Like AC_LIBOBJ, except that the module name goes",
|
|
"# into {macro_prefix}_LIBOBJS instead of into LIBOBJS.",
|
|
"AC_DEFUN([{macro_prefix}_LIBOBJ], [",
|
|
" AS_LITERAL_IF([$1], [{macro_prefix}_LIBSOURCES([$1.c])])dnl",
|
|
" {macro_prefix}_LIBOBJS=\"${macro_prefix}_LIBOBJS $1.$ac_objext\"",
|
|
"])",
|
|
"",
|
|
"# Like AC_REPLACE_FUNCS, except that the module name goes",
|
|
"# into {macro_prefix}_LIBOBJS instead of into LIBOBJS.",
|
|
"AC_DEFUN([{macro_prefix}_REPLACE_FUNCS], [",
|
|
" m4_foreach_w([gl_NAME], [$1], [AC_LIBSOURCES(gl_NAME[.c])])dnl",
|
|
" AC_CHECK_FUNCS([$1], , [{macro_prefix}_LIBOBJ($ac_func)])",
|
|
"])",
|
|
"",
|
|
"# Like AC_LIBSOURCES, except the directory where the source file is",
|
|
"# expected is derived from the gnulib-tool parameterization,",
|
|
"# and alloca is special cased (for the alloca-opt module).",
|
|
"# We could also entirely rely on EXTRA_lib..._SOURCES.",
|
|
"AC_DEFUN([{macro_prefix}_LIBSOURCES], [",
|
|
" m4_foreach([_gl_NAME], [$1], [",
|
|
" m4_if(_gl_NAME, [alloca.c], [], [",
|
|
" m4_define([{macro_prefix}_LIBSOURCES_DIR], [{source_base}])",
|
|
" m4_append([{macro_prefix}_LIBSOURCES_LIST], _gl_NAME, [ ])",
|
|
" ])",
|
|
" ])",
|
|
"])",
|
|
)
|
|
|
|
def init_macro_done(config, **override):
|
|
"""
|
|
Generate few statements after the gl_INIT macro.
|
|
|
|
[macro_prefix] the prefix of the macros 'gl_EARLY' and 'gl_INIT'
|
|
"""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
|
|
for line in __INIT_MACRO_DONE:
|
|
yield line.format(**config)
|
|
|
|
|
|
|
|
__COMMAND_LINE_PATHS = (
|
|
("libname", lambda k, v, d: f"--lib={v}"),
|
|
("source_base", lambda k, v, d: f"--source-base={v}"),
|
|
("m4_base", lambda k, v, d: f"--m4-base={v}"),
|
|
("po_base", lambda k, v, d: f"--po-base={v}" if k in d else None),
|
|
("doc_base", lambda k, v, d: f"--doc-base={v}"),
|
|
("tests_base", lambda k, v, d: f"--tests-base={v}"),
|
|
("auxdir", lambda k, v, d: f"--aux-dir={v}"),
|
|
)
|
|
__COMMAND_LINE_TESTS = (
|
|
("tests", lambda v: "--with-tests" if v else None),
|
|
("cxx_tests", lambda v: "--with-c++-tests" if v else None),
|
|
("longrunning_tests", lambda v: "--with-longrunning-tests" if v else None),
|
|
("privileged_tests", lambda v: "--with-privileged-tests" if v else None),
|
|
("unportable_tests", lambda v: "--with-unportable-tests" if v else None),
|
|
("all_tests", lambda v: "--with-all-tests" if v else None),
|
|
)
|
|
__COMMAND_LINE_MISC = (
|
|
("makefile_name", lambda k, v, d: "" if v is None else f"--makefile-name={v}"),
|
|
("conditionals", lambda k, v, d: ("--no-", "--")[v] + "conditional-dependencies"),
|
|
("libtool", lambda k, v, d: ("--no-", "--")[v] + "libtool"),
|
|
("macro_prefix", lambda k, v, d: f"--macro-prefix={v}"),
|
|
("gnumake", lambda k, v, d: "--gnu-make" if v else None),
|
|
("po_domain", lambda k, v, d: f"--po-domain={v}" if k in d else None),
|
|
("witness_c_macro", lambda k, v, d: f"--witness-c-macro={v}" if k in d else None),
|
|
("vc_files", lambda k, v, d: ("--no-", "--")[v] + "vc-files" if k in d else None),
|
|
)
|
|
|
|
def command_line(config, explicit, **override):
|
|
"""Generate gnulib command-line invocation."""
|
|
yield "gnulib-tool --import"
|
|
for path in config.overrides:
|
|
yield f"--local-dir={path}"
|
|
for (key, hook) in __COMMAND_LINE_PATHS:
|
|
value = config[key]
|
|
option = hook(key, value, explicit)
|
|
if option is not None:
|
|
yield option
|
|
for (key, hook) in __COMMAND_LINE_TESTS:
|
|
value = config[key]
|
|
option = hook(value)
|
|
if option is not None:
|
|
yield option
|
|
for module in config.avoids:
|
|
yield f"--avoid={module}"
|
|
licenses = tuple(sorted(config.licenses))
|
|
if licenses in _LGPL:
|
|
lgpl = _LGPL[licenses]
|
|
if lgpl != "yes":
|
|
yield f"--lgpl={lgpl}"
|
|
else:
|
|
yield "--lgpl"
|
|
for (key, hook) in __COMMAND_LINE_MISC:
|
|
value = config[key]
|
|
option = hook(key, value, explicit)
|
|
if option is not None:
|
|
yield option
|
|
for module in config.modules:
|
|
yield f"{module}"
|
|
|
|
|
|
|
|
__MAKEFILE_PKGDATA = _re.compile(r"^pkgdata_DATA\s+\=")
|
|
__MAKEFILE_SUBDIRS = _re.compile(r"lib/.*/.*\.c", _re.S)
|
|
__MAKEFILE_LDFLAGS = _re.compile(r"^lib_LDFLAGS\s*\+\=.*?$", _re.S)
|
|
__MAKEFILE_LIBNAME = _re.compile(r"lib_([A-Z][A-Z]*)", _re.S)
|
|
__MAKEFILE_GNUMAKE = _re.compile(r"^if\s(.*?)$", _re.S | _re.M)
|
|
|
|
|
|
def _lib_makefile_callback(database, macro_prefix, conditionals, gnumake):
|
|
|
|
def _automake_conditional(module, conditional, unconditional):
|
|
yield ""
|
|
if database.conditional(module):
|
|
yield "if {}".format(module.conditional_name(macro_prefix))
|
|
yield conditional
|
|
yield "endif"
|
|
else:
|
|
yield conditional
|
|
yield unconditional
|
|
|
|
def _automake_unconditional(module, conditional, unconditional):
|
|
yield ""
|
|
yield conditional
|
|
yield unconditional
|
|
|
|
def _gnumake_conditional(module, conditional, unconditional):
|
|
yield "ifeq (,$(OMIT_GNULIB_MODULE_{}))".format(module.name)
|
|
yield ""
|
|
if database.conditional(module):
|
|
yield "ifneq (,$({}))".format(module.conditional_name(macro_prefix))
|
|
yield __MAKEFILE_GNUMAKE.sub("ifneq (,$(\\1))", conditional)
|
|
yield "endif"
|
|
else:
|
|
yield __MAKEFILE_GNUMAKE.sub("ifneq (,$(\\1))", conditional)
|
|
yield "endif"
|
|
yield __MAKEFILE_GNUMAKE.sub("ifneq (,$(\\1))", unconditional)
|
|
|
|
def _gnumake_unconditional(module, conditional, unconditional):
|
|
yield ""
|
|
yield __MAKEFILE_GNUMAKE.sub("ifneq (,$(\\1))", conditional)
|
|
yield __MAKEFILE_GNUMAKE.sub("ifneq (,$(\\1))", unconditional)
|
|
|
|
callbacks = (
|
|
(_automake_unconditional, _gnumake_unconditional),
|
|
(_automake_conditional, _gnumake_conditional),
|
|
)
|
|
return callbacks[conditionals][gnumake]
|
|
|
|
|
|
def lib_makefile(path, config, explicit, database, mkedits, testing, autoconf, **override):
|
|
"""Generate library Makefile.am file."""
|
|
if not isinstance(autoconf, _Executable):
|
|
raise TypeError("autoconf: executable expected")
|
|
|
|
date = _datetime.now()
|
|
libname = config.libname
|
|
po_domain = config.po_domain
|
|
macro_prefix = config.macro_prefix
|
|
libext = "la" if config.libtool else "a"
|
|
perhaps_LT = "LT" if config.libtool else ""
|
|
assign = "+=" if config.gnumake or "makefile_name" in explicit else "="
|
|
eliminate_LDFLAGS = True if config.libtool else False
|
|
|
|
# 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.
|
|
transform_check_PROGRAMS = True if testing else False
|
|
|
|
yield "## DO NOT EDIT! GENERATED AUTOMATICALLY!"
|
|
yield "## Process this file with automake to produce Makefile.in."
|
|
yield f"# Copyright (C) 2002-{date.year} Free Software Foundation, Inc."
|
|
for line in __DISCLAIMER[1:]:
|
|
yield line
|
|
yield ""
|
|
|
|
# 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.
|
|
actioncmd = " ".join(command_line(config, explicit))
|
|
if len(actioncmd) <= 3000:
|
|
yield f"# Reproduce by: {actioncmd}"
|
|
yield ""
|
|
|
|
callback = _lib_makefile_callback(database, macro_prefix, config.conditionals, config.gnumake)
|
|
def _snippet():
|
|
lines = []
|
|
subdirs = False
|
|
for module in database.main_modules:
|
|
if module.test:
|
|
continue
|
|
conditional = module.conditional_automake_snippet
|
|
conditional = conditional.replace("lib_LIBRARIES", "lib%_LIBRARIES")
|
|
conditional = conditional.replace("lib_LTLIBRARIES", "lib%_LTLIBRARIES")
|
|
if eliminate_LDFLAGS:
|
|
conditional = __MAKEFILE_LDFLAGS.sub("", conditional)
|
|
conditional = __MAKEFILE_LIBNAME.sub(f"{libname}_{libext}_\\1", conditional)
|
|
conditional = conditional.replace("lib%_LIBRARIES", "lib_LIBRARIES")
|
|
conditional = conditional.replace("lib%_LTLIBRARIES", "lib_LTLIBRARIES")
|
|
if transform_check_PROGRAMS:
|
|
conditional = conditional.replace("check_PROGRAMS", "noinst_PROGRAMS")
|
|
conditional = conditional.replace(r"${gl_include_guard_prefix}", config.include_guard_prefix)
|
|
unconditional = module.unconditional_automake_snippet.format(auxdir=config.auxdir)
|
|
unconditional = __MAKEFILE_LIBNAME.sub(f"{libname}_{libext}_\\1", unconditional)
|
|
if (conditional + unconditional).strip():
|
|
lines.append(f"## begin gnulib module {module.name}")
|
|
if module.name == "alloca":
|
|
lines.append(f"{libname}_{libext}_LIBADD += @{perhaps_LT}ALLOCA@")
|
|
lines.append(f"{libname}_{libext}_DEPENDENCIES += @{perhaps_LT}ALLOCA@")
|
|
lines += list(callback(module, conditional, unconditional))
|
|
lines.append(f"## end gnulib module {module.name}")
|
|
lines.append("")
|
|
subdirs |= any(__MAKEFILE_SUBDIRS.match(file) for file in module.files)
|
|
return (subdirs, lines)
|
|
|
|
(subdirs, lines) = _snippet()
|
|
if "makefile_name" not in explicit:
|
|
# If there are source files in subdirectories, prevent collision of the
|
|
# object files (example: hash.c and libxml/hash.c).
|
|
yield "AUTOMAKE_OPTIONS = 1.9.6 gnits{}".format(" subdir-objects" if subdirs else "")
|
|
yield ""
|
|
if "makefile_name" not in explicit:
|
|
yield "SUBDIRS ="
|
|
yield "noinst_HEADERS ="
|
|
yield "noinst_LIBRARIES ="
|
|
yield "noinst_LTLIBRARIES ="
|
|
# Automake versions < 1.11.4 create an empty pkgdatadir at
|
|
# installation time if you specify pkgdata_DATA to empty.
|
|
# See automake bugs #10997 and #11030:
|
|
# * http://debbugs.gnu.org/10997
|
|
# * http://debbugs.gnu.org/11030
|
|
# So we need this workaround.
|
|
if __MAKEFILE_PKGDATA.match("\n".join(lines)):
|
|
yield "pkgdata_DATA ="
|
|
yield "EXTRA_DIST ="
|
|
yield "BUILT_SOURCES ="
|
|
yield "SUFFIXES ="
|
|
yield f"MOSTLYCLEANFILES {assign} core *.stackdump"
|
|
if "makefile_name" not in explicit:
|
|
yield "MOSTLYCLEANDIRS ="
|
|
yield "CLEANFILES ="
|
|
yield "DISTCLEANFILES ="
|
|
yield "MAINTAINERCLEANFILES ="
|
|
|
|
if config.gnumake:
|
|
yield "# Start of GNU Make output."
|
|
with autoconf("-t", "AC_SUBST:$1 = @$1@", config.ac_file) as process:
|
|
(stdout, stderr) = process.communicate()
|
|
stdout = stdout.decode("UTF-8")
|
|
stderr = stderr.decode("UTF-8")
|
|
if process.returncode == 0:
|
|
for line in sorted(set(stdout.splitlines())):
|
|
yield line
|
|
else:
|
|
yield "== gnulib-tool GNU Make output failed as follows =="
|
|
for line in stderr.splitlines():
|
|
yield f"# stderr: {line}"
|
|
yield "# End of GNU Make output."
|
|
else:
|
|
yield "# No GNU Make output."
|
|
|
|
for (directory, key, value) in mkedits:
|
|
if key and _os.path.join(directory, "Makefile.am") == path:
|
|
yield f"{key} += {value}"
|
|
del (directory, key, value)
|
|
|
|
cppflags = "".join((
|
|
" -D{}=1".format(config.witness_c_macro) if "witness_c_macro" in explicit else "",
|
|
" -DGNULIB_STRICT_CHECKING=1" if testing else "",
|
|
))
|
|
if "makefile_name" not in explicit:
|
|
yield ""
|
|
yield f"AM_CPPFLAGS ={cppflags}"
|
|
yield "AM_CFLAGS ="
|
|
elif "".join(cppflags):
|
|
yield ""
|
|
yield f"AM_CPPFLAGS +={cppflags}"
|
|
yield ""
|
|
|
|
snippet = "\n".join(lines)
|
|
if "makefile_name" in explicit:
|
|
makefile = _os.path.join(config.source_base, "Makefile.am")
|
|
if _os.path.exists(makefile):
|
|
with _codecs.open(makefile, "rb", "UTF-8") as stream:
|
|
snippet += ("\n" + stream.read())
|
|
# 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.
|
|
# By default, the generated library should not be installed.
|
|
pattern = _re.compile(f"^[a-zA-Z0-9_]*_{perhaps_LT}LIBRARIES\\s*\\+?\\=\\s*{libname}\\.{libext}$", _re.S)
|
|
if not pattern.findall(snippet):
|
|
yield f"noinst_{perhaps_LT}LIBRARIES += {libname}.{libext}"
|
|
|
|
yield ""
|
|
yield f"{libname}_{libext}_SOURCES ="
|
|
# Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However,
|
|
# automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@.
|
|
yield f"{libname}_{libext}_LIBADD = $({macro_prefix}_{perhaps_LT}LIBOBJS)"
|
|
yield f"{libname}_{libext}_DEPENDENCIES = $({macro_prefix}_{perhaps_LT}LIBOBJS)"
|
|
yield f"EXTRA_{libname}_{libext}_SOURCES ="
|
|
if config.libtool:
|
|
yield f"{libname}_{libext}_LDFLAGS = $(AM_LDFLAGS)"
|
|
yield f"{libname}_{libext}_LDFLAGS += -no-undefined"
|
|
# Synthesize an ${libname}_${libext}_LDFLAGS augmentation by combining
|
|
# the link dependencies of all modules.
|
|
def _directives(modules):
|
|
for module in modules:
|
|
for directive in module.link_directives:
|
|
index = directive.find("when linking with libtool")
|
|
if index != -1:
|
|
directive = directive[:index].strip(" ")
|
|
yield directive
|
|
for directive in sorted(set(_directives(database.main_modules))):
|
|
yield f"{libname}_{libext}_LDFLAGS += {directive}"
|
|
yield ""
|
|
|
|
if "po_base" in explicit:
|
|
yield f"AM_CPPFLAGS += -DDEFAULT_TEXT_DOMAIN=\\\"{po_domain}-gnulib\\\""
|
|
yield ""
|
|
|
|
for line in lines:
|
|
src = "$(top_srcdir)/build-aux/"
|
|
dst = _os.path.join("$(top_srcdir)", config.auxdir)
|
|
dst += _os.path.sep
|
|
yield line.replace(src, dst)
|
|
yield ""
|
|
yield "mostlyclean-local: mostlyclean-generic"
|
|
yield "\t@for dir in '' $(MOSTLYCLEANDIRS); do \\"
|
|
yield "\t if test -n \"$$dir\" && test -d $$dir; then \\"
|
|
yield "\t echo \"rmdir $$dir\"; rmdir $$dir; \\"
|
|
yield "\t fi; \\"
|
|
yield "\tdone; \\"
|
|
yield "\t:"
|
|
|
|
|
|
def _tests_makefile_callback(gnumake):
|
|
|
|
def _automake(module, snippet):
|
|
yield ""
|
|
yield snippet
|
|
|
|
def _gnumake(module, snippet):
|
|
yield f"ifeq (,$(OMIT_GNULIB_MODULE_{module.name}))"
|
|
yield ""
|
|
yield snippet
|
|
yield "endif"
|
|
|
|
return _gnumake if gnumake else _automake
|
|
|
|
def tests_makefile(path, config, explicit, modules, mkedits, testing, libtests):
|
|
"""Generate tests Makefile.am file."""
|
|
single_configure = config.single_configure
|
|
if testing and not single_configure:
|
|
modules = sorted(filter(lambda module: module.test, modules))
|
|
|
|
date = _datetime.now()
|
|
tests_base = config.tests_base
|
|
source_base = config.source_base
|
|
m4_base = config.m4_base
|
|
macro_prefix = config.macro_prefix
|
|
witness_c_macro = config.witness_c_macro
|
|
tests_base_inverse = "/".join(".." for _ in config.tests_base.split(_os.path.sep))
|
|
(libname, libext) = (config.libname, "la" if config.libtool else "a")
|
|
assign = "+=" if config.gnumake or "makefile_name" in explicit else "="
|
|
eliminate_LDFLAGS = True if config.libtool else False
|
|
|
|
# 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.
|
|
transform_check_PROGRAMS = True if testing else False
|
|
|
|
yield "## DO NOT EDIT! GENERATED AUTOMATICALLY!"
|
|
yield "## Process this file with automake to produce Makefile.in."
|
|
yield f"# Copyright (C) 2002-{date.year} Free Software Foundation, Inc."
|
|
for line in __DISCLAIMER[1:]:
|
|
yield line
|
|
yield ""
|
|
|
|
callback = _tests_makefile_callback(config.gnumake)
|
|
def _snippet():
|
|
main = []
|
|
longrunning = []
|
|
subdirs = False
|
|
for module in modules:
|
|
lines = []
|
|
snippet = module.automake_snippet
|
|
snippet = snippet.replace("lib_LIBRARIES", "lib%_LIBRARIES")
|
|
snippet = snippet.replace("lib_LTLIBRARIES", "lib%_LTLIBRARIES")
|
|
if eliminate_LDFLAGS:
|
|
snippet = __MAKEFILE_LDFLAGS.sub("", snippet)
|
|
snippet = __MAKEFILE_LIBNAME.sub("libtests_a_\\1", snippet)
|
|
snippet = snippet.replace("lib%_LIBRARIES", "lib_LIBRARIES")
|
|
snippet = snippet.replace("lib%_LTLIBRARIES", "lib_LTLIBRARIES")
|
|
if transform_check_PROGRAMS:
|
|
snippet = snippet.replace("check_PROGRAMS", "noinst_PROGRAMS")
|
|
snippet = snippet.replace(r"${gl_include_guard_prefix}", config.include_guard_prefix)
|
|
if libtests and module.name == "alloca":
|
|
lines += ["libtests_a_LIBADD += @ALLOCA@"]
|
|
lines += ["libtests_a_DEPENDENCIES += @ALLOCA@"]
|
|
subdirs |= any(__MAKEFILE_SUBDIRS.match(file) for file in module.files)
|
|
if snippet.strip():
|
|
lines.append(f"## begin gnulib module {module.name}")
|
|
lines += list(callback(module, snippet))
|
|
lines.append(f"## end gnulib module {module.name}")
|
|
lines.append("")
|
|
if module.longrunning_test:
|
|
longrunning += lines
|
|
else:
|
|
main += lines
|
|
lines = (main + longrunning)
|
|
return (subdirs, lines)
|
|
|
|
(subdirs, lines) = _snippet()
|
|
|
|
# Generate dependencies here, since it eases the debugging of test failures.
|
|
# If there are source files in subdirectories, prevent collision of the
|
|
# object files (example: hash.c and libxml/hash.c).
|
|
subdir_options = " subdir-objects" if subdirs else ""
|
|
yield f"AUTOMAKE_OPTIONS = 1.9.6 foreign{subdir_options}"
|
|
yield ""
|
|
if testing and not single_configure:
|
|
yield f"ACLOCAL_AMFLAGS = -I {tests_base_inverse}/{m4_base}"
|
|
yield ""
|
|
|
|
# Nothing is being added to SUBDIRS; nevertheless the existence of this
|
|
# variable is needed to avoid an error from automake:
|
|
# "AM_GNU_GETTEXT used but SUBDIRS not defined"
|
|
yield "SUBDIRS = ."
|
|
yield "TESTS ="
|
|
yield "XFAIL_TESTS ="
|
|
yield "TESTS_ENVIRONMENT ="
|
|
yield "noinst_PROGRAMS ="
|
|
if not testing:
|
|
yield "check_PROGRAMS ="
|
|
yield "EXTRA_PROGRAMS ="
|
|
yield "noinst_HEADERS ="
|
|
yield "noinst_LIBRARIES ="
|
|
if libtests:
|
|
if testing:
|
|
yield "noinst_LIBRARIES += libtests.a"
|
|
else:
|
|
yield "check_LIBRARIES = libtests.a"
|
|
|
|
# Automake versions < 1.11.4 create an empty pkgdatadir at
|
|
# installation time if you specify pkgdata_DATA to empty.
|
|
# See automake bugs #10997 and #11030:
|
|
# * http://debbugs.gnu.org/10997
|
|
# * http://debbugs.gnu.org/11030
|
|
# So we need this workaround.
|
|
if __MAKEFILE_PKGDATA.match("\n".join(lines)):
|
|
yield "pkgdata_DATA ="
|
|
|
|
yield "EXTRA_DIST ="
|
|
yield "BUILT_SOURCES ="
|
|
yield "SUFFIXES ="
|
|
yield "MOSTLYCLEANFILES = core *.stackdump"
|
|
yield "MOSTLYCLEANDIRS ="
|
|
yield "CLEANFILES ="
|
|
yield "DISTCLEANFILES ="
|
|
yield "MAINTAINERCLEANFILES ="
|
|
|
|
# Execute edits that apply to the Makefile.am being generated.
|
|
for (directory, key, value) in mkedits:
|
|
if key and _os.path.join(directory, "Makefile.am") == path:
|
|
del (directory, key, value)
|
|
yield f"{key} += {value}"
|
|
|
|
yield ""
|
|
yield "AM_CPPFLAGS = \\"
|
|
if testing:
|
|
yield " -DGNULIB_STRICT_CHECKING=1 \\"
|
|
if "witness_c_macro" in explicit:
|
|
yield " -D{witness_c_macro}=1 \\"
|
|
yield " -D@{witness_c_macro}@=1 \\"
|
|
yield f" -I. -I$(srcdir) \\"
|
|
yield f" -I{tests_base_inverse} -I$(srcdir)/{tests_base_inverse} \\"
|
|
yield f" -I{tests_base_inverse}/{source_base} -I$(srcdir)/{tests_base_inverse}/{source_base}"
|
|
yield f""
|
|
|
|
# All test programs need to be linked with libtests.a.
|
|
# It needs to be passed to the linker before ${libname}.${libext}, since
|
|
# the tests-related modules depend on the main modules.
|
|
# It also needs to be passed to the linker after ${libname}.${libext}
|
|
# because the latter might contain incomplete modules (such as the 'error'
|
|
# module whose dependency to 'progname' is voluntarily omitted).
|
|
# The LIBTESTS_LIBDEPS can be passed to the linker once or twice, it does
|
|
# not matter.
|
|
local_ldadd_before = " libtests.a" if libtests else ""
|
|
local_ldadd_after = " libtests.a $(LIBTESTS_LIBDEPS)" if libtests else ""
|
|
yield f"LDADD ={local_ldadd_before} {tests_base_inverse}/{source_base}/{libname}.{libext}{local_ldadd_after}"
|
|
yield ""
|
|
|
|
if libtests:
|
|
yield "libtests_a_SOURCES ="
|
|
# Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However,
|
|
# automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@.
|
|
yield f"libtests_a_LIBADD = $({macro_prefix}tests_LIBOBJS)"
|
|
yield f"libtests_a_DEPENDENCIES = $({macro_prefix}tests_LIBOBJS)"
|
|
yield "EXTRA_libtests_a_SOURCES ="
|
|
# The circular dependency in LDADD requires this.
|
|
yield "AM_LIBTOOLFLAGS = --preserve-dup-deps"
|
|
yield ""
|
|
|
|
# Many test scripts use ${EXEEXT} or ${srcdir}.
|
|
# EXEEXT is defined by AC_PROG_CC through autoconf.
|
|
# srcdir is defined by autoconf and automake.
|
|
yield "TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'"
|
|
yield ""
|
|
|
|
for line in lines:
|
|
src = "$(top_srcdir)/build-aux/"
|
|
dst = _os.path.join("$(top_srcdir)", config.auxdir)
|
|
dst += _os.path.sep
|
|
yield line.replace(src, dst)
|
|
yield ""
|
|
yield "# Clean up after Solaris cc."
|
|
yield "clean-local:"
|
|
yield "\trm -rf SunWS_cache"
|
|
yield ""
|
|
yield "mostlyclean-local: mostlyclean-generic"
|
|
yield "\t@for dir in '' $(MOSTLYCLEANDIRS); do \\"
|
|
yield "\t if test -n \"$$dir\" && test -d $$dir; then \\"
|
|
yield "\t echo \"rmdir $$dir\"; rmdir $$dir; \\"
|
|
yield "\t fi; \\"
|
|
yield "\tdone; \\"
|
|
yield "\t:"
|
|
|
|
|
|
|
|
__GNULIB_CACHE_OPTIONS = (
|
|
("obsolete", "gl_WITH_OBSOLETE"),
|
|
("cxx_tests", "gl_WITH_CXX_TESTS"),
|
|
("longrunning", "gl_WITH_LONGRUNNING_TESTS"),
|
|
("privileged", "gl_WITH_PRIVILEGED_TESTS"),
|
|
)
|
|
|
|
def gnulib_cache(config, explicit):
|
|
"""
|
|
Generate gnulib-cache.m4 file.
|
|
"""
|
|
date = _datetime.now()
|
|
yield "## DO NOT EDIT! GENERATED AUTOMATICALLY!"
|
|
yield "## Process this file with automake to produce Makefile.in."
|
|
yield f"# Copyright (C) 2002-{date.year} Free Software Foundation, Inc."
|
|
for line in __DISCLAIMER:
|
|
yield line
|
|
yield "#"
|
|
yield "# This file represents the specification of how gnulib-tool is used."
|
|
yield "# It acts as a cache: It is written and read by gnulib-tool."
|
|
yield "# In projects that use version control, this file is meant to be put under"
|
|
yield "# version control, like the configure.ac and various Makefile.am files."
|
|
yield ""
|
|
yield ""
|
|
yield "# Specification in the form of a command-line invocation:"
|
|
yield "# " + " ".join(command_line(config, explicit))
|
|
yield ""
|
|
yield "# Specification in the form of a few gnulib-tool.m4 macro invocations:"
|
|
yield "gl_LOCAL_DIR([{}])".format(" ".join(config.overrides))
|
|
yield "gl_MODULES(["
|
|
for module in sorted(config.modules):
|
|
yield f" {module}"
|
|
yield "])"
|
|
for key in ("obsolete", "cxx_tests", "longrunning_tests", "privileged_tests", "unportable_tests"):
|
|
if config[key]:
|
|
yield "gl_WITH_{}".format(key.upper())
|
|
if config.all_tests:
|
|
yield "gl_WITH_ALL_TESTS"
|
|
yield "gl_AVOID([{}])".format(" ".join(sorted(config.avoids)))
|
|
yield f"gl_SOURCE_BASE([{config.source_base}])"
|
|
yield f"gl_M4_BASE([{config.m4_base}])"
|
|
if config.po_base:
|
|
yield f"gl_PO_BASE([{config.po_base}])"
|
|
else:
|
|
yield f"gl_PO_BASE([])"
|
|
yield f"gl_DOC_BASE([{config.doc_base}])"
|
|
yield f"gl_TESTS_BASE([{config.tests_base}])"
|
|
if config.tests:
|
|
yield "gl_WITH_TESTS"
|
|
yield "gl_LIB([{}])".format(config.libname)
|
|
licenses = tuple(sorted(config.licenses))
|
|
if licenses in _LGPL:
|
|
lgpl = _LGPL[licenses]
|
|
if lgpl != "yes":
|
|
yield f"gl_LGPL([{lgpl}])"
|
|
else:
|
|
yield "gl_LGPL([])"
|
|
if config.makefile_name:
|
|
yield f"gl_MAKEFILE_NAME([{config.makefile_name}])"
|
|
else:
|
|
yield f"gl_MAKEFILE_NAME([])"
|
|
if config.conditionals:
|
|
yield "gl_CONDITIONAL_DEPENDENCIES"
|
|
if config.libtool:
|
|
yield "gl_LIBTOOL"
|
|
yield f"gl_MACRO_PREFIX([{config.macro_prefix}])"
|
|
yield f"gl_PO_DOMAIN([{config.po_domain}])"
|
|
yield f"gl_WITNESS_C_MACRO([{config.witness_c_macro}])"
|
|
if config.vc_files:
|
|
yield "gl_VC_FILES([])"
|
|
|
|
|
|
|
|
def gnulib_comp(config, explicit, database, **override):
|
|
"""gnulib-comp.m4 generator"""
|
|
config = _BaseConfig(**config)
|
|
for (key, value) in override.items():
|
|
config[key] = value
|
|
macro_prefix = config.macro_prefix
|
|
main_modules = database.main_modules
|
|
test_modules = database.test_modules
|
|
|
|
subdirs = False
|
|
for module in database.main_modules:
|
|
subdirs |= any(__MAKEFILE_SUBDIRS.match(file) for file in module.files)
|
|
|
|
date = _datetime.now()
|
|
ac_file = config.ac_file
|
|
yield "# DO NOT EDIT! GENERATED AUTOMATICALLY!"
|
|
yield f"# Copyright (C) 2002-{date.year} Free Software Foundation, Inc."
|
|
for line in __DISCLAIMER[1:]:
|
|
yield line
|
|
|
|
yield "#"
|
|
yield "# This file represents the compiled summary of the specification in"
|
|
yield "# gnulib-cache.m4. It lists the computed macro invocations that need"
|
|
yield "# to be invoked from configure.ac."
|
|
yield "# In projects that use version control, this file can be treated like"
|
|
yield "# other built files."
|
|
yield ""
|
|
yield ""
|
|
yield f"# This macro should be invoked from {ac_file}, in the section"
|
|
yield "# \"Checks for programs\", right after AC_PROG_CC, and certainly before"
|
|
yield "# any checks for libraries, header files, types and library functions."
|
|
yield f"AC_DEFUN([{macro_prefix}_EARLY],"
|
|
yield "["
|
|
yield " m4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace"
|
|
yield " m4_pattern_allow([^gl_ES$])dnl a valid locale name"
|
|
yield " m4_pattern_allow([^gl_LIBOBJS$])dnl a variable"
|
|
yield " m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable"
|
|
yield ""
|
|
yield " # Pre-early section."
|
|
if "externsions" not in (module.name for module in database.final_modules):
|
|
yield " AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])"
|
|
yield " AC_REQUIRE([gl_PROG_AR_RANLIB])"
|
|
yield ""
|
|
if not config.gnumake and subdirs:
|
|
yield " AC_REQUIRE([AM_PROG_CC_C_O])"
|
|
for module in database.final_modules:
|
|
yield f" # Code from module {module.name}:"
|
|
lines = module.early_autoconf_snippet.split("\n")
|
|
for line in filter(lambda line: line.strip(), lines):
|
|
yield f" {line}"
|
|
yield "])"
|
|
yield ""
|
|
yield f"# This macro should be invoked from {ac_file}, in the section"
|
|
yield "# \"Check for header files, types and library functions\"."
|
|
yield f"AC_DEFUN([{macro_prefix}_INIT],"
|
|
yield "["
|
|
if config.libtool:
|
|
yield " AM_CONDITIONAL([GL_COND_LIBTOOL], [true])"
|
|
yield " gl_cond_libtool=true"
|
|
else:
|
|
yield " AM_CONDITIONAL([GL_COND_LIBTOOL], [false])"
|
|
yield " gl_cond_libtool=false"
|
|
yield " gl_libdeps="
|
|
yield " gl_ltlibdeps="
|
|
yield f" gl_m4_base='{config.m4_base}'"
|
|
for line in init_macro_header(config, macro_prefix=macro_prefix):
|
|
yield line
|
|
yield f" gl_source_base='{config.source_base}'"
|
|
if "witness_c_macro" in explicit:
|
|
yield f" m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [{config.witness_c_macro}])"
|
|
for line in autoconf_snippets(config, database, main_modules, True, False, True, macro_prefix=macro_prefix):
|
|
yield line
|
|
if "witness_c_macro" in explicit:
|
|
yield " m4_popdef([gl_MODULE_INDICATOR_CONDITION])"
|
|
yield " # End of code from modules"
|
|
for line in init_macro_footer(config, macro_prefix=macro_prefix):
|
|
yield line
|
|
yield " gltests_libdeps="
|
|
yield " gltests_ltlibdeps="
|
|
for line in init_macro_header(config, macro_prefix=(macro_prefix + "tests")):
|
|
yield line
|
|
yield f" gl_source_base='{config.tests_base}'"
|
|
# Define a tests witness macro that depends on the package.
|
|
# PACKAGE is defined by AM_INIT_AUTOMAKE, PACKAGE_TARNAME is defined by AC_INIT.
|
|
# See <http://lists.gnu.org/archive/html/automake/2009-05/msg00145.html>.
|
|
yield "changequote(,)dnl"
|
|
yield "".join((
|
|
f" {macro_prefix}tests_WITNESS=IN_`",
|
|
"echo \"${PACKAGE-$PACKAGE_TARNAME}\"",
|
|
" | ",
|
|
"LC_ALL=C tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
" | ",
|
|
"LC_ALL=C sed -e 's/[^A-Z0-9_]/_/g'",
|
|
"`_GNULIB_TESTS",
|
|
))
|
|
yield "changequote([, ])dnl"
|
|
yield f" AC_SUBST([{macro_prefix}tests_WITNESS])"
|
|
yield f" gl_module_indicator_condition=${macro_prefix}tests_WITNESS"
|
|
yield " m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [$gl_module_indicator_condition])"
|
|
for line in autoconf_snippets(config, database, test_modules, True, True, True, macro_prefix=macro_prefix):
|
|
yield line
|
|
yield " m4_popdef([gl_MODULE_INDICATOR_CONDITION])"
|
|
for line in init_macro_footer(config, macro_prefix=(macro_prefix + "tests")):
|
|
yield line
|
|
|
|
# _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
|
|
# created using libtool, because libtool already handles the dependencies.
|
|
if not config.libtool:
|
|
libname = config.libname.upper()
|
|
yield f" {libname}_LIBDEPS=\"$gl_libdeps\""
|
|
yield f" AC_SUBST([{libname}_LIBDEPS])"
|
|
yield f" {libname}_LTLIBDEPS=\"$gl_ltlibdeps\""
|
|
yield f" AC_SUBST([{libname}_LTLIBDEPS])"
|
|
if database.libtests:
|
|
yield " LIBTESTS_LIBDEPS=\"$gltests_libdeps\""
|
|
yield " AC_SUBST([LIBTESTS_LIBDEPS])"
|
|
yield "])"
|
|
for line in init_macro_done(config, source_base=config.source_base, macro_prefix=macro_prefix):
|
|
yield line
|
|
for line in init_macro_done(config, source_base=config.tests_base, macro_prefix=(macro_prefix + "tests")):
|
|
yield line
|
|
yield ""
|
|
yield "# This macro records the list of files which have been installed by"
|
|
yield "# gnulib-tool and may be removed by future gnulib-tool invocations."
|
|
yield f"AC_DEFUN([{macro_prefix}_FILE_LIST], ["
|
|
test_files = set()
|
|
main_files = set(database.main_files)
|
|
for file in database.test_files:
|
|
if file.startswith("lib/"):
|
|
file = ("tests=lib/" + file[len("lib/"):])
|
|
test_files.add(file)
|
|
for file in sorted(main_files | test_files):
|
|
yield f" {file}"
|
|
yield "])"
|