|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
import re |
|
|
import sys |
|
|
import shlex |
|
|
import subprocess as sp |
|
|
from pathlib import Path |
|
|
from .constants import ( |
|
|
DIRS, |
|
|
TESTS, |
|
|
UTILS, |
|
|
combine_lines, |
|
|
execute, |
|
|
ensure_writable, |
|
|
force_output, |
|
|
hardlink, |
|
|
joinpath, |
|
|
link_relative, |
|
|
lines_to_multiline, |
|
|
movefile, |
|
|
copyfile, |
|
|
substart, |
|
|
bold_escapes, |
|
|
relinverse, |
|
|
rmtree, |
|
|
) |
|
|
from .functions import rewrite_file_name |
|
|
from .enums import CopyAction |
|
|
from .GLError import GLError |
|
|
from .GLConfig import GLConfig |
|
|
from .GLModuleSystem import GLModuleTable, GLModuleSystem |
|
|
from .GLFileSystem import GLFileSystem |
|
|
from .GLMakefileTable import GLMakefileTable |
|
|
from .GLEmiter import GLEmiter |
|
|
from .GLFileTable import GLFileTable |
|
|
|
|
|
|
|
|
def _patch_test_driver() -> None: |
|
|
'''Patch the test-driver script in testdirs.''' |
|
|
test_driver = joinpath('build-aux', 'test-driver') |
|
|
print('patching file %s' % test_driver) |
|
|
diffs = [ joinpath(DIRS['root'], name) |
|
|
for name in [joinpath('build-aux', 'test-driver.diff'), |
|
|
joinpath('build-aux', 'test-driver-1.16.3.diff')] ] |
|
|
patched = False |
|
|
for diff in diffs: |
|
|
command = f'patch {shlex.quote(test_driver)} < {shlex.quote(diff)}' |
|
|
try: |
|
|
result = sp.call(command, shell=True, stdout=sp.DEVNULL, stderr=sp.DEVNULL) |
|
|
except OSError as exc: |
|
|
if os.path.isfile(f'{test_driver}.orig'): |
|
|
os.remove(f'{test_driver}.orig') |
|
|
if os.path.isfile(f'{test_driver}.rej'): |
|
|
os.remove(f'{test_driver}.rej') |
|
|
raise GLError(20, None) from exc |
|
|
if result == 0: |
|
|
patched = True |
|
|
break |
|
|
if os.path.isfile(f'{test_driver}.orig'): |
|
|
os.remove(f'{test_driver}.orig') |
|
|
if os.path.isfile(f'{test_driver}.rej'): |
|
|
os.remove(f'{test_driver}.rej') |
|
|
if not patched: |
|
|
raise GLError(20, None) |
|
|
if os.path.isfile(f'{test_driver}.orig'): |
|
|
os.remove(f'{test_driver}.orig') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GLTestDir: |
|
|
'''GLTestDir class is used to create a scratch package with the given |
|
|
list of the modules.''' |
|
|
|
|
|
config: GLConfig |
|
|
testdir: str |
|
|
emitter: GLEmiter |
|
|
filesystem: GLFileSystem |
|
|
modulesystem: GLModuleSystem |
|
|
makefiletable: GLMakefileTable |
|
|
|
|
|
def __init__(self, config: GLConfig, testdir: str) -> None: |
|
|
'''Create new GLTestDir instance.''' |
|
|
if type(config) is not GLConfig: |
|
|
raise TypeError('config must be a GLConfig, not %s' |
|
|
% type(config).__name__) |
|
|
if type(testdir) is not str: |
|
|
raise TypeError('testdir must be a string, not %s' |
|
|
% type(testdir).__name__) |
|
|
self.config = config |
|
|
self.testdir = os.path.normpath(testdir) |
|
|
|
|
|
if os.path.exists(self.testdir): |
|
|
raise GLError(22, self.testdir) |
|
|
|
|
|
try: |
|
|
os.mkdir(self.testdir) |
|
|
except Exception as exc: |
|
|
raise GLError(19, self.testdir) from exc |
|
|
self.emitter = GLEmiter(self.config) |
|
|
self.filesystem = GLFileSystem(self.config) |
|
|
self.modulesystem = GLModuleSystem(self.config) |
|
|
self.makefiletable = GLMakefileTable(self.config) |
|
|
|
|
|
|
|
|
self.config.setSourceBase('gllib') |
|
|
self.config.setM4Base('glm4') |
|
|
self.config.setDocBase('gldoc') |
|
|
self.config.setTestsBase('gltests') |
|
|
self.config.setMacroPrefix('gl') |
|
|
self.config.resetPoBase() |
|
|
self.config.resetPoDomain() |
|
|
self.config.resetWitnessCMacro() |
|
|
self.config.resetVCFiles() |
|
|
|
|
|
def execute(self) -> None: |
|
|
'''Create a scratch package with the given modules.''' |
|
|
auxdir = self.config['auxdir'] |
|
|
sourcebase = self.config['sourcebase'] |
|
|
m4base = self.config['m4base'] |
|
|
testsbase = self.config['testsbase'] |
|
|
libname = self.config['libname'] |
|
|
libtool = self.config['libtool'] |
|
|
single_configure = self.config['single_configure'] |
|
|
macro_prefix = self.config['macro_prefix'] |
|
|
verbose = self.config['verbosity'] |
|
|
|
|
|
specified_modules = self.config['modules'] |
|
|
if len(specified_modules) == 0: |
|
|
|
|
|
specified_modules = self.modulesystem.list() |
|
|
specified_modules = [ module_name |
|
|
for module_name in specified_modules |
|
|
if self.modulesystem.find(module_name) is not None \ |
|
|
and self.modulesystem.find(module_name).getUsabilityInTestdir() != 'no' ] |
|
|
|
|
|
|
|
|
modules = set() |
|
|
for module_name in specified_modules: |
|
|
module = self.modulesystem.find(module_name) |
|
|
if module is not None: |
|
|
if module.getUsabilityInTestdir() == 'no': |
|
|
if self.config['errors']: |
|
|
raise GLError(24, module_name) |
|
|
else: |
|
|
sys.stderr.write('gnulib-tool: warning: ') |
|
|
sys.stderr.write('module %s cannot be used in a testdir\n' % module_name) |
|
|
else: |
|
|
modules.add(module) |
|
|
specified_modules = sorted(modules) |
|
|
|
|
|
|
|
|
|
|
|
inctests = self.config.checkInclTestCategory(TESTS['tests']) |
|
|
if inctests and self.config.checkSingleConfigure(): |
|
|
self.config.addAvoid('havelib-tests') |
|
|
|
|
|
|
|
|
moduletable = GLModuleTable(self.config, |
|
|
True, |
|
|
self.config.checkInclTestCategory(TESTS['all-tests'])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
saved_inctests = self.config.checkInclTestCategory(TESTS['tests']) |
|
|
self.config.disableInclTestCategory(TESTS['tests']) |
|
|
for requested_module in specified_modules: |
|
|
requested_licence = requested_module.getLicense() |
|
|
if requested_licence != 'GPL': |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
modules = moduletable.transitive_closure([requested_module]) |
|
|
for module in modules: |
|
|
license = module.getLicense() |
|
|
if license not in ['GPLv2+ build tool', 'GPLed build tool', |
|
|
'public domain', 'unlimited', 'unmodifiable license text']: |
|
|
incompatible = False |
|
|
if requested_licence == 'GPLv3+' or requested_licence == 'GPL': |
|
|
if license not in ['LGPLv2+', 'LGPLv3+ or GPLv2+', 'LGPLv3+', 'LGPL', 'GPLv2+', 'GPLv3+', 'GPL']: |
|
|
incompatible = True |
|
|
elif requested_licence == 'GPLv2+': |
|
|
if license not in ['LGPLv2+', 'LGPLv3+ or GPLv2+', 'GPLv2+']: |
|
|
incompatible = True |
|
|
elif requested_licence == 'LGPLv3+' or requested_licence == 'LGPL': |
|
|
if license not in ['LGPLv2+', 'LGPLv3+ or GPLv2+', 'LGPLv3+', 'LGPL']: |
|
|
incompatible = True |
|
|
elif requested_licence == 'LGPLv3+ or GPLv2+': |
|
|
if license not in ['LGPLv2+', 'LGPLv3+ or GPLv2+']: |
|
|
incompatible = True |
|
|
elif requested_licence == 'LGPLv2+': |
|
|
if license not in ['LGPLv2+']: |
|
|
incompatible = True |
|
|
if incompatible: |
|
|
warningmsg = 'module %s depends on a module with an incompatible license: %s' % (requested_module, module) |
|
|
sys.stderr.write('gnulib-tool: warning: %s\n' % warningmsg) |
|
|
self.config.setInclTestCategory(TESTS['tests'], saved_inctests) |
|
|
|
|
|
|
|
|
modules = moduletable.transitive_closure(specified_modules) |
|
|
final_modules = list(modules) |
|
|
|
|
|
|
|
|
if verbose >= 0: |
|
|
(bold_on, bold_off) = bold_escapes() |
|
|
print('Module list with included dependencies (indented):') |
|
|
specified_modules_set = { module.name |
|
|
for module in specified_modules } |
|
|
for module in final_modules: |
|
|
if module.name in specified_modules_set: |
|
|
print(' %s%s%s' % (bold_on, module.name, bold_off)) |
|
|
else: |
|
|
print(' %s' % module.name) |
|
|
|
|
|
|
|
|
if single_configure: |
|
|
|
|
|
main_modules, tests_modules = \ |
|
|
moduletable.transitive_closure_separately(specified_modules, final_modules) |
|
|
|
|
|
if verbose >= 1: |
|
|
print('Main module list:') |
|
|
for module in main_modules: |
|
|
print(' %s' % module.name) |
|
|
print('Tests-related module list:') |
|
|
for module in tests_modules: |
|
|
print(' %s' % module.name) |
|
|
|
|
|
libtests = False |
|
|
for module in tests_modules: |
|
|
files = module.getFiles() |
|
|
for file in files: |
|
|
if file.startswith('lib/'): |
|
|
libtests = True |
|
|
break |
|
|
self.emitter.config.setLibtests(libtests) |
|
|
|
|
|
if single_configure: |
|
|
|
|
|
main_modules = moduletable.add_dummy(main_modules) |
|
|
if libtests: |
|
|
|
|
|
tests_modules = moduletable.add_dummy(tests_modules) |
|
|
else: |
|
|
modules = moduletable.add_dummy(modules) |
|
|
|
|
|
|
|
|
if single_configure: |
|
|
if verbose >= -1: |
|
|
for module in main_modules: |
|
|
notice = module.getNotice().strip('\n') |
|
|
if notice: |
|
|
print('Notice from module %s:' % module.name) |
|
|
pattern = re.compile(r'^(.*)$', re.M) |
|
|
notice = pattern.sub(r' \1', notice) |
|
|
print(notice) |
|
|
else: |
|
|
if verbose >= -1: |
|
|
for module in modules: |
|
|
notice = module.getNotice().strip('\n') |
|
|
if notice: |
|
|
print('Notice from module %s:' % module.name) |
|
|
pattern = re.compile(r'^(.*)$', re.M) |
|
|
notice = pattern.sub(r' \1', notice) |
|
|
print(notice) |
|
|
|
|
|
|
|
|
if single_configure: |
|
|
main_filelist, tests_filelist = \ |
|
|
moduletable.filelist_separately(main_modules, tests_modules) |
|
|
else: |
|
|
main_modules = modules |
|
|
tests_modules = [ module |
|
|
for module in modules |
|
|
if module.repeatModuleInTests() ] |
|
|
main_filelist, tests_filelist = \ |
|
|
moduletable.filelist_separately(main_modules, tests_modules) |
|
|
|
|
|
filelist = sorted(set(main_filelist + tests_filelist)) |
|
|
|
|
|
|
|
|
if verbose >= 0: |
|
|
print('File list:') |
|
|
for file in filelist: |
|
|
if file.startswith('tests=lib/'): |
|
|
rest = file[10:] |
|
|
print(' lib/%s -> tests/%s' % (rest, rest)) |
|
|
else: |
|
|
print(' %s' % file) |
|
|
|
|
|
|
|
|
|
|
|
filelist = sorted(set(filelist + ['build-aux/config.guess', 'build-aux/config.sub'])) |
|
|
|
|
|
|
|
|
|
|
|
new_table = { (rewrite_file_name(file_name, self.config, True), file_name) |
|
|
for file_name in filelist } |
|
|
|
|
|
|
|
|
filetable = GLFileTable(filelist) |
|
|
filetable.new_files = sorted(new_table, key=lambda pair: pair[0]) |
|
|
|
|
|
|
|
|
directories = sorted({ joinpath(self.testdir, os.path.dirname(pair[0])) |
|
|
for pair in filetable.new_files }) |
|
|
for directory in directories: |
|
|
if not os.path.isdir(directory): |
|
|
os.makedirs(directory) |
|
|
|
|
|
|
|
|
for (dest, src) in filetable.new_files: |
|
|
destpath = joinpath(self.testdir, dest) |
|
|
if src.startswith('tests=lib/'): |
|
|
src = substart('tests=lib/', 'lib/', src) |
|
|
lookedup, flag = self.filesystem.lookup(src) |
|
|
if os.path.isfile(destpath): |
|
|
os.remove(destpath) |
|
|
if flag: |
|
|
copyfile(lookedup, destpath) |
|
|
ensure_writable(destpath) |
|
|
else: |
|
|
if self.filesystem.shouldLink(src, lookedup) == CopyAction.Symlink: |
|
|
link_relative(lookedup, destpath) |
|
|
elif self.filesystem.shouldLink(src, lookedup) == CopyAction.Hardlink: |
|
|
hardlink(lookedup, destpath) |
|
|
else: |
|
|
copyfile(lookedup, destpath) |
|
|
ensure_writable(destpath) |
|
|
|
|
|
|
|
|
for_test = True |
|
|
directory = joinpath(self.testdir, sourcebase) |
|
|
if not os.path.isdir(directory): |
|
|
os.mkdir(directory) |
|
|
destfile = joinpath(directory, 'Makefile.am') |
|
|
if single_configure: |
|
|
emit = self.emitter.lib_Makefile_am(destfile, main_modules, |
|
|
moduletable, self.makefiletable, '', for_test) |
|
|
else: |
|
|
emit = self.emitter.lib_Makefile_am(destfile, modules, |
|
|
moduletable, self.makefiletable, '', for_test) |
|
|
with open(destfile, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
directory = joinpath(self.testdir, m4base) |
|
|
if not os.path.isdir(directory): |
|
|
os.mkdir(directory) |
|
|
destfile = joinpath(directory, 'Makefile.am') |
|
|
emit = '## Process this file with automake to produce Makefile.in.\n\n' |
|
|
emit += 'EXTRA_DIST =\n' |
|
|
for file in filetable.all_files: |
|
|
if file.startswith('m4/'): |
|
|
file = substart('m4/', '', file) |
|
|
emit += 'EXTRA_DIST += %s\n' % file |
|
|
with open(destfile, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
subdirs = [sourcebase, m4base] |
|
|
subdirs_with_configure_ac = [] |
|
|
|
|
|
inctests = self.config.checkInclTestCategory(TESTS['tests']) |
|
|
if inctests: |
|
|
directory = joinpath(self.testdir, testsbase) |
|
|
if not os.path.isdir(directory): |
|
|
os.mkdir(directory) |
|
|
if single_configure: |
|
|
|
|
|
destfile = joinpath(directory, 'Makefile.am') |
|
|
witness_macro = '%stests_WITNESS' % macro_prefix |
|
|
emit = self.emitter.tests_Makefile_am(destfile, tests_modules, moduletable, |
|
|
self.makefiletable, witness_macro, for_test) |
|
|
with open(destfile, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
else: |
|
|
|
|
|
destfile = joinpath(directory, 'Makefile.am') |
|
|
libtests = False |
|
|
self.config.setLibtests(False) |
|
|
emit = self.emitter.tests_Makefile_am(destfile, modules, moduletable, |
|
|
self.makefiletable, '', for_test) |
|
|
with open(destfile, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
emit = '' |
|
|
saved_auxdir = auxdir |
|
|
auxdir = os.path.normpath(joinpath(relinverse(testsbase), auxdir)) |
|
|
self.config.setAuxDir(auxdir) |
|
|
|
|
|
emit += '# Process this file with autoconf ' |
|
|
emit += 'to produce a configure script.\n' |
|
|
emit += 'AC_INIT([dummy], [0])\n' |
|
|
emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir |
|
|
emit += 'AM_INIT_AUTOMAKE\n\n' |
|
|
emit += 'AC_CONFIG_HEADERS([config.h])\n\n' |
|
|
emit += 'AC_PROG_CC\n' |
|
|
emit += 'AC_PROG_INSTALL\n' |
|
|
emit += 'AC_PROG_MAKE_SET\n' |
|
|
emit += self.emitter.preEarlyMacros(False, '', modules) |
|
|
snippets = [] |
|
|
for module in modules: |
|
|
if module.name in ['gnumakefile', 'maintainer-makefile']: |
|
|
|
|
|
pass |
|
|
|
|
|
else: |
|
|
snippet = module.getAutoconfEarlySnippet() |
|
|
lines = [ line |
|
|
for line in snippet.split('\n') |
|
|
if line.strip() ] |
|
|
snippet = lines_to_multiline(lines) |
|
|
pattern = re.compile(r'AC_REQUIRE\(\[([^()]*)]\)', re.M) |
|
|
snippet = pattern.sub(r'\1', snippet) |
|
|
snippet = snippet.strip() |
|
|
snippets.append(snippet) |
|
|
snippets = [ snippet |
|
|
for snippet in snippets |
|
|
if snippet.strip()] |
|
|
emit += lines_to_multiline(snippets) |
|
|
if libtool: |
|
|
emit += 'LT_INIT([win32-dll])\n' |
|
|
emit += 'LT_LANG([C++])\n' |
|
|
emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' |
|
|
emit += 'gl_cond_libtool=true\n' |
|
|
else: |
|
|
emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' |
|
|
emit += 'gl_cond_libtool=false\n' |
|
|
emit += 'gl_libdeps=\n' |
|
|
emit += 'gl_ltlibdeps=\n' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit += 'AC_DEFUN([gl_INIT], [\n' |
|
|
replace_auxdir = True |
|
|
emit += "gl_m4_base='../%s'\n" % m4base |
|
|
emit += self.emitter.initmacro_start(macro_prefix, True) |
|
|
|
|
|
|
|
|
|
|
|
emit += self.emitter.shellvars_init(True, f'../{sourcebase}') |
|
|
emit += self.emitter.autoconfSnippets(modules, modules, moduletable, |
|
|
lambda module: module.isNonTests(), |
|
|
False, False, False, replace_auxdir) |
|
|
emit += self.emitter.shellvars_init(True, '.') |
|
|
emit += self.emitter.autoconfSnippets(modules, modules, moduletable, |
|
|
lambda module: module.isTests(), |
|
|
False, False, False, replace_auxdir) |
|
|
emit += self.emitter.initmacro_end(macro_prefix, True) |
|
|
|
|
|
|
|
|
|
|
|
if not libtool: |
|
|
libname_upper = libname.upper().replace('-', '_') |
|
|
emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper |
|
|
emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper |
|
|
emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper |
|
|
emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper |
|
|
emit += '])\n' |
|
|
|
|
|
emit += self.emitter.initmacro_done(macro_prefix, sourcebase) |
|
|
emit += '\ngl_INIT\n\n' |
|
|
|
|
|
|
|
|
|
|
|
emit += 'AH_TOP([#include \"../config.h\"])\n\n' |
|
|
emit += 'AC_CONFIG_FILES([Makefile])\n' |
|
|
emit += 'AC_OUTPUT\n' |
|
|
path = joinpath(self.testdir, testsbase, 'configure.ac') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
self.config.setAuxDir(saved_auxdir) |
|
|
auxdir = self.config['auxdir'] |
|
|
subdirs_with_configure_ac.append(testsbase) |
|
|
|
|
|
subdirs.append(testsbase) |
|
|
|
|
|
|
|
|
emit = '## Process this file with automake to produce Makefile.in.\n\n' |
|
|
emit += 'AUTOMAKE_OPTIONS = 1.14 foreign\n\n' |
|
|
emit += 'SUBDIRS = %s\n\n' % ' '.join(subdirs) |
|
|
emit += 'ACLOCAL_AMFLAGS = -I %s\n' % m4base |
|
|
path = joinpath(self.testdir, 'Makefile.am') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
emit = '# Process this file with autoconf ' |
|
|
emit += 'to produce a configure script.\n' |
|
|
emit += 'AC_INIT([dummy], [0])\n' |
|
|
if auxdir != '.': |
|
|
emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir |
|
|
emit += 'AM_INIT_AUTOMAKE\n\n' |
|
|
emit += 'AC_CONFIG_HEADERS([config.h])\n\n' |
|
|
emit += 'AC_PROG_CC\n' |
|
|
emit += 'AC_PROG_INSTALL\n' |
|
|
emit += 'AC_PROG_MAKE_SET\n\n' |
|
|
emit += '# For autobuild.\n' |
|
|
emit += 'AC_CANONICAL_BUILD\n' |
|
|
emit += 'AC_CANONICAL_HOST\n\n' |
|
|
emit += 'm4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace\n' |
|
|
emit += 'm4_pattern_allow([^gl_ES$])dnl a valid locale name\n' |
|
|
emit += 'm4_pattern_allow([^gl_LIBOBJS$])dnl a variable\n' |
|
|
emit += 'm4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable\n' |
|
|
emit += self.emitter.preEarlyMacros(False, '', modules) |
|
|
snippets = [] |
|
|
for module in final_modules: |
|
|
if single_configure: |
|
|
solution = True |
|
|
else: |
|
|
solution = module.isNonTests() |
|
|
if solution: |
|
|
snippet = module.getAutoconfEarlySnippet() |
|
|
lines = [ line |
|
|
for line in snippet.split('\n') |
|
|
if line.strip() ] |
|
|
snippet = lines_to_multiline(lines) |
|
|
pattern = re.compile(r'AC_REQUIRE\(\[([^()]*)]\)', re.M) |
|
|
snippet = pattern.sub(r'\1', snippet) |
|
|
snippet = snippet.strip() |
|
|
snippets.append(snippet) |
|
|
snippets = [ snippet |
|
|
for snippet in snippets |
|
|
if snippet.strip() ] |
|
|
emit += lines_to_multiline(snippets) |
|
|
if libtool: |
|
|
emit += 'LT_INIT([win32-dll])\n' |
|
|
emit += 'LT_LANG([C++])\n' |
|
|
emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' |
|
|
emit += 'gl_cond_libtool=true\n' |
|
|
else: |
|
|
emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' |
|
|
emit += 'gl_cond_libtool=false\n' |
|
|
emit += 'gl_libdeps=\n' |
|
|
emit += 'gl_ltlibdeps=\n' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit += 'AC_DEFUN([gl_INIT], [\n' |
|
|
if auxdir != 'build-aux': |
|
|
replace_auxdir = True |
|
|
else: |
|
|
replace_auxdir = False |
|
|
emit += 'gl_m4_base=\'%s\'\n' % m4base |
|
|
emit += self.emitter.initmacro_start(macro_prefix, False) |
|
|
emit += self.emitter.shellvars_init(False, sourcebase) |
|
|
if single_configure: |
|
|
emit += self.emitter.autoconfSnippets(main_modules, main_modules, moduletable, |
|
|
lambda module: True, |
|
|
True, False, False, replace_auxdir) |
|
|
else: |
|
|
emit += self.emitter.autoconfSnippets(modules, modules, moduletable, |
|
|
lambda module: module.isNonTests(), |
|
|
True, False, False, replace_auxdir) |
|
|
emit += self.emitter.initmacro_end(macro_prefix, False) |
|
|
if single_configure: |
|
|
emit += ' gltests_libdeps=\n' |
|
|
emit += ' gltests_ltlibdeps=\n' |
|
|
emit += self.emitter.initmacro_start('%stests' % macro_prefix, True) |
|
|
emit += self.emitter.shellvars_init(True, testsbase) |
|
|
|
|
|
emit += ' %stests_WITNESS=IN_GNULIB_TESTS\n' % macro_prefix |
|
|
emit += ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix |
|
|
emit += ' gl_module_indicator_condition=$%stests_WITNESS\n' % macro_prefix |
|
|
emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], ' |
|
|
emit += '[$gl_module_indicator_condition])\n' |
|
|
snippets = self.emitter.autoconfSnippets(tests_modules, main_modules + tests_modules, |
|
|
moduletable, lambda module: True, |
|
|
True, False, False, replace_auxdir) |
|
|
emit += snippets |
|
|
emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' |
|
|
emit += self.emitter.initmacro_end('%stests' % macro_prefix, True) |
|
|
|
|
|
|
|
|
if not libtool: |
|
|
libname_upper = libname.upper().replace('-', '_') |
|
|
emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper |
|
|
emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper |
|
|
emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper |
|
|
emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper |
|
|
if single_configure and libtests: |
|
|
emit += ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n' |
|
|
emit += ' AC_SUBST([LIBTESTS_LIBDEPS])\n' |
|
|
emit += '])\n' |
|
|
emit += self.emitter.initmacro_done(macro_prefix, sourcebase) |
|
|
if single_configure: |
|
|
emit += self.emitter.initmacro_done('%stests' % macro_prefix, testsbase) |
|
|
emit += '\ngl_INIT\n\n' |
|
|
if subdirs_with_configure_ac: |
|
|
emit += 'AC_CONFIG_SUBDIRS([%s])\n' % ' '.join(subdirs_with_configure_ac) |
|
|
makefiles = ['Makefile'] |
|
|
for directory in subdirs: |
|
|
|
|
|
|
|
|
if not directory in subdirs_with_configure_ac: |
|
|
makefiles.append(joinpath(directory, 'Makefile')) |
|
|
emit += 'AC_CONFIG_FILES([%s])\n' % ' '.join(makefiles) |
|
|
emit += 'AC_OUTPUT\n' |
|
|
path = joinpath(self.testdir, 'configure.ac') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
force_output() |
|
|
os.chdir(self.testdir) |
|
|
|
|
|
if os.path.isfile(joinpath(m4base, 'gettext.m4')): |
|
|
args = [UTILS['autopoint'], '--force'] |
|
|
execute(args, verbose) |
|
|
for src in os.listdir(m4base): |
|
|
src = joinpath(m4base, src) |
|
|
if src.endswith('.m4~'): |
|
|
dest = src[:-1] |
|
|
if os.path.isfile(dest): |
|
|
os.remove(dest) |
|
|
movefile(src, dest) |
|
|
|
|
|
if libtool: |
|
|
args = [UTILS['libtoolize'], '--copy'] |
|
|
execute(args, verbose) |
|
|
|
|
|
args = [UTILS['aclocal'], '-I', m4base] |
|
|
execute(args, verbose) |
|
|
if not os.path.isdir('build-aux'): |
|
|
print('executing mkdir build-aux') |
|
|
os.mkdir('build-aux') |
|
|
|
|
|
args = [UTILS['autoconf']] |
|
|
execute(args, verbose) |
|
|
|
|
|
args = [UTILS['autoheader']] |
|
|
execute(args, verbose) |
|
|
|
|
|
print('executing touch config.h.in') |
|
|
Path('config.h.in').touch() |
|
|
|
|
|
args = [UTILS['automake'], '--add-missing', '--copy'] |
|
|
execute(args, verbose) |
|
|
rmtree('autom4te.cache') |
|
|
os.chdir(DIRS['cwd']) |
|
|
if inctests and not single_configure: |
|
|
|
|
|
|
|
|
os.chdir(joinpath(self.testdir, testsbase)) |
|
|
|
|
|
if os.path.isfile(joinpath(m4base, 'gettext.m4')): |
|
|
args = [UTILS['autopoint'], '--force'] |
|
|
execute(args, verbose) |
|
|
for src in os.listdir(m4base): |
|
|
src = joinpath(m4base, src) |
|
|
if src.endswith('.m4~'): |
|
|
dest = src[:-1] |
|
|
if os.path.isfile(dest): |
|
|
os.remove(dest) |
|
|
movefile(src, dest) |
|
|
|
|
|
args = [UTILS['aclocal'], '-I', joinpath('..', m4base)] |
|
|
execute(args, verbose) |
|
|
if not os.path.isdir(joinpath('../build-aux')): |
|
|
print('executing mkdir ../build-aux') |
|
|
os.mkdir('../build-aux') |
|
|
|
|
|
args = [UTILS['autoconf']] |
|
|
execute(args, verbose) |
|
|
|
|
|
args = [UTILS['autoheader']] |
|
|
execute(args, verbose) |
|
|
|
|
|
print('executing touch config.h.in') |
|
|
Path('config.h.in').touch() |
|
|
|
|
|
args = [UTILS['automake'], '--add-missing', '--copy'] |
|
|
execute(args, verbose) |
|
|
rmtree('autom4te.cache') |
|
|
os.chdir(DIRS['cwd']) |
|
|
|
|
|
|
|
|
|
|
|
path = joinpath(self.testdir, sourcebase, 'Makefile.am') |
|
|
with open(path, mode='r', newline='\n', encoding='utf-8') as file: |
|
|
snippet = file.read() |
|
|
snippet = combine_lines(snippet) |
|
|
|
|
|
|
|
|
regex_find = [] |
|
|
pattern = re.compile(r'^CLEANFILES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
pattern = re.compile(r'^MOSTLYCLEANFILES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
regex_find = [ line.strip() |
|
|
for line in regex_find |
|
|
if line.strip() ] |
|
|
cleaned_files = [] |
|
|
for part in regex_find: |
|
|
cleaned_files += \ |
|
|
[ line.strip() |
|
|
for line in part.split(' ') |
|
|
if line.strip() ] |
|
|
|
|
|
|
|
|
|
|
|
regex_find = [] |
|
|
pattern = re.compile(r'^BUILT_SOURCES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
regex_find = [ line.strip() |
|
|
for line in regex_find |
|
|
if line.strip()] |
|
|
built_sources = [] |
|
|
for part in regex_find: |
|
|
built_sources += \ |
|
|
[ line.strip() |
|
|
for line in part.split(' ') |
|
|
if line.strip()] |
|
|
built_sources = [ line |
|
|
for line in built_sources |
|
|
if not bool(re.compile(r'[$]\([A-Za-z0-9_]*\)$').findall(line)) ] |
|
|
distributed_built_sources = [ file |
|
|
for file in built_sources |
|
|
if file not in cleaned_files ] |
|
|
|
|
|
tests_distributed_built_sources = [] |
|
|
if inctests: |
|
|
|
|
|
path = joinpath(self.testdir, testsbase, 'Makefile.am') |
|
|
with open(path, mode='r', newline='\n', encoding='utf-8') as file: |
|
|
snippet = file.read() |
|
|
snippet = combine_lines(snippet) |
|
|
|
|
|
|
|
|
regex_find = [] |
|
|
pattern = re.compile(r'^CLEANFILES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
pattern = re.compile(r'^MOSTLYCLEANFILES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
regex_find = [ line.strip() |
|
|
for line in regex_find |
|
|
if line.strip() ] |
|
|
tests_cleaned_files = [] |
|
|
for part in regex_find: |
|
|
tests_cleaned_files += \ |
|
|
[ line.strip() |
|
|
for line in part.split(' ') |
|
|
if line.strip() ] |
|
|
|
|
|
|
|
|
|
|
|
regex_find = [] |
|
|
pattern = re.compile(r'^BUILT_SOURCES[\t ]*\+=(.*)$', re.M) |
|
|
regex_find += pattern.findall(snippet) |
|
|
regex_find = [ line.strip() |
|
|
for line in regex_find |
|
|
if line.strip() ] |
|
|
tests_built_sources = [] |
|
|
for part in regex_find: |
|
|
tests_built_sources += \ |
|
|
[ line.strip() |
|
|
for line in part.split(' ') |
|
|
if line.strip() ] |
|
|
tests_built_sources = [ line |
|
|
for line in tests_built_sources |
|
|
if not bool(re.compile(r'[$]\([A-Za-z0-9_]*\)$').findall(line)) ] |
|
|
tests_distributed_built_sources = [ file |
|
|
for file in tests_built_sources |
|
|
if file not in tests_cleaned_files] |
|
|
|
|
|
os.chdir(self.testdir) |
|
|
if distributed_built_sources or tests_distributed_built_sources: |
|
|
force_output() |
|
|
sp.call('./configure') |
|
|
if distributed_built_sources: |
|
|
os.chdir(sourcebase) |
|
|
with open('Makefile', mode='a', newline='\n', encoding='utf-8') as file: |
|
|
file.write('built_sources: $(BUILT_SOURCES)\n') |
|
|
args = [UTILS['make'], |
|
|
'AUTOCONF=%s' % UTILS['autoconf'], |
|
|
'AUTOHEADER=%s' % UTILS['autoheader'], |
|
|
'ACLOCAL=%s' % UTILS['aclocal'], |
|
|
'AUTOMAKE=%s' % UTILS['automake'], |
|
|
'AUTORECONF=%s' % UTILS['autoreconf'], |
|
|
'built_sources'] |
|
|
sp.call(args) |
|
|
os.chdir('..') |
|
|
if tests_distributed_built_sources: |
|
|
os.chdir(testsbase) |
|
|
with open('Makefile', mode='a', newline='\n', encoding='utf-8') as file: |
|
|
file.write('built_sources: $(BUILT_SOURCES)\n') |
|
|
args = [UTILS['make'], |
|
|
'AUTOCONF=%s' % UTILS['autoconf'], |
|
|
'AUTOHEADER=%s' % UTILS['autoheader'], |
|
|
'ACLOCAL=%s' % UTILS['aclocal'], |
|
|
'AUTOMAKE=%s' % UTILS['automake'], |
|
|
'AUTORECONF=%s' % UTILS['autoreconf'], |
|
|
'built_sources'] |
|
|
sp.call(args) |
|
|
os.chdir('..') |
|
|
args = [UTILS['make'], |
|
|
'AUTOCONF=%s' % UTILS['autoconf'], |
|
|
'AUTOHEADER=%s' % UTILS['autoheader'], |
|
|
'ACLOCAL=%s' % UTILS['aclocal'], |
|
|
'AUTOMAKE=%s' % UTILS['automake'], |
|
|
'AUTORECONF=%s' % UTILS['autoreconf'], |
|
|
'AUTOPOINT=%s' % UTILS['autopoint'], |
|
|
'LIBTOOLIZE=%s' % UTILS['libtoolize'], |
|
|
'distclean'] |
|
|
sp.call(args) |
|
|
if os.path.isfile(joinpath('build-aux', 'test-driver')): |
|
|
_patch_test_driver() |
|
|
os.chdir(DIRS['cwd']) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GLMegaTestDir: |
|
|
'''GLMegaTestDir class is used to create a mega scratch package with the |
|
|
given modules one by one and all together.''' |
|
|
|
|
|
config: GLConfig |
|
|
megatestdir: str |
|
|
modulesystem: GLModuleSystem |
|
|
|
|
|
def __init__(self, config: GLConfig, megatestdir: str) -> None: |
|
|
'''Create new GLTestDir instance.''' |
|
|
if type(config) is not GLConfig: |
|
|
raise TypeError('config must be a GLConfig, not %s' |
|
|
% type(config).__name__) |
|
|
if type(megatestdir) is not str: |
|
|
raise TypeError('megatestdir must be a string, not %s' |
|
|
% type(megatestdir).__name__) |
|
|
self.config = config |
|
|
self.megatestdir = os.path.normpath(megatestdir) |
|
|
|
|
|
if os.path.exists(self.megatestdir): |
|
|
raise GLError(22, self.megatestdir) |
|
|
|
|
|
try: |
|
|
os.mkdir(self.megatestdir) |
|
|
except Exception as exc: |
|
|
raise GLError(19, self.megatestdir) from exc |
|
|
self.modulesystem = GLModuleSystem(self.config) |
|
|
|
|
|
def execute(self) -> None: |
|
|
'''Create a mega scratch package with the given modules one by one |
|
|
and all together.''' |
|
|
auxdir = self.config['auxdir'] |
|
|
verbose = self.config['verbosity'] |
|
|
|
|
|
megasubdirs = [] |
|
|
modules = [ self.modulesystem.find(m) |
|
|
for m in self.config['modules'] ] |
|
|
if not modules: |
|
|
modules = self.modulesystem.list() |
|
|
modules = [ self.modulesystem.find(m) |
|
|
for m in modules ] |
|
|
|
|
|
|
|
|
module_set = set(modules) |
|
|
modules = [ module |
|
|
for module in modules |
|
|
if module in module_set ] |
|
|
|
|
|
|
|
|
for module in modules: |
|
|
self.config.setModules([module.name]) |
|
|
GLTestDir(self.config, joinpath(self.megatestdir, module.name)).execute() |
|
|
megasubdirs.append(module.name) |
|
|
|
|
|
|
|
|
|
|
|
modules = [ module |
|
|
for module in modules |
|
|
if module.name != 'config-h' ] |
|
|
self.config.setModules([ module.name |
|
|
for module in modules ]) |
|
|
GLTestDir(self.config, joinpath(self.megatestdir, 'ALL')).execute() |
|
|
megasubdirs.append('ALL') |
|
|
|
|
|
|
|
|
emit = '' |
|
|
repdict = dict() |
|
|
repdict['Jan'] = repdict['January'] = '01' |
|
|
repdict['Feb'] = repdict['February'] = '02' |
|
|
repdict['Mar'] = repdict['March'] = '03' |
|
|
repdict['Apr'] = repdict['April'] = '04' |
|
|
repdict['May'] = repdict['May'] = '05' |
|
|
repdict['Jun'] = repdict['June'] = '06' |
|
|
repdict['Jul'] = repdict['July'] = '07' |
|
|
repdict['Aug'] = repdict['August'] = '08' |
|
|
repdict['Sep'] = repdict['September'] = '09' |
|
|
repdict['Oct'] = repdict['October'] = '10' |
|
|
repdict['Nov'] = repdict['November'] = '11' |
|
|
repdict['Dec'] = repdict['December'] = '12' |
|
|
vc_witness = joinpath(DIRS['root'], '.git', 'refs', 'heads', 'master') |
|
|
if not os.path.isfile(vc_witness): |
|
|
vc_witness = joinpath(DIRS['root'], 'ChangeLog') |
|
|
mdate_sh = joinpath(DIRS['root'], 'build-aux', 'mdate-sh') |
|
|
args = ['sh', mdate_sh, vc_witness] |
|
|
cvsdate = sp.check_output(args).decode('UTF-8').strip() |
|
|
for key in repdict: |
|
|
if len(key) > 3: |
|
|
cvsdate = cvsdate.replace(key, repdict[key]) |
|
|
for key in repdict: |
|
|
cvsdate = cvsdate.replace(key, repdict[key]) |
|
|
cvsdate = ''.join([ date |
|
|
for date in cvsdate.split(' ') |
|
|
if date.strip() ]) |
|
|
cvsdate = '%s%s%s' % (cvsdate[4:], cvsdate[2:4], cvsdate[:2]) |
|
|
emit += '#!/bin/sh\n' |
|
|
emit += 'CVSDATE=%s\n' % cvsdate |
|
|
emit += ': ${MAKE=make}\n' |
|
|
emit += 'test -d logs || mkdir logs\n' |
|
|
emit += 'for module in %s; do\n' % ' '.join(megasubdirs) |
|
|
emit += ' echo "Working on module $module..."\n' |
|
|
emit += ' safemodule=`echo $module | sed -e \'s|/|-|g\'`\n' |
|
|
emit += ' (echo "To: gnulib@autobuild.josefsson.org"\n' |
|
|
emit += ' echo\n' |
|
|
emit += ' set -x\n' |
|
|
emit += ' : autobuild project... $module\n' |
|
|
emit += ' : autobuild revision... cvs-$CVSDATE-000000\n' |
|
|
emit += ' : autobuild timestamp... `date "+%Y%m%d-%H%M%S"`\n' |
|
|
emit += ' : autobuild hostname... `hostname`\n' |
|
|
emit += ' cd $module && ./configure $CONFIGURE_OPTIONS && $MAKE' |
|
|
emit += ' && $MAKE check && $MAKE distclean\n' |
|
|
emit += ' echo rc=$?\n' |
|
|
emit += ' ) 2>&1 | { if test -n "$AUTOBUILD_SUBST"; then ' |
|
|
emit += 'sed -e "$AUTOBUILD_SUBST"; else cat; fi; } > logs/$safemodule\n' |
|
|
emit += 'done\n' |
|
|
path = joinpath(self.megatestdir, 'do-autobuild') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
emit = '## Process this file with automake to produce Makefile.in.\n\n' |
|
|
emit += 'AUTOMAKE_OPTIONS = 1.14 foreign\n\n' |
|
|
emit += 'SUBDIRS = %s\n\n' % ' '.join(megasubdirs) |
|
|
emit += 'EXTRA_DIST = do-autobuild\n' |
|
|
path = joinpath(self.megatestdir, 'Makefile.am') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
emit = '# Process this file with autoconf ' |
|
|
emit += 'to produce a configure script.\n' |
|
|
emit += 'AC_INIT([dummy], [0])\n' |
|
|
if auxdir != '.': |
|
|
emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir |
|
|
emit += 'AM_INIT_AUTOMAKE\n\n' |
|
|
emit += 'AC_PROG_MAKE_SET\n\n' |
|
|
emit += 'AC_CONFIG_SUBDIRS([%s])\n' % ' '.join(megasubdirs) |
|
|
emit += 'AC_CONFIG_FILES([Makefile])\n' |
|
|
emit += 'AC_OUTPUT\n' |
|
|
path = joinpath(self.megatestdir, 'configure.ac') |
|
|
with open(path, mode='w', newline='\n', encoding='utf-8') as file: |
|
|
file.write(emit) |
|
|
|
|
|
|
|
|
force_output() |
|
|
os.chdir(self.megatestdir) |
|
|
args = [UTILS['aclocal']] |
|
|
execute(args, verbose) |
|
|
try: |
|
|
if not os.path.isdir('build-aux'): |
|
|
print('executing mkdir build-aux') |
|
|
os.mkdir('build-aux') |
|
|
except Exception: |
|
|
pass |
|
|
args = [UTILS['autoconf']] |
|
|
execute(args, verbose) |
|
|
args = [UTILS['automake'], '--add-missing', '--copy'] |
|
|
execute(args, verbose) |
|
|
rmtree('autom4te.cache') |
|
|
if os.path.isfile(joinpath('build-aux', 'test-driver')): |
|
|
_patch_test_driver() |
|
|
os.chdir(DIRS['cwd']) |
|
|
|