#
# gen_make.py -- generate makefiles and dependencies
#
import os
import sys
import string
import gen_base
import generator.swig.header_wrappers
import generator.swig.checkout_swig_header
import generator.swig.external_runtime
import generator.util.executable
_exec = generator.util.executable
from gen_base import build_path_join, build_path_strip, build_path_splitfile, \
build_path_basename, build_path_dirname, build_path_retreat, unique
try:
True
except NameError:
True = 1
False = 0
class Generator(gen_base.GeneratorBase):
_extension_map = {
('exe', 'target'): '$(EXEEXT)',
('exe', 'object'): '.o',
('lib', 'target'): '.la',
('lib', 'object'): '.lo',
}
def __init__(self, fname, verfname, options=None):
gen_base.GeneratorBase.__init__(self, fname, verfname, options)
self.section_counter = 0
self.assume_shared_libs = False
if ('--assume-shared-libs', '') in options:
self.assume_shared_libs = True
def begin_section(self, description):
self.section_counter = self.section_counter + 1
count = self.section_counter
self.ofile.write('\n########################################\n')
self.ofile.write('# Section %d: %s\n' % (count, description))
self.ofile.write('########################################\n\n')
def write(self):
self.ofile = open('build-outputs.mk', 'w')
self.ofile.write('# DO NOT EDIT -- AUTOMATICALLY GENERATED\n')
install_deps = self.graph.get_deps(gen_base.DT_INSTALL)
install_sources = self.graph.get_all_sources(gen_base.DT_INSTALL)
# ensure consistency between runs
install_deps.sort()
install_sources.sort(lambda s1, s2: cmp(s1.name, s2.name))
########################################
self.begin_section('Global make variables')
for target in install_sources:
if isinstance(target, gen_base.TargetRaModule) or \
isinstance(target, gen_base.TargetFsModule):
# name of the module: strip 'libsvn_' and upper-case it
name = string.upper(target.name[7:])
# construct a list of the other .la libs to link against
retreat = build_path_retreat(target.path)
deps = [ target.filename ]
link = [ build_path_join(retreat, target.filename) ]
for source in self.graph.get_sources(gen_base.DT_LINK, target.name):
if not isinstance(source, gen_base.TargetLib) or source.external_lib:
continue
deps.append(source.filename)
link.append(build_path_join(retreat, source.filename))
self.ofile.write('%s_DEPS = %s\n'
'%s_LINK = %s\n\n' % (name, string.join(deps, ' '),
name, string.join(link, ' ')))
# write a list of directories in which things are built
# get all the test scripts' directories
script_dirs = map(build_path_dirname, self.scripts + self.bdb_scripts)
# remove duplicate directories between targets and tests
build_dirs = unique(self.target_dirs + script_dirs + self.swig_dirs)
self.ofile.write('BUILD_DIRS = %s\n\n' % string.join(build_dirs))
# write lists of test files
# deps = all, progs = not including those marked "testing = skip"
self.ofile.write('BDB_TEST_DEPS = %s\n\n' %
string.join(self.bdb_test_deps + self.bdb_scripts))
self.ofile.write('BDB_TEST_PROGRAMS = %s\n\n' %
string.join(self.bdb_test_progs + self.bdb_scripts))
self.ofile.write('TEST_DEPS = %s\n\n' %
string.join(self.test_deps + self.scripts))
self.ofile.write('TEST_PROGRAMS = %s\n\n' %
string.join(self.test_progs + self.scripts))
# write list of all manpages
self.ofile.write('MANPAGES = %s\n\n' % string.join(self.manpages))
# write a list of files to remove during "make clean"
cfiles = [ ]
for target in install_sources:
# .la files are handled by the standard 'clean' rule; clean all the
# other targets
if not isinstance(target, gen_base.TargetScript) \
and not isinstance(target, gen_base.TargetProject) \
and not isinstance(target, gen_base.TargetI18N) \
and not isinstance(target, gen_base.TargetJava) \
and not target.external_lib \
and target.filename[-3:] != '.la':
cfiles.append(target.filename)
cfiles.sort()
self.ofile.write('CLEAN_FILES = %s\n\n' % string.join(cfiles))
# this is here because autogen-standalone needs it too
self.ofile.write('SWIG_INCLUDES = -I$(abs_srcdir)/subversion/include \\\n'
' -I$(abs_srcdir)/subversion/bindings/swig \\\n'
' -I$(abs_srcdir)/subversion/bindings/swig/include \\\n'
' -I$(abs_srcdir)/subversion/bindings/swig/proxy \\\n'
' -I$(abs_builddir)/subversion/bindings/swig/proxy \\\n'
' $(SVN_APR_INCLUDES) $(SVN_APRUTIL_INCLUDES)\n\n')
if self.release_mode:
self.ofile.write('RELEASE_MODE = 1\n\n')
########################################
self.begin_section('SWIG headers (wrappers and external runtimes)')
if not self.release_mode:
for swig in (generator.swig.header_wrappers,
generator.swig.checkout_swig_header,
generator.swig.external_runtime):
gen = swig.Generator(self.conf, "swig")
gen.write_makefile_rules(self.ofile)
########################################
self.begin_section('SWIG autogen rules')
# write dependencies and build rules for generated .c files
swig_c_deps = self.graph.get_deps(gen_base.DT_SWIG_C)
swig_c_deps.sort(lambda (t1, s1), (t2, s2): cmp(t1.filename, t2.filename))
swig_lang_deps = {}
for lang in self.swig.langs:
swig_lang_deps[lang] = []
short = self.swig.short
for objname, sources in swig_c_deps:
lang = objname.lang
swig_lang_deps[lang].append(str(objname))
for lang in self.swig.langs:
lang_deps = string.join(swig_lang_deps[lang])
self.ofile.write(
'autogen-swig-%s: %s\n' % (short[lang], lang_deps) +
'autogen-swig: autogen-swig-%s\n' % short[lang] +
'\n')
self.ofile.write('\n')
########################################
self.begin_section('Rules to build SWIG .c files from .i files')
for objname, sources in swig_c_deps:
deps = string.join(map(str, sources))
source = str(sources[0])
source_dir = build_path_dirname(source)
opts = self.swig.opts[objname.lang]
if not self.release_mode:
self.ofile.write('%s: %s\n' % (objname, deps) +
'\t$(SWIG) $(SWIG_INCLUDES) %s ' % opts +
'-o $@ $(top_srcdir)/%s\n' % source
)
self.ofile.write('\n')
########################################
self.begin_section('Individual target build rules')
for target_ob in install_sources:
if isinstance(target_ob, gen_base.TargetScript):
# there is nothing to build
continue
target = target_ob.name
if isinstance(target_ob, gen_base.TargetJava):
path = target_ob.output_dir
else:
path = target_ob.path
retreat = build_path_retreat(path)
# get the source items (.o and .la) for the link unit
objects = [ ]
object_srcs = [ ]
headers = [ ]
header_classes = [ ]
header_class_filenames = [ ]
deps = [ ]
libs = [ ]
for link_dep in self.graph.get_sources(gen_base.DT_LINK, target_ob.name):
if isinstance(link_dep, gen_base.TargetJava):
deps.append(link_dep.name)
elif isinstance(link_dep, gen_base.TargetLinked):
if link_dep.external_lib:
libs.append(link_dep.external_lib)
elif link_dep.external_project:
# FIXME: This is a temporary workaround to fix build breakage
# expeditiously. It is of questionable validity for a build
# node to have external_project but not have external_lib.
pass
else:
# append the output of the target to our stated dependencies
if not self.assume_shared_libs:
deps.append(link_dep.filename)
# link against the library
libs.append(build_path_join(retreat, link_dep.filename))
elif isinstance(link_dep, gen_base.ObjectFile):
# link in the object file
objects.append(link_dep.filename)
for dep in self.graph.get_sources(gen_base.DT_OBJECT, link_dep, gen_base.SourceFile):
object_srcs.append(
build_path_join('$(abs_srcdir)', dep.filename))
elif isinstance(link_dep, gen_base.HeaderFile):
# link in the header file
# N.B. that filename_win contains the '_'-escaped class name
headers.append(link_dep.filename_win)
header_classes.append(link_dep.classname)
for dep in self.graph.get_sources(gen_base.DT_OBJECT, link_dep, gen_base.ObjectFile):
header_class_filenames.append(dep.filename)
else:
### we don't know what this is, so we don't know what to do with it
raise UnknownDependency
for nonlib in self.graph.get_sources(gen_base.DT_NONLIB, target_ob.name):
if isinstance(nonlib, gen_base.TargetLinked):
if not nonlib.external_lib:
deps.append(nonlib.filename)
targ_varname = string.replace(target, '-', '_')
objnames = string.join(build_path_strip(path, objects))
# Output value of path variable
self.ofile.write('%s_PATH = %s\n' % (targ_varname, path))
# Add additional install dependencies if necessary
if target_ob.add_install_deps:
self.ofile.write('install-%s: %s\n'
% (target_ob.install, target_ob.add_install_deps))
if isinstance(target_ob, gen_base.TargetJava):
self.ofile.write(
'%s_HEADERS = %s\n'
'%s_OBJECTS = %s\n'
'%s_DEPS = $(%s_HEADERS) $(%s_OBJECTS) %s %s\n'
'%s: $(%s_DEPS)\n'
% (targ_varname, string.join(headers),
targ_varname, string.join(objects),
targ_varname, targ_varname, targ_varname, target_ob.add_deps,
string.join(deps),
target_ob.name, targ_varname))
# Build the headers from the header_classes with one 'javah' call
if headers:
self.ofile.write(
'%s_CLASS_FILENAMES = %s\n'
'%s_CLASSES = %s\n'
'$(%s_HEADERS): $(%s_CLASS_FILENAMES)\n'
'\t%s -d %s -classpath %s:$(%s_CLASSPATH) $(%s_CLASSES)\n'
% (targ_varname, string.join(header_class_filenames),
targ_varname, string.join(header_classes),
targ_varname, targ_varname,
target_ob.link_cmd, target_ob.output_dir, target_ob.classes,
targ_varname, targ_varname))
# Build the objects from the object_srcs with one 'javac' call
if object_srcs:
self.ofile.write(
'%s_SRC = %s\n'
'$(%s_OBJECTS): $(%s_SRC)\n'
'\t%s -d %s -classpath %s:$(%s_CLASSPATH) $(%s_SRC)\n'
% (targ_varname, string.join(object_srcs),
targ_varname, targ_varname,
target_ob.link_cmd, target_ob.output_dir, target_ob.classes,
targ_varname, targ_varname))
# Once the bytecodes have been compiled up, we produce the
# JAR.
if target_ob.jar:
self.ofile.write('\n\t$(JAR) cf %s -C %s %s' %
(build_path_join(target_ob.classes, target_ob.jar),
target_ob.classes,
string.join(target_ob.packages, ' ')))
self.ofile.write('\n\n')
elif isinstance(target_ob, gen_base.TargetI18N):
self.ofile.write(
'%s_DEPS = %s %s\n'
'%s: $(%s_DEPS)\n\n'
% (targ_varname, target_ob.add_deps, string.join(objects + deps),
target_ob.name, targ_varname))
else:
self.ofile.write(
'%s_DEPS = %s %s\n'
'%s_OBJECTS = %s\n'
'%s: $(%s_DEPS)\n'
'\tcd %s && %s -o %s %s $(%s_OBJECTS) %s $(LIBS)\n\n'
% (targ_varname, target_ob.add_deps, string.join(objects + deps),
targ_varname, objnames,
target_ob.filename, targ_varname,
path, target_ob.link_cmd,
build_path_basename(target_ob.filename),
(isinstance(target_ob, gen_base.TargetLib) and not
target_ob.undefined_lib_symbols) and '$(LT_NO_UNDEFINED)' or "",
targ_varname, string.join(gen_base.unique(libs)))
)
########################################
self.begin_section('Install-Group build targets')
for itype, i_targets in install_deps:
# perl bindings do their own thing, "swig-pl" target is
# already specified in Makefile.in
if itype == "swig-pl":
continue
outputs = [ ]
for t in i_targets:
if hasattr(t, 'filename'):
outputs.append(t.filename)
self.ofile.write('%s: %s\n\n' % (itype, string.join(outputs)))
########################################
self.begin_section('Install-Group install targets')
# for each install group, write a rule to install its outputs
for area, inst_targets in install_deps:
# perl bindings do their own thing, "install-swig-pl" target is
# already specified in Makefile.in
if area == "swig-pl":
continue
# get the output files for these targets, sorted in dependency order
files = gen_base._sorted_files(self.graph, area)
if area == 'apache-mod':
self.ofile.write('install-mods-shared: %s\n' % (string.join(files),))
la_tweaked = { }
for file in files:
# cd to dirname before install to work around libtool 1.4.2 bug.
dirname, fname = build_path_splitfile(file)
base, ext = os.path.splitext(fname)
name = string.replace(base, 'mod_', '')
self.ofile.write('\tcd %s ; '
'$(MKDIR) "$(APACHE_LIBEXECDIR)" ; '
'$(INSTALL_MOD_SHARED) -n %s %s\n'
% (dirname, name, fname))
if ext == '.la':
la_tweaked[file + '-a'] = None
for apmod in inst_targets:
for source in self.graph.get_sources(gen_base.DT_LINK, apmod.name,
gen_base.Target):
if not source.external_lib:
bt = source.filename
if bt[-3:] == '.la':
la_tweaked[bt + '-a'] = None
la_tweaked = la_tweaked.keys()
la_tweaked.sort()
# Construct a .libs directory within the Apache area and populate it
# with the appropriate files. Also drop the .la file in the target dir.
self.ofile.write('\ninstall-mods-static: %s\n'
'\t$(MKDIR) $(DESTDIR)%s\n'
% (string.join(la_tweaked + self.apache_files),
build_path_join('$(APACHE_TARGET)', '.libs')))
for file in la_tweaked:
dirname, fname = build_path_splitfile(file)
base = os.path.splitext(fname)[0]
self.ofile.write('\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
'\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
% (build_path_join(dirname, '.libs', base + '.a'),
build_path_join('$(APACHE_TARGET)', '.libs',
base + '.a'),
file,
build_path_join('$(APACHE_TARGET)', base + '.la')))
# copy the other files to the target dir
for file in self.apache_files:
self.ofile.write('\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
% (file, build_path_join('$(APACHE_TARGET)',
build_path_basename(file))))
self.ofile.write('\n')
elif area != 'test' and area != 'bdb-test':
area_var = string.replace(area, '-', '_')
upper_var = string.upper(area_var)
self.ofile.write('install-%s: %s\n'
'\t$(MKDIR) $(DESTDIR)$(%sdir)\n'
% (area, string.join(files), area_var))
for file in files:
# cd to dirname before install to work around libtool 1.4.2 bug.
dirname, fname = build_path_splitfile(file)
if area == 'locale':
lang, objext = os.path.splitext(fname)
installdir = '$(DESTDIR)$(%sdir)/%s/LC_MESSAGES' % (area_var, lang)
self.ofile.write('\t$(MKDIR) %s\n'
'\tcd %s ; $(INSTALL_%s) %s '
'%s/$(PACKAGE_NAME)%s\n'
% (installdir,
dirname, upper_var, fname,
installdir, objext))
else:
self.ofile.write('\tcd %s ; $(INSTALL_%s) %s $(DESTDIR)%s\n'
% (dirname, upper_var, fname,
build_path_join('$(%sdir)' % area_var, fname)))
# certain areas require hooks for extra install rules defined
# in Makefile.in
### we should turn AREA into an object, then test it instead of this
if area[:5] == 'swig-' and area[-4:] != '-lib' or \
area[:7] == 'javahl-':
self.ofile.write('\t$(INSTALL_EXTRA_%s)\n' % upper_var)
self.ofile.write('\n')
########################################
self.begin_section('The install-include rule')
includedir = build_path_join('$(includedir)',
'subversion-%s' % self.version)
self.ofile.write('install-include: %s\n'
'\t$(MKDIR) $(DESTDIR)%s\n'
% (string.join(self.includes), includedir))
for file in self.includes:
self.ofile.write('\t$(INSTALL_INCLUDE) %s $(DESTDIR)%s\n'
% (build_path_join('$(abs_srcdir)', file),
build_path_join(includedir,
build_path_basename(file))))
########################################
self.begin_section('Shortcut targets for manual builds of specific items')
for target in install_sources:
if not isinstance(target, gen_base.TargetScript) and \
not isinstance(target, gen_base.TargetJava) and \
not isinstance(target, gen_base.TargetI18N):
self.ofile.write('%s: %s\n' % (target.name, target.filename))
########################################
self.begin_section('Rules to build all other kinds of object-like files')
# write dependencies and build rules (when not using suffix rules)
# for all other generated files which will not be installed
# (or will be installed, but not by the main generated build)
obj_deps = self.graph.get_deps(gen_base.DT_OBJECT)
obj_deps.sort(lambda (t1, s1), (t2, s2): cmp(t1.filename, t2.filename))
for objname, sources in obj_deps:
deps = string.join(map(str, sources))
self.ofile.write('%s: %s\n' % (objname, deps))
cmd = objname.compile_cmd
if cmd:
if not getattr(objname, 'source_generated', 0):
self.ofile.write('\t%s %s\n\n'
% (cmd, build_path_join('$(abs_srcdir)',
str(sources[0]))))
else:
self.ofile.write('\t%s %s\n\n' % (cmd, sources[0]))
else:
self.ofile.write('\n')
self.ofile.close()
self.write_standalone()
def write_standalone(self):
"""Write autogen-standalone.mk"""
standalone = open("autogen-standalone.mk", "w")
standalone.write('# DO NOT EDIT -- AUTOMATICALLY GENERATED\n')
standalone.write('abs_srcdir = %s\n' % os.getcwd())
standalone.write('abs_builddir = %s\n' % os.getcwd())
standalone.write('top_srcdir = .\n')
standalone.write('top_builddir = .\n')
standalone.write('SWIG = swig\n')
standalone.write('PYTHON = python\n')
standalone.write('\n')
standalone.write(open("build-outputs.mk","r").read())
standalone.close()
class UnknownDependency(Exception):
"We don't know how to deal with the dependent to link it in."
pass
### End of file.
syntax highlighted by Code2HTML, v. 0.9.1