diff options
author | lloyd <[email protected]> | 2009-07-02 14:59:45 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-07-02 14:59:45 +0000 |
commit | 3694fda953cb75482f2540f456d4a18f13e23550 (patch) | |
tree | 741a445206a0f362c90ae947f9fdee4d33dba762 /configure.py | |
parent | 6a6c9012864e0ba8d86dd5541a8d4e0c12feaf38 (diff) |
Much more of the makefile generation now working
Diffstat (limited to 'configure.py')
-rwxr-xr-x | configure.py | 380 |
1 files changed, 240 insertions, 140 deletions
diff --git a/configure.py b/configure.py index 25e180ad9..4c5cb3216 100755 --- a/configure.py +++ b/configure.py @@ -24,12 +24,20 @@ from getpass import getuser from time import ctime class BuildConfigurationInformation(): + + def __init__(self, options): + self.checkobj_dir = os.path.join(options.build_dir, 'checks') + self.libobj_dir = os.path.join(options.build_dir, 'lib') + + self.include_dir = os.path.join(options.build_dir, 'include') + self.full_include_dir = os.path.join(self.include_dir, 'botan') + def version_major(self): return 1 def version_minor(self): return 8 def version_patch(self): return 3 def version_string(self): - return "%d.%d.%d" % (self.version_major(), + return '%d.%d.%d' % (self.version_major(), self.version_minor(), self.version_patch()) @@ -45,49 +53,53 @@ class BuildConfigurationInformation(): def process_command_line(args): parser = OptionParser() - parser.add_option("--cc", dest="compiler", - help="set the desired build compiler") - parser.add_option("--os", dest="os", default=platform.system().lower(), - help="set the target operating system [%default]") - parser.add_option("--cpu", dest="cpu", - help="set the target processor type/model") + parser.add_option('--cc', dest='compiler', + help='set the desired build compiler') + parser.add_option('--os', dest='os', default=platform.system().lower(), + help='set the target operating system [%default]') + parser.add_option('--cpu', dest='cpu', + help='set the target processor type/model') - parser.add_option("--with-build-dir", dest="build_dir", - metavar="DIR", default="build", - help="setup the build in DIR [default %default]") + parser.add_option('--with-build-dir', dest='build_dir', + metavar='DIR', default='build', + help='setup the build in DIR [default %default]') - parser.add_option("--prefix", dest="prefix", - help="set the base installation directory") - parser.add_option("--docdir", dest="docdir", default="docdir", - help="set the documentation installation directory") + parser.add_option('--prefix', dest='prefix', + help='set the base installation directory') + parser.add_option('--docdir', dest='docdir', + help='set the documentation installation directory') + parser.add_option('--libdir', dest='libdir', + help='set the library installation directory') - parser.add_option("--with-local-config", dest="local_config", metavar="FILE", - help="include the contents of FILE into build.h") + parser.add_option('--with-local-config', dest='local_config', metavar='FILE', + help='include the contents of FILE into build.h') + """ + These exist only for autoconf compatability (requested by zw for monotone) + """ compat_with_autoconf_options = [ - "bindir", - "datadir", - "datarootdir", - "dvidir", - "exec-prefix", - "htmldir", - "includedir", - "infodir", - "libdir", - "libexecdir", - "localedir", - "localstatedir", - "mandir", - "oldincludedir", - "pdfdir", - "psdir", - "sbindir", - "sharedstatedir", - "sysconfdir" + 'bindir', + 'datadir', + 'datarootdir', + 'dvidir', + 'exec-prefix', + 'htmldir', + 'includedir', + 'infodir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'oldincludedir', + 'pdfdir', + 'psdir', + 'sbindir', + 'sharedstatedir', + 'sysconfdir' ] for opt in compat_with_autoconf_options: - parser.add_option("--" + opt, dest=opt, help=SUPPRESS_HELP) + parser.add_option('--' + opt, dest=opt, help=SUPPRESS_HELP) (options, args) = parser.parse_args(args) @@ -104,7 +116,7 @@ def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs): self.line = line def __str__(self): - return "%s at %s:%d" % (self.msg, infofile, self.line) + return '%s at %s:%d' % (self.msg, infofile, self.line) (dirname, basename) = os.path.split(infofile) @@ -116,7 +128,7 @@ def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs): lex = shlex.shlex(open(infofile), infofile, posix=True) - lex.wordchars += ':.<>/,-' + lex.wordchars += ':.<>/,-!' for group in allowed_groups: to_obj.__dict__[group] = [] @@ -137,7 +149,7 @@ def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs): group = match.group(1) if group not in allowed_groups: - raise LexerError("Unknown group '%s'" % (group), lex.lineno) + raise LexerError('Unknown group "%s"' % (group), lex.lineno) end_marker = '</' + group + '>' @@ -148,7 +160,7 @@ def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs): elif token in name_val_pairs.keys(): to_obj.__dict__[token] = lex.get_token() else: # No match -> error - raise LexerError("Bad token '%s'" % (token), lex.lineno) + raise LexerError('Bad token "%s"' % (token), lex.lineno) """ Convert a lex'ed map (from build-data files) from a list to a dict @@ -175,9 +187,13 @@ class ModuleInfo(object): # Coerce to more useful types self.mp_bits = int(self.mp_bits) self.uses_tr1 == bool(self.uses_tr1) + self.libs = force_to_dict(self.libs) self.add = map(lambda f: os.path.join(self.lives_in, f), self.add) + def libs_needed(self): + print self.libs + def __cmp__(self, other): if self.basename < other.basename: return -1 @@ -197,16 +213,21 @@ class ArchInfo(object): self.submodel_aliases = force_to_dict(self.submodel_aliases) + if self.unaligned == 'ok': + self.unaligned_ok = 1 + else: + self.unaligned_ok = 0 + def defines(self, target_submodel): - macros = ["TARGET_ARCH_IS_%s" % (self.basename.upper())] + macros = ['TARGET_ARCH_IS_%s' % (self.basename.upper())] if self.basename != target_submodel: - macros.append("TARGET_CPU_IS_%s" % (target_submodel.upper())) + macros.append('TARGET_CPU_IS_%s' % (target_submodel.upper())) if self.endian != None: - macros.append("TARGET_CPU_IS_%s_ENDIAN" % (self.endian.upper())) + macros.append('TARGET_CPU_IS_%s_ENDIAN' % (self.endian.upper())) - macros.append("TARGET_UNALIGNED_LOADSTORE_OK %d" % (self.unaligned == "ok")) + macros.append('TARGET_UNALIGNED_LOADSTORE_OK %d' % (self.unaligned_ok)) return macros @@ -241,12 +262,17 @@ class CompilerInfo(object): # FIXME: this has weirdness to handle s// ing out bits self.mach_opt = force_to_dict(self.mach_opt) + def so_link_command_for(self, osname): + if osname in self.so_link_flags: + return self.so_link_flags[osname] + return self.so_link_flags['default'] + def defines(self): if self.compiler_has_tr1: - return ["USE_STD_TR1"] + return ['USE_STD_TR1'] return [] -class OperatingSystemInfo(object): +class OsInfo(object): def __init__(self, infofile): lex_me_harder(infofile, self, ['aliases', 'target_features', 'supports_shared'], @@ -265,9 +291,17 @@ class OperatingSystemInfo(object): 'install_cmd_exec': 'install -m 755' }) + self.ar_needs_ranlib = bool(self.ar_needs_ranlib) + + def ranlib_command(self): + if self.ar_needs_ranlib == True: + return 'ranlib' + else: + return 'true' # no-op + def defines(self): - return ["TARGET_OS_IS_%s" % (self.basename.upper())] + \ - ["TARGET_OS_HAS_" + feat.upper() for feat in self.target_features] + return ['TARGET_OS_IS_%s' % (self.basename.upper())] + \ + ['TARGET_OS_HAS_' + feat.upper() for feat in self.target_features] def guess_processor(archinfo): base_proc = platform.machine() @@ -292,87 +326,147 @@ def guess_processor(archinfo): # No matches, so just use the base proc type return (base_proc,base_proc) -def process_template(template, variables): +def process_template(template_file, variables): class PercentSignTemplate(Template): delimiter = '%' try: - template = PercentSignTemplate(''.join(open(template).readlines())) + template = PercentSignTemplate(''.join(open(template_file).readlines())) return template.substitute(variables) except KeyError, e: - raise Exception("Unbound variable %s in template %s" % (e, template)) + raise Exception('Unbound variable %s in template %s' % (e, template_file)) -def create_template_vars(options, modules, cc, arch, osinfo): - vars = {} +def create_template_vars(build_config, options, modules, cc, arch, osinfo): + def make_cpp_macros(macros): + return '\n'.join(['#define BOTAN_' + macro for macro in macros]) - def create_macro_tokens(macros): - return "\n".join(["#define BOTAN_" + macro for macro in macros]) + """ + Figure out what external libraries are needed based on selected modules + """ + def link_against(): + for module in modules: + for (osname,link_to) in module.libs.iteritems(): + if osname == 'all' or osname == osinfo.basename: + yield link_to + else: + match = re.match('^all!(.*)', osname) + if match is not None: + exceptions = match.group(1).split(',') + if osinfo.basename not in exceptions: + yield link_to + + + def slurp_file(filename): + if filename is None: + return '' + return ''.join(open(filename).readlines()) - build_config = BuildConfigurationInformation() - vars['version_major'] = build_config.version_major() - vars['version_minor'] = build_config.version_minor() - vars['version_patch'] = build_config.version_patch() + def objectfile_list(sources, obj_dir): + for src in sources: + basename = os.path.basename(src) - vars['version'] = build_config.version_string() + for src_suffix in ['.cpp', '.S']: + basename = basename.replace(src_suffix, '.' + osinfo.obj_suffix) + yield os.path.join(obj_dir, basename) - vars['timestamp'] = build_config.timestamp() - vars['user'] = build_config.username() - vars['hostname'] = build_config.hostname() - vars['command_line'] = ' '.join(sys.argv) + def build_commands(sources, obj_dir, flags): + for (obj_file,src) in zip(objectfile_list(sources, obj_dir), sources): + yield "%s: %s\n\t$(CXX) %s%s $(%s_FLAGS) %s$? %s$@\n" % ( + obj_file, src, + cc.add_include_dir_option, + build_config.include_dir, + flags, + cc.compile_option, + cc.output_to_option) - vars['module_defines'] = create_macro_tokens(["HAS_" + m.define - for m in modules if m.define]) + def makefile_list(items): + return (' '*16).join([item + ' \\\n' for item in items]) - vars['target_os_defines'] = create_macro_tokens(osinfo.defines()) - vars['target_cpu_defines'] = create_macro_tokens(arch.defines(options.cpu)) - vars['target_compiler_defines'] = create_macro_tokens(cc.defines()) + vars = { + 'version_major': build_config.version_major(), + 'version_minor': build_config.version_minor(), + 'version_patch': build_config.version_patch(), + 'version': build_config.version_string(), - vars['local_config'] = "" - if options.local_config != None: - vars['local_config'] = ''.join(open(options.local_config).readlines()) + 'timestamp': build_config.timestamp(), + 'user': build_config.username(), + 'hostname': build_config.hostname(), + 'command_line': ' '.join(sys.argv), + 'local_config': slurp_file(options.local_config), - vars['cc'] = cc.binary_name - vars['lib_opt'] = cc.lib_opt_flags - vars['check_opt'] = cc.check_opt_flags - vars['mach_opt'] = '' - vars['lang_flags'] = cc.lang_flags - vars['warn_flags'] = cc.warning_flags - vars['shared_flags'] = cc.shared_flags - vars['so_link'] = 'so link command' - vars['so_version'] = 'SO VERSION' - vars['so_suffix'] = 'SO' - vars['dll_export_flags'] = cc.dll_export_flags - vars['mp_bits'] = 666 + 'prefix': options.prefix or osinfo.install_root, + 'libdir': options.libdir or osinfo.lib_dir, + 'includedir': options.includedir or osinfo.header_dir, + 'docdir': options.docdir or osinfo.doc_dir, + + 'doc_src_dir': 'doc', + 'build_dir': options.build_dir, + + 'os': options.os, + 'arch': options.arch, + 'submodel': options.cpu, - vars['submodel'] = options.cpu - vars['arch'] = options.arch - vars['os'] = options.os + 'cc': cc.binary_name, + 'lib_opt': cc.lib_opt_flags, + 'check_opt': cc.check_opt_flags, + 'lang_flags': cc.lang_flags, + 'warn_flags': cc.warning_flags, + 'shared_flags': cc.shared_flags, + 'dll_export_flags': cc.dll_export_flags, - vars['mod_list'] = "\n".join(["%s (%s)" % (m.basename, m.realname) - for m in sorted(modules)]) + 'so_link': cc.so_link_command_for(osinfo.basename), - vars['link_to'] = '' + 'link_to': ' '.join([cc.add_lib_option + lib + for lib in sorted(link_against())]), - vars['ar_command'] = cc.ar_command + 'module_defines': make_cpp_macros(['HAS_' + m.define + for m in modules if m.define]), + + 'target_os_defines': make_cpp_macros(osinfo.defines()), + 'target_cpu_defines': make_cpp_macros(arch.defines(options.cpu)), + 'target_compiler_defines': make_cpp_macros(cc.defines()), + + 'include_files': makefile_list(build_config.headers), + + 'lib_objs': makefile_list(objectfile_list(build_config.sources, + build_config.libobj_dir)), + + 'check_objs': makefile_list(objectfile_list(build_config.check_sources, + build_config.checkobj_dir)), + + 'lib_build_cmds': '\n'.join(build_commands(build_config.sources, + build_config.libobj_dir, 'LIB')), + + 'check_build_cmds': '\n'.join(build_commands(build_config.check_sources, + build_config.checkobj_dir, 'CHECK')), + + 'ar_command': cc.ar_command, + 'ranlib_command': osinfo.ranlib_command(), + 'install_cmd_exec': osinfo.install_cmd_exec, + 'install_cmd_data': osinfo.install_cmd_data, + + 'static_suffix': osinfo.static_suffix, + 'so_suffix': osinfo.so_suffix, + + 'botan_config': 'botan-config', + 'botan_pkgconfig': 'botan.pc', + + 'mod_list': '\n'.join(['%s (%s)' % (m.basename, m.realname) + for m in sorted(modules)]), + } + + + vars['mach_opt'] = '*MACH_OPT*' + + vars['mp_bits'] = 666 - vars['install_cmd_exec'] = 'install exec' - vars['install_cmd_data'] = 'install data' - vars['ranlib_command'] = 'randlib command' vars['check_prefix'] = 'check prefix' - vars['doc_files'] = 'list of doc files' - vars['doc_src_dir'] = 'doc' - vars['include_files'] = 'list of include files' - vars['lib_objs'] = 'list of obj files' - vars['check_objs'] = 'list of check objs' vars['lib_prefix'] = 'lib prefix' - vars['lib_build_cmds'] = 'lib build commands' - vars['check_build_cmds'] = 'check build commands' - vars['static_suffix'] = 'a' + vars['so_version'] = '*SO VERSION*' - vars['botan_config'] = 'botan-config' - vars['botan_pkgconfig'] = 'botan.pc' + vars['doc_files'] = 'list of doc files' return vars @@ -393,53 +487,50 @@ def choose_modules_to_use(options, modules): chosen.append(module) return chosen -def setup_build_tree(options, headers, sources): +def setup_build_tree(build_config, options, headers, sources): shutil.rmtree(options.build_dir) - include_dir = os.path.join(options.build_dir, 'include', 'botan') - checks_dir = os.path.join(options.build_dir, 'checks') - libobj_dir = os.path.join(options.build_dir, 'lib') - - os.makedirs(include_dir) - os.makedirs(checks_dir) - os.makedirs(libobj_dir) + #os.makedirs(include_dir) + #os.makedirs(checks_dir) + #os.makedirs(libobj_dir) for header_file in headers: shutil.copy(header_file, include_dir) -def main(argv = None): - if argv is None: - argv = sys.argv - - (options, args) = process_command_line(argv[1:]) +def load_info_files(options): - if args != []: - raise Exception("Unhandled option(s) " + ' '.join(args)) - - """ - Walk through a directory and find all files named desired_name - """ def find_files_named(desired_name, in_path): for (dirpath, dirnames, filenames) in os.walk(in_path): if desired_name in filenames: yield os.path.join(dirpath, desired_name) - def list_files_in(in_path): - for (dirpath, dirnames, filenames) in os.walk(in_path): + modules = [ModuleInfo(info) + for info in find_files_named('info.txt', 'src')] + + def list_files_in_build_data(subdir): + for (dirpath, dirnames, filenames) in \ + os.walk(os.path.join(options.build_data, subdir)): for filename in filenames: yield os.path.join(dirpath, filename) - modules = [ModuleInfo(info) - for info in find_files_named('info.txt', 'src')] + archinfo = [ArchInfo(info) for info in list_files_in_build_data('arch')] + ccinfo = [CompilerInfo(info) for info in list_files_in_build_data('cc')] + osinfo = [OsInfo(info) for info in list_files_in_build_data('os')] + + return (modules, archinfo, ccinfo, osinfo) + +def main(argv = None): + if argv is None: + argv = sys.argv + + (options, args) = process_command_line(argv[1:]) + if args != []: + raise Exception('Unhandled option(s) ' + ' '.join(args)) - build_data = os.path.join('src', 'build-data') + build_config = BuildConfigurationInformation(options) + options.build_data = os.path.join('src', 'build-data') - archinfo = [ArchInfo(info) - for info in list_files_in(os.path.join(build_data, 'arch'))] - ccinfo = [CompilerInfo(info) - for info in list_files_in(os.path.join(build_data, 'cc'))] - osinfo = [OperatingSystemInfo(info) - for info in list_files_in(os.path.join(build_data, 'os'))] + (modules, archinfo, ccinfo, osinfo) = load_info_files(options) # FIXME: need full canonicalization to (arch,submodel) when --cpu is used if options.cpu is None: @@ -453,25 +544,34 @@ def main(argv = None): modules_to_use = choose_modules_to_use(options, modules) + all_files = sum([mod.add for mod in modules_to_use], []) + build_config.headers = sorted([file for file in all_files if file.endswith('.h')]) + build_config.sources = sorted(set(all_files) - set(build_config.headers)) + + build_config.check_sources = sorted( + [os.path.join('checks', file) for file in os.listdir('checks') if file.endswith('.cpp')]) + def find_it(what, infoset): for info in infoset: if info.basename == what: return info return None - template_vars = create_template_vars(options, modules_to_use, + template_vars = create_template_vars(build_config, options, + modules_to_use, find_it(options.compiler, ccinfo), find_it(options.arch, archinfo), find_it(options.os, osinfo)) - #headers = [file for file in all_files if file.endswith('.h')] - #sources = list(set(all_files) - set(headers)) - #setup_build_tree(options, headers, sources) + #setup_build_tree(build_config, options, headers, sources) + + options.makefile_dir = os.path.join(options.build_data, 'makefile') - print process_template(os.path.join(build_data, 'buildh.in'), template_vars) + #print process_template(os.path.join(options.build_data, 'buildh.in'), template_vars) + print process_template(os.path.join(options.makefile_dir, 'unix_shr.in'), template_vars) if __name__ == '__main__': try: sys.exit(main()) except Exception, e: - print >>sys.stderr, "Exception:", e + print >>sys.stderr, 'Exception:', e |