4 #===============================================================================
5 # Define global imports
6 #===============================================================================
14 import subprocess
as sp
15 from . import constants
16 from .GLError
import GLError
17 from .GLConfig
import GLConfig
18 from .GLModuleSystem
import GLModule
19 from .GLModuleSystem
import GLModuleTable
20 from .GLModuleSystem
import GLModuleSystem
21 from .GLFileSystem
import GLFileSystem
22 from .GLFileSystem
import GLFileAssistant
23 from .GLMakefileTable
import GLMakefileTable
24 from .GLEmiter
import GLEmiter
27 #===============================================================================
28 # Define module information
29 #===============================================================================
30 __author__
= constants
.__author
__
31 __license__
= constants
.__license
__
32 __copyright__
= constants
.__copyright
__
35 #===============================================================================
36 # Define global constants
37 #===============================================================================
38 PYTHON3
= constants
.PYTHON3
43 UTILS
= constants
.UTILS
44 MODES
= constants
.MODES
45 TESTS
= constants
.TESTS
46 compiler
= constants
.compiler
47 joinpath
= constants
.joinpath
48 cleaner
= constants
.cleaner
49 relpath
= constants
.relativize
50 string
= constants
.string
53 isfile
= os
.path
.isfile
54 normpath
= os
.path
.normpath
57 #===============================================================================
58 # Define GLTestDir class
59 #===============================================================================
60 class GLTestDir(object):
61 '''GLTestDir class is used to create a scratch package with the given
62 list of the modules.'''
64 def __init__(self
, config
, testdir
):
65 '''GLTestDir.__init__(config, testdir) -> GLTestDir
67 Create new GLTestDir instance.'''
68 if type(config
) is not GLConfig
:
69 raise(TypeError('config must be a GLConfig, not %s' %
70 type(config
).__name
__))
71 if type(testdir
) is bytes
or type(testdir
) is string
:
72 if type(testdir
) is bytes
:
73 testdir
= testdir
.decode(ENCS
['default'])
75 self
.testdir
= os
.path
.normpath(testdir
)
76 if not os
.path
.exists(self
.testdir
):
77 try: # Try to create directory
78 os
.mkdir(self
.testdir
)
79 except Exception as error
:
80 raise(GLError(19, self
.testdir
))
81 self
.emiter
= GLEmiter(self
.config
)
82 self
.filesystem
= GLFileSystem(self
.config
)
83 self
.modulesystem
= GLModuleSystem(self
.config
)
84 self
.moduletable
= GLModuleTable(self
.config
)
85 self
.assistant
= GLFileAssistant(self
.config
)
86 self
.makefiletable
= GLMakefileTable(self
.config
)
89 self
.config
.setSourceBase('gllib')
90 self
.config
.setM4Base('glm4')
91 self
.config
.setDocBase('gldoc')
92 self
.config
.setTestsBase('gltests')
93 self
.config
.setMacroPrefix('gl')
94 self
.config
.resetPoBase()
95 self
.config
.resetPoDomain()
96 self
.config
.resetWitnessCMacro()
97 self
.config
.resetVCFiles()
99 def rewrite_files(self
, files
):
100 '''GLTestDir.rewrite_files(files)
102 Replace auxdir, docbase, sourcebase, m4base and testsbase from default
103 to their version from config.'''
104 if type(files
) is not list:
106 'files argument must has list type, not %s' % type(files
).__name
__))
108 [ # Begin to convert bytes to string
109 file.decode(ENCS
['default']) \
110 if type(file) is bytes
else file \
112 ] # Finish to convert bytes to string
114 if type(file) is not string
:
115 raise(TypeError('each file must be a string instance'))
116 files
= sorted(set(files
))
117 auxdir
= self
.config
['auxdir']
118 docbase
= self
.config
['docbase']
119 sourcebase
= self
.config
['sourcebase']
120 m4base
= self
.config
['m4base']
121 testsbase
= self
.config
['testsbase']
124 if file.startswith('build-aux/'):
125 path
= constants
.substart('build-aux/', '%s/' % auxdir
, file)
126 elif file.startswith('doc/'):
127 path
= constants
.substart('doc/', '%s/' % docbase
, file)
128 elif file.startswith('lib/'):
129 path
= constants
.substart('lib/', '%s/' % sourcebase
, file)
130 elif file.startswith('m4/'):
131 path
= constants
.substart('m4/', '%s/' % m4base
, file)
132 elif file.startswith('tests/'):
133 path
= constants
.substart('tests/', '%s/' % testsbase
, file)
134 elif file.startswith('tests=lib/'):
135 path
= constants
.substart(
136 'tests=lib/', '%s/' % testsbase
, file)
137 elif file.startswith('top/'):
138 path
= constants
.substart('top/', '', file)
139 else: # file is not a special file
141 result
+= [os
.path
.normpath(path
)]
142 result
= sorted(set(result
))
146 '''GLTestDir.execute()
148 Create a scratch package with the given modules.'''
149 localdir
= self
.config
['localdir']
150 auxdir
= self
.config
['auxdir']
151 testflags
= list(self
.config
['testflags'])
152 sourcebase
= self
.config
['sourcebase']
153 m4base
= self
.config
['m4base']
154 pobase
= self
.config
['pobase']
155 docbase
= self
.config
['docbase']
156 testsbase
= self
.config
['testsbase']
157 libname
= self
.config
['libname']
158 libtool
= self
.config
['libtool']
159 witness_c_macro
= self
.config
['witness_c_macro']
160 symbolic
= self
.config
['symbolic']
161 lsymbolic
= self
.config
['lsymbolic']
162 single_configure
= self
.config
['single_configure']
163 include_guard_prefix
= self
.config
['include_guard_prefix']
164 macro_prefix
= self
.config
['macro_prefix']
165 verbose
= self
.config
['verbosity']
167 base_modules
= [self
.modulesystem
.find(
168 m
) for m
in self
.config
['modules']]
170 base_modules
= self
.modulesystem
.list()
171 base_modules
= [self
.modulesystem
.find(m
) for m
in base_modules
]
172 # All modules together.
173 # Except config-h, which breaks all modules which use HAVE_CONFIG_H.
174 # Except ftruncate, mountlist, which abort the configuration on mingw.
175 # Except lib-ignore, which leads to link errors when Sun C++ is used.
176 base_modules
= sorted(set(base_modules
))
177 base_modules
= [module
for module
in base_modules
if str(module
) not in
178 ['config-h', 'ftruncate', 'mountlist', 'lib-ignore']]
180 # When computing transitive closures, don't consider $module to depend on
181 # $module-tests. Need this because tests are implicitly GPL and may depend
182 # on GPL modules - therefore we don't want a warning in this case.
183 saved_testflags
= list(self
.config
['testflags'])
184 self
.config
.disableTestFlag(TESTS
['tests'])
185 for requested_module
in base_modules
:
186 requested_licence
= requested_module
.getLicense()
187 # Here we use self.moduletable.transitive_closure([module]), not just
188 # module.getDependencies, so that we also detect weird situations like
189 # an LGPL module which depends on a GPLed build tool module which depends
191 if requested_licence
!= 'GPL':
192 modules
= self
.moduletable
.transitive_closure(
194 for module
in modules
:
195 license
= module
.getLicense()
196 errormsg
= 'module %s depends on a module ' % requested_module
197 errormsg
+= 'with an incompatible license: %s\n' % module
198 if requested_licence
== 'GPLv2+':
199 if license
not in ['GPLv2+', 'LGPLv2+']:
200 sys
.stderr
.write(errormsg
)
201 elif requested_licence
in ['LGPL']:
202 if license
not in ['LGPL', 'LGPLv2+']:
203 sys
.stderr
.write(errormsg
)
204 elif requested_licence
in ['LGPLv2+']:
205 if license
not in ['LGPLv2+']:
206 sys
.stderr
.write(errormsg
)
207 self
.config
.setTestFlags(saved_testflags
)
209 # Determine final module list.
210 modules
= self
.moduletable
.transitive_closure(base_modules
)
211 final_modules
= list(modules
)
213 # Show final module list.
217 term
= os
.getenv('TERM')
221 print('Module list with included dependencies (indented):')
222 for module
in final_modules
:
223 if str(module
) in self
.config
.getModules():
224 print(' %s%s%s' % (bold_on
, module
, bold_off
))
225 else: # if str(module) not in self.config.getModules()
226 print(' %s' % module
)
228 # Generate lists of the modules.
230 # Determine main module list and tests-related module list separately.
231 main_modules
, tests_modules
= \
232 self
.moduletable
.transitive_closure_separately(
233 base_modules
, final_modules
)
234 # Print main_modules and tests_modules.
236 print('Main module list:')
237 for module
in main_modules
:
238 print(' %s' % str(module
))
239 print('Tests-related module list:')
240 for module
in tests_modules
:
241 print(' %s' % str(module
))
242 # Determine whether a $testsbase/libtests.a is needed.
244 for module
in tests_modules
:
245 files
= module
.getFiles()
247 if file.startswith('lib/'):
251 self
.config
.enableLibtests()
254 # Add dummy package if it is needed.
255 main_modules
= self
.moduletable
.add_dummy(main_modules
)
256 if 'dummy' in [str(module
) for module
in main_modules
]:
257 main_modules
= [m
for m
in main_modules
if str(m
) != 'dummy']
258 dummy
= self
.modulesystem
.find('dummy')
259 main_modules
= sorted(set(main_modules
)) + [dummy
]
260 if libtests
: # if we need to use libtests.a
261 tests_modules
= self
.moduletable
.add_dummy(tests_modules
)
262 if 'dummy' in [str(module
) for module
in tests_modules
]:
264 m
for m
in tests_modules
if str(m
) != 'dummy']
265 dummy
= self
.modulesystem
.find('dummy')
266 tests_modules
= sorted(set(tests_modules
)) + [dummy
]
267 else: # if not single_configure
268 modules
= self
.moduletable
.add_dummy(modules
)
269 if 'dummy' in [str(module
) for module
in modules
]:
270 modules
= [m
for m
in modules
if str(m
) != 'dummy']
271 dummy
= self
.modulesystem
.find('dummy')
272 modules
= sorted(set(modules
)) + [dummy
]
274 # Show banner notice of every module.
276 for module
in main_modules
:
277 notice
= module
.getNotice()
279 print('Notice from module %s:' % str(module
))
280 pattern
= compiler('^(.*?)$', re
.S | re
.M
)
281 notice
= pattern
.sub(' \\1', notice
)
283 else: # if not single_configure
284 for module
in modules
:
285 notice
= module
.getNotice()
287 print('Notice from module %s:' % str(module
))
288 pattern
= compiler('^(.*?)$', re
.S | re
.M
)
289 notice
= pattern
.sub(' \\1', notice
)
292 # Determine final file list.
294 main_filelist
, tests_filelist
= \
295 self
.moduletable
.filelist_separately(
296 main_modules
, tests_modules
)
297 filelist
= sorted(set(main_filelist
+ tests_filelist
))
298 else: # if not single_configure
299 filelist
= self
.moduletable
.filelist(modules
)
301 filelist
= sorted(set(filelist
))
303 # Print list of files.
306 for file in filelist
:
307 if file.startswith('tests=lib/'):
309 print(' lib/%s -> tests/%s' % (rest
, rest
))
313 # Add files for which the copy in gnulib is newer than the one that
314 # "automake --add-missing --copy" would provide.
315 filelist
+= ['build-aux/config.guess', 'build-aux/config.sub']
316 filelist
= sorted(set(filelist
))
318 # Create directories.
319 directories
= [os
.path
.dirname(file)
320 for file in self
.rewrite_files(filelist
)]
321 directories
= sorted(set(directories
))
323 # Copy files or make symbolic links.
326 dest
= self
.rewrite_files([src
])[-1]
327 filetable
+= [tuple([dest
, src
])]
328 for row
in filetable
:
331 destpath
= joinpath(self
.testdir
, dest
)
332 dirname
= os
.path
.dirname(destpath
)
333 if not isdir(dirname
):
335 if src
.startswith('tests=lib/'):
336 src
= constants
.substart('tests=lib/', 'lib/', src
)
337 lookedup
, flag
= self
.filesystem
.lookup(src
)
341 shutil
.copy(lookedup
, destpath
)
343 if symbolic
or (lsymbolic
and lookedup
== joinpath(localdir
, src
)):
344 constants
.link_relative(lookedup
, destpath
)
346 shutil
.copy(lookedup
, destpath
)
348 # Create $sourcebase/Makefile.am.
350 directory
= joinpath(self
.testdir
, sourcebase
)
351 if not isdir(directory
):
353 destfile
= joinpath(directory
, 'Makefile.am')
355 emit
, uses_subdirs
= self
.emiter
.lib_Makefile_am(destfile
, main_modules
,
356 self
.moduletable
, self
.makefiletable
, '', for_test
)
357 else: # if not single_configure
358 emit
, uses_subdirs
= self
.emiter
.lib_Makefile_am(destfile
, modules
,
359 self
.moduletable
, self
.makefiletable
, '', for_test
)
360 with codecs
.open(destfile
, 'wb', 'UTF-8') as file:
362 any_uses_subdirs
= uses_subdirs
364 # Create $m4base/Makefile.am.
365 directory
= joinpath(self
.testdir
, m4base
)
366 if not isdir(directory
):
368 destfile
= joinpath(directory
, 'Makefile.am')
370 emit
+= '## Process this file with automake to produce Makefile.in.\n\n'
371 emit
+= 'EXTRA_DIST =\n'
372 for file in filelist
:
373 if file.startswith('m4/'):
374 file = constants
.substart('m4/', '', file)
375 emit
+= 'EXTRA_DIST += %s\n' % file
376 emit
= constants
.nlconvert(emit
)
377 if type(emit
) is bytes
:
378 emit
= emit
.decode(ENCS
['default'])
379 with codecs
.open(destfile
, 'wb', 'UTF-8') as file:
382 subdirs
= [sourcebase
, m4base
]
383 subdirs_with_configure_ac
= list()
385 testsbase_appened
= False
386 inctests
= self
.config
.checkTestFlag(TESTS
['tests'])
388 directory
= joinpath(self
.testdir
, testsbase
)
389 if not isdir(directory
):
392 # Create $testsbase/Makefile.am.
393 destfile
= joinpath(directory
, 'Makefile.am')
394 print(repr(destfile
))
395 witness_macro
= '%stests_WITNESS' % macro_prefix
396 emit
, uses_subdirs
= self
.emiter
.tests_Makefile_am(destfile
,
397 tests_modules
, self
.makefiletable
, witness_macro
, for_test
)
398 with codecs
.open(destfile
, 'wb', 'UTF-8') as file:
400 else: # if not single_configure
401 # Create $testsbase/Makefile.am.
402 destfile
= joinpath(directory
, 'Makefile.am')
404 self
.config
.disableLibtests()
405 emit
, uses_subdirs
= self
.emiter
.tests_Makefile_am(destfile
,
406 modules
, self
.makefiletable
, '', for_test
)
407 with codecs
.open(destfile
, 'wb', 'UTF-8') as file:
409 # Viewed from the $testsbase subdirectory, $auxdir is different.
411 saved_auxdir
= self
.config
['auxdir']
412 testsbase
= '%s/' % os
.path
.normpath(testsbase
)
415 finish
= (len(testsbase
.split('/')) - 1)
416 while counter
< finish
:
419 auxdir
= os
.path
.normpath(joinpath(auxdir
, saved_auxdir
))
420 testsbase
= os
.path
.normpath(testsbase
)
421 self
.config
.setAuxDir(auxdir
)
422 # Create $testsbase/configure.ac.
423 emit
+= '# Process this file with autoconf '
424 emit
+= 'to produce a configure script.\n'
425 emit
+= 'AC_INIT([dummy], [0])\n'
426 emit
+= 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir
427 emit
+= 'AM_INIT_AUTOMAKE\n\n'
428 emit
+= 'AC_CONFIG_HEADERS([config.h])\n\n'
429 emit
+= 'AC_PROG_CC\n'
430 emit
+= 'AC_PROG_INSTALL\n'
431 emit
+= 'AC_PROG_MAKE_SET\n'
432 emit
+= 'gl_PROG_AR_RANLIB\n\n'
434 emit
+= 'AM_PROG_CC_C_O\n\n'
436 for module
in modules
:
437 if str(module
) in ['gnumakefile', 'maintainer-makefile']:
438 # These are meant to be used only in the top-level directory.
440 # if str(module) not in ['gnumakefile', 'maintainer-makefile']
442 snippet
= module
.getAutoconfSnippet_Early()
443 lines
= [line
for line
in snippet
.split(
444 '\n') if line
.strip()]
445 snippet
= '\n'.join(lines
)
447 'AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re
.S | re
.M
)
448 snippet
= pattern
.sub('\\1', snippet
)
449 snippet
= snippet
.strip()
450 snippets
+= [snippet
]
451 snippets
= [snippet
for snippet
in snippets
if snippet
.strip()]
452 emit
+= '%s\n' % '\n'.join(snippets
)
454 emit
+= 'LT_INIT([win32-dll])\n'
455 emit
+= 'LT_LANG([C++])\n'
456 emit
+= 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n'
457 emit
+= 'gl_cond_libtool=true\n'
458 else: # if not libtool
459 emit
+= 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n'
460 emit
+= 'gl_cond_libtool=false\n'
461 emit
+= 'gl_libdeps=\n'
462 emit
+= 'gl_ltlibdeps=\n'
463 # Wrap the set of autoconf snippets into an autoconf macro that is then
464 # invoked. This is needed because autoconf does not support AC_REQUIRE
466 # error: AC_REQUIRE(gt_CSHARPCOMP): cannot be used outside of an
468 # but we want the AC_REQUIRE to have its normal meaning (provide one
469 # expansion of the required macro before the current point, and only
470 # one expansion total).
471 emit
+= 'AC_DEFUN([gl_INIT], [\n'
472 replace_auxdir
= True
473 emit
+= "gl_m4_base='../%s'\n" % m4base
474 emit
+= self
.emiter
.initmacro_start(macro_prefix
)
475 # We don't have explicit ordering constraints between the various
476 # autoconf snippets. It's cleanest to put those of the library before
477 # those of the tests.
478 emit
+= "gl_source_base='../%s'\n" % sourcebase
479 emit
+= self
.emiter
.autoconfSnippets(modules
,
480 self
.moduletable
, self
.assistant
, 1, False, False, False,
482 emit
+= "gl_source_base='.'"
483 emit
+= self
.emiter
.autoconfSnippets(modules
,
484 self
.moduletable
, self
.assistant
, 2, False, False, False,
486 emit
+= self
.emiter
.initmacro_end(macro_prefix
)
487 # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
488 # created using libtool, because libtool already handles the
491 libname_upper
= libname
.upper().replace('-', '_')
492 emit
+= ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper
493 emit
+= ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper
494 emit
+= ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper
495 emit
+= ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper
497 # FIXME use $sourcebase or $testsbase?
498 emit
+= self
.emiter
.initmacro_done(macro_prefix
, sourcebase
)
499 emit
+= '\ngl_INIT\n\n'
500 # Usually $testsbase/config.h will be a superset of config.h. Verify
501 # this by "merging" config.h into $testsbase/config.h; look out for gcc
503 emit
+= 'AH_TOP([#include \"../config.h\"])\n\n'
504 emit
+= 'AC_CONFIG_FILES([Makefile])\n'
505 emit
+= 'AC_OUTPUT\n'
506 emit
= constants
.nlconvert(emit
)
507 if type(emit
) is bytes
:
508 emit
= emit
.decode(ENCS
['default'])
509 path
= joinpath(self
.testdir
, testsbase
, 'configure.ac')
510 with codecs
.open(path
, 'wb', 'UTF-8') as file:
513 # Restore changed variables.
514 self
.config
.setAuxDir(saved_auxdir
)
515 auxdir
= self
.config
['auxdir']
516 subdirs_with_configure_ac
+= [testsbase
]
518 subdirs
+= [testsbase
]
519 testsbase_appened
= True
521 # Create Makefile.am.
523 emit
+= '## Process this file with automake to produce Makefile.in.\n\n'
524 emit
+= 'AUTOMAKE_OPTIONS = 1.9.6 foreign\n\n'
525 emit
+= 'SUBDIRS = %s\n\n' % ' '.join(subdirs
)
526 emit
+= 'ACLOCAL_AMFLAGS = -I %s\n' % m4base
527 emit
= constants
.nlconvert(emit
)
528 if type(emit
) is bytes
:
529 emit
= emit
.decode(ENCS
['default'])
530 path
= joinpath(self
.testdir
, 'Makefile.am')
531 with codecs
.open(path
, 'wb', 'UTF-8') as file:
534 # Create configure.ac
536 emit
+= '# Process this file with autoconf '
537 emit
+= 'to produce a configure script.\n'
538 emit
+= 'AC_INIT([dummy], [0])\n'
540 emit
+= 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir
541 emit
+= 'AM_INIT_AUTOMAKE\n\n'
542 emit
+= 'AC_CONFIG_HEADERS([config.h])\n\n'
543 emit
+= 'AC_PROG_CC\n'
544 emit
+= 'AC_PROG_INSTALL\n'
545 emit
+= 'AC_PROG_MAKE_SET\n\n'
546 emit
+= '# For autobuild.\n'
547 emit
+= 'AC_CANONICAL_BUILD\n'
548 emit
+= 'AC_CANONICAL_HOST\n\n'
549 emit
+= 'm4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace\n'
550 emit
+= 'm4_pattern_allow([^gl_ES$])dnl a valid locale name\n'
551 emit
+= 'm4_pattern_allow([^gl_LIBOBJS$])dnl a variable\n'
552 emit
+= 'm4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable\n\n'
553 emit
+= 'gl_PROG_AR_RANLIB\n\n'
555 emit
+= 'AM_PROG_CC_C_O\n'
557 for module
in final_modules
:
560 else: # if not single_configure
561 solution
= module
.isNonTests()
563 snippet
= module
.getAutoconfSnippet_Early()
564 lines
= [line
for line
in snippet
.split('\n') if line
.strip()]
565 snippet
= '\n'.join(lines
)
567 'AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re
.S | re
.M
)
568 snippet
= pattern
.sub('\\1', snippet
)
569 snippet
= snippet
.strip()
570 snippets
+= [snippet
]
571 snippets
= [snippet
for snippet
in snippets
if snippet
.strip()]
572 emit
+= '%s\n' % '\n'.join(snippets
)
574 emit
+= 'LT_INIT([win32-dll])\n'
575 emit
+= 'LT_LANG([C++])\n'
576 emit
+= 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n'
577 emit
+= 'gl_cond_libtool=true\n'
578 else: # if not libtool
579 emit
+= 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n'
580 emit
+= 'gl_cond_libtool=false\n'
581 emit
+= 'gl_libdeps=\n'
582 emit
+= 'gl_ltlibdeps=\n'
583 # Wrap the set of autoconf snippets into an autoconf macro that is then
584 # invoked. This is needed because autoconf does not support AC_REQUIRE
586 # error: AC_REQUIRE(gt_CSHARPCOMP): cannot be used outside of an
588 # but we want the AC_REQUIRE to have its normal meaning (provide one
589 # expansion of the required macro before the current point, and only one
591 emit
+= 'AC_DEFUN([gl_INIT], [\n'
592 if auxdir
!= 'build-aux':
593 replace_auxdir
= True
594 else: # auxdir == 'build-aux'
595 replace_auxdir
= False
596 emit
+= 'gl_m4_base=\'%s\'\n' % m4base
597 emit
+= self
.emiter
.initmacro_start(macro_prefix
)
598 emit
+= 'gl_source_base=\'%s\'\n' % sourcebase
600 emit
+= self
.emiter
.autoconfSnippets(main_modules
, self
.moduletable
,
601 self
.assistant
, 0, False, False, False, replace_auxdir
)
602 else: # if not single_configure
603 emit
+= self
.emiter
.autoconfSnippets(modules
, self
.moduletable
,
604 self
.assistant
, 1, False, False, False, replace_auxdir
)
605 emit
+= self
.emiter
.initmacro_end(macro_prefix
)
607 emit
+= ' gltests_libdeps=\n'
608 emit
+= ' gltests_ltlibdeps=\n'
609 emit
+= self
.emiter
.initmacro_start('%stests' % macro_prefix
)
610 emit
+= ' gl_source_base=\'%s\'\n' % testsbase
611 # Define a tests witness macro.
612 emit
+= ' %stests_WITNESS=IN_GNULIB_TESTS\n' % macro_prefix
613 emit
+= ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix
614 emit
+= ' gl_module_indicator_condition=$%stests_WITNESS\n' % \
616 emit
+= ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], '
617 emit
+= '[$gl_module_indicator_condition])\n'
618 snippets
= self
.emiter
.autoconfSnippets(tests_modules
, self
.moduletable
,
619 self
.assistant
, 1, True, False, False, replace_auxdir
)
620 emit
+= snippets
.strip()
621 emit
+= ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
622 emit
+= self
.emiter
.initmacro_end('%stests' % macro_prefix
)
623 # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
624 # created using libtool, because libtool already handles the dependencies.
626 libname_upper
= libname
.upper().replace('-', '_')
627 emit
+= ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper
628 emit
+= ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper
629 emit
+= ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper
630 emit
+= ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper
631 if single_configure
and libtests
:
632 emit
+= ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n'
633 emit
+= ' AC_SUBST([LIBTESTS_LIBDEPS])\n'
635 emit
+= self
.emiter
.initmacro_done(macro_prefix
, sourcebase
)
637 emit
+= self
.emiter
.initmacro_done('%stests' %
638 macro_prefix
, testsbase
)
639 emit
+= '\ngl_INIT\n\n'
640 if subdirs_with_configure_ac
:
642 emit
+= 'AC_CONFIG_SUBDIRS([%s])\n' % \
643 ' '.join(subdirs_with_configure_ac
[:-1])
644 else: # if not single_configure
645 emit
+= 'AC_CONFIG_SUBDIRS([%s])\n' % \
646 ' '.join(subdirs_with_configure_ac
)
647 makefiles
= ['Makefile']
648 for directory
in subdirs
:
649 # For subdirs that have a configure.ac by their own, it's the subdir's
650 # configure.ac which creates the subdir's Makefile.am, not this one.
651 makefiles
+= [joinpath(directory
, 'Makefile')]
652 if not single_configure
:
653 makefiles
= makefiles
[:-1]
654 emit
+= 'AC_CONFIG_FILES([%s])\n' % ' '.join(makefiles
)
655 emit
+= 'AC_OUTPUT\n'
656 path
= joinpath(self
.testdir
, 'configure.ac')
657 with codecs
.open(path
, 'wb', 'UTF-8') as file:
660 # Create autogenerated files.
661 # Do not use "${AUTORECONF} --force --install", because it may invoke
662 # autopoint, which brings in older versions of some of our .m4 files.
663 os
.chdir(self
.testdir
)
665 if isfile(joinpath(m4base
, 'gettext.m4')):
666 args
= [UTILS
['autopoint'], '--force']
667 constants
.execute(args
, verbose
)
668 for src
in os
.listdir(m4base
):
669 src
= joinpath(m4base
, src
)
670 if src
.endswith('.m4~'):
674 shutil
.move(src
, dest
)
677 args
= [UTILS
['libtoolize'], '--copy']
678 constants
.execute(args
, verbose
)
680 args
= [UTILS
['aclocal'], '-I', m4base
]
681 constants
.execute(args
, verbose
)
682 if not isdir('build-aux'):
683 os
.mkdir('build-aux')
685 args
= [UTILS
['autoconf']]
686 constants
.execute(args
, verbose
)
688 args
= [UTILS
['autoheader']]
689 constants
.execute(args
, verbose
)
691 args
= [UTILS
['automake'], '--add-missing', '--copy']
692 constants
.execute(args
, verbose
)
693 os
.chdir(DIRS
['cwd'])
694 if inctests
and not single_configure
:
695 # Do not use "${AUTORECONF} --force --install", because it may invoke
696 # autopoint, which brings in older versions of some of our .m4 files.
697 os
.chdir(joinpath(self
.testdir
, testsbase
))
699 if isfile(joinpath(m4base
, 'gettext.m4')):
700 args
= [UTILS
['autopoint'], '--force']
701 constants
.execute(args
, verbose
)
702 for src
in os
.listdir(m4base
):
703 src
= joinpath(m4base
, src
)
704 if src
.endswith('.m4~'):
708 shutil
.move(src
, dest
)
710 args
= [UTILS
['aclocal'], '-I', joinpath('..', m4base
)]
711 constants
.execute(args
, verbose
)
712 if not isdir(joinpath('../build-aux')):
713 os
.mkdir('../build-aux')
715 args
= [UTILS
['autoconf']]
716 constants
.execute(args
, verbose
)
718 args
= [UTILS
['autoheader']]
719 constants
.execute(args
, verbose
)
721 args
= [UTILS
['automake'], '--add-missing', '--copy']
722 constants
.execute(args
, verbose
)
723 os
.chdir(DIRS
['cwd'])
725 # Need to run configure and make once, to create built files that are to be
726 # distributed (such as parse-datetime.c).
727 path
= joinpath(self
.testdir
, sourcebase
, 'Makefile.am')
728 with codecs
.open(path
, 'rb', 'UTF-8') as file:
729 snippet
= file.read()
730 snippet
= constants
.remove_backslash_newline(snippet
)
731 cleaned_files
= list()
732 tests_cleaned_files
= list()
733 built_sources
= list()
734 tests_built_sources
= list()
735 distributed_built_sources
= list()
736 tests_distributed_built_sources
= list()
738 # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...".
740 pattern
= compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
741 regex_find
+= pattern
.findall(snippet
)
742 pattern
= compiler('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
743 regex_find
+= pattern
.findall(snippet
)
744 regex_find
= [line
.strip() for line
in regex_find
if line
.strip()]
745 for part
in regex_find
:
747 [line
.strip() for line
in part
.split(' ') if line
.strip()]
749 # Extract the value of "BUILT_SOURCES += ...". Remove variable references
750 # such $(FOO_H) because they don't refer to distributed files.
752 pattern
= compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
753 regex_find
+= pattern
.findall(snippet
)
754 regex_find
= [line
.strip() for line
in regex_find
if line
.strip()]
755 for part
in regex_find
:
757 [line
.strip() for line
in part
.split(' ') if line
.strip()]
758 built_sources
= [line
for line
in built_sources
759 if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line
))]
760 distributed_built_sources
= [file for file in built_sources
761 if file not in cleaned_files
]
764 # Likewise for built files in the $testsbase directory.
765 path
= joinpath(self
.testdir
, testsbase
, 'Makefile.am')
766 with codecs
.open(path
, 'rb', 'UTF-8') as file:
767 snippet
= file.read()
768 snippet
= constants
.remove_backslash_newline(snippet
)
770 # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...".
772 pattern
= compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
773 regex_find
+= pattern
.findall(snippet
)
775 '^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
776 regex_find
+= pattern
.findall(snippet
)
777 regex_find
= [line
.strip() for line
in regex_find
if line
.strip()]
778 for part
in regex_find
:
779 tests_cleaned_files
+= \
780 [line
.strip() for line
in part
.split(' ') if line
.strip()]
782 # Extract the value of "BUILT_SOURCES += ...". Remove variable references
783 # such $(FOO_H) because they don't refer to distributed files.
785 tests_built_sources
= list()
786 pattern
= compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re
.S | re
.M
)
787 regex_find
+= pattern
.findall(snippet
)
788 regex_find
= [line
.strip() for line
in regex_find
if line
.strip()]
789 for part
in regex_find
:
790 tests_built_sources
+= \
791 [line
.strip() for line
in part
.split(' ') if line
.strip()]
792 tests_built_sources
= [line
for line
in tests_built_sources
793 if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line
))]
794 tests_distributed_built_sources
= [file for file in tests_built_sources
795 if file not in cleaned_files
]
797 if distributed_built_sources
or tests_distributed_built_sources
:
798 os
.chdir(self
.testdir
)
799 sp
.call('./configure')
800 if distributed_built_sources
:
802 with codecs
.open('Makefile', 'ab', 'UTF-8') as file:
803 file.write('built_sources: $(BUILT_SOURCES)\n')
804 args
= [UTILS
['make'],
805 'AUTOCONF=%s' % UTILS
['autoconf'],
806 'AUTOHEADER=%s' % UTILS
['autoheader'],
807 'ACLOCAL=%s' % UTILS
['aclocal'],
808 'AUTOMAKE=%s' % UTILS
['automake'],
809 'AUTORECONF=%s' % UTILS
['autoreconf'],
813 if tests_distributed_built_sources
:
815 with codecs
.open('Makefile', 'ab', 'UTF-8') as file:
816 file.write('built_sources: $(BUILT_SOURCES)\n')
817 args
= [UTILS
['make'],
818 'AUTOCONF=%s' % UTILS
['autoconf'],
819 'AUTOHEADER=%s' % UTILS
['autoheader'],
820 'ACLOCAL=%s' % UTILS
['aclocal'],
821 'AUTOMAKE=%s' % UTILS
['automake'],
822 'AUTORECONF=%s' % UTILS
['autoreconf'],
826 args
= [UTILS
['make'],
827 'AUTOCONF=%s' % UTILS
['autoconf'],
828 'AUTOHEADER=%s' % UTILS
['autoheader'],
829 'ACLOCAL=%s' % UTILS
['aclocal'],
830 'AUTOMAKE=%s' % UTILS
['automake'],
831 'AUTORECONF=%s' % UTILS
['autoreconf'],
832 'AUTOPOINT=%s' % UTILS
['autopoint'],
833 'LIBTOOLIZE=%s' % UTILS
['libtoolize'],
836 sp
.call(['rm', '-rf', self
.config
['tempdir']], shell
=False)
839 #===============================================================================
840 # Define GLMegaTestDir class
841 #===============================================================================
842 class GLMegaTestDir(object):
843 '''GLMegaTestDir class is used to create a mega scratch package with the
844 given modules one by one and all together.'''
846 def __init__(self
, config
, megatestdir
):
847 '''GLMegaTestDir.__init__(config, megatestdir) -> GLMegaTestDir
849 Create new GLTestDir instance.'''
850 if type(config
) is not GLConfig
:
851 raise(TypeError('config must be a GLConfig, not %s' %
852 type(config
).__name
__))
853 if type(megatestdir
) is bytes
or type(megatestdir
) is string
:
854 if type(megatestdir
) is bytes
:
855 megatestdir
= megatestdir
.decode(ENCS
['default'])
857 self
.megatestdir
= os
.path
.normpath(megatestdir
)
858 if not os
.path
.exists(self
.megatestdir
):
859 try: # Try to create directory
860 os
.mkdir(self
.megatestdir
)
861 except Exception as error
:
862 raise(GLError(19, self
.megatestdir
))
863 self
.emiter
= GLEmiter(self
.config
)
864 self
.filesystem
= GLFileSystem(self
.config
)
865 self
.modulesystem
= GLModuleSystem(self
.config
)
866 self
.moduletable
= GLModuleTable(self
.config
)
867 self
.assistant
= GLFileAssistant(self
.config
)
868 self
.makefiletable
= GLMakefileTable(self
.config
)
871 '''GLMegaTestDir.execute()
873 Create a mega scratch package with the given modules one by one and all
876 modules
= [self
.modulesystem
.find(m
) for m
in self
.config
['modules']]
878 modules
= self
.modulesystem
.list()
879 modules
= [self
.modulesystem
.find(m
) for m
in modules
]
880 modules
= sorted(set(modules
))
882 # First, all modules one by one.
883 for module
in modules
:
884 self
.config
.setModules([str(module
)])
885 #GLTestDir(self.config, self.megatestdir).execute()
886 megasubdirs
+= [str(module
)]
888 # Then, all modules all together.
889 # Except config-h, which breaks all modules which use HAVE_CONFIG_H.
890 modules
= [module
for module
in modules
if str(module
) != 'config-h']
891 self
.config
.setModules([str(module
) for module
in modules
])
892 #GLTestDir(self.config, self.megatestdir).execute()
893 megasubdirs
+= ['ALL']
898 repdict
['Jan'] = repdict
['January'] = '01'
899 repdict
['Feb'] = repdict
['February'] = '02'
900 repdict
['Mar'] = repdict
['March'] = '03'
901 repdict
['Apr'] = repdict
['April'] = '04'
902 repdict
['May'] = repdict
['May'] = '05'
903 repdict
['Jun'] = repdict
['June'] = '06'
904 repdict
['Jul'] = repdict
['July'] = '07'
905 repdict
['Aug'] = repdict
['August'] = '08'
906 repdict
['Sep'] = repdict
['September'] = '09'
907 repdict
['Oct'] = repdict
['October'] = '10'
908 repdict
['Nov'] = repdict
['November'] = '11'
909 repdict
['Dec'] = repdict
['December'] = '12'
910 vc_witness
= joinpath(DIRS
['root'], '.git', 'refs', 'heads', 'master')
911 mdate_sh
= joinpath(DIRS
['root'], 'build-aux', 'mdate-sh')
912 args
= ['sh', mdate_sh
, vc_witness
]
913 cvsdate
= sp
.check_output(args
).decode("UTF-8").strip()
916 cvsdate
= cvsdate
.replace(key
, repdict
[key
])
918 cvsdate
= cvsdate
.replace(key
, repdict
[key
])
920 [date
for date
in cvsdate
.split(' ') if date
.strip()])
921 cvsdate
= '%s%s%s' % (cvsdate
[4:], cvsdate
[2:4], cvsdate
[:2])
922 emit
+= '#!/bin/sh\n'
923 emit
+= 'CVSDATE=%s\n' % cvsdate
924 emit
+= ': ${MAKE=make}\n'
925 emit
+= 'test -d logs || mkdir logs\n'
926 emit
+= 'for module in %s; do\n' % ' '.join(megasubdirs
)
927 emit
+= ' echo "Working on module $module..."\n'
928 emit
+= ' safemodule=`echo $module | sed -e \'s|/|-|g\'`\n'
929 emit
+= ' (echo "To: gnulib@autobuild.josefsson.org"\\\n'
932 emit
+= ' : autobuild project... $module\n'
933 emit
+= ' : autobuild revision... cvs-$CVSDATE-000000\n'
934 emit
+= ' : autobuild timestamp... `date "+%Y%m%d-%H%M%S"`\n'
935 emit
+= ' : autobuild hostname... `hostname`\n'
936 emit
+= ' cd $module && ./configure $CONFIGURE_OPTIONS && $MAKE'
937 emit
+= ' && $MAKE check && $MAKE distclean\n'
938 emit
+= ' echo rc=$?\n'
939 emit
+= ' ) 2>&1 | { if test -n "$AUTOBUILD_SUBST"; then '
940 emit
+= 'sed -e "$AUTOBUILD_SUBST"; else cat; fi; } > logs/$safemodule\n'
942 emit
= constants
.nlconvert(emit
)
943 if type(emit
) is bytes
:
944 emit
= emit
.decode(ENCS
['default'])
945 path
= joinpath(self
.megatestdir
, 'do-autobuild')
946 with codecs
.open(path
, 'wb', 'UTF-8') as file:
949 # Create Makefile.am.
951 emit
+= '## Process this file with automake to produce Makefile.in.\n\n'
952 emit
+= 'AUTOMAKE_OPTIONS = 1.9.6 foreign\n\n'
953 emit
+= 'SUBDIRS = %s\n\n' % ' '.join(megasubdirs
)
954 emit
+= 'EXTRA_DIST = do-autobuild\n'
955 emit
= constants
.nlconvert(emit
)
956 if type(emit
) is bytes
:
957 emit
= emit
.decode(ENCS
['default'])
958 path
= joinpath(self
.megatestdir
, 'Makefile.am')
959 with codecs
.open(path
, 'wb', 'UTF-8') as file:
963 emit
+= '# Process this file with autoconf '
964 emit
+= 'to produce a configure script.\n'
965 emit
+= 'AC_INIT([dummy], [0])\n\n'
967 emit
+= 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir
968 emit
+= 'AM_INIT_AUTOMAKE\n\n'
969 emit
+= 'AC_PROG_MAKE_SET\n\n'
970 emit
+= 'AC_CONFIG_SUBDIRS([%s])\n' % ' '.megasubdirs
971 emit
+= 'AC_CONFIG_FILES([Makefile])\n'
972 emit
+= 'AC_OUTPUT\n'
973 emit
= constants
.nlconvert(emit
)
974 if type(emit
) is bytes
:
975 emit
= emit
.decode(ENCS
['default'])
976 path
= joinpath(self
.megatestdir
, 'Makefile.am')
977 with codecs
.open(path
, 'wb', 'UTF-8') as file:
980 # Create autogenerated files.
981 os
.chdir(DIRS
['cwd'])
982 args
= [UTILS
['aclocal']]
983 constants
.execute(args
, verbose
)
984 try: # Try to make a directory
985 if not isdir('build-aux'):
986 os
, mkdir('build-aux')
987 except Exception as error
:
989 args
= [UTILS
['autoconf']]
990 constants
.execute(args
, verbose
)
991 args
= [UTILS
['automake'], '--add-missing', '--copy']
992 constants
.execute(args
, verbose
)
993 sp
.call(['rm', '-rf', self
.config
['tempdir']], shell
=False)