2 # gen_make.py -- generate makefiles and dependencies
11 import generator
.swig
.header_wrappers
12 import generator
.swig
.checkout_swig_header
13 import generator
.swig
.external_runtime
14 import generator
.util
.executable
15 _exec
= generator
.util
.executable
17 from gen_base
import build_path_join
, build_path_strip
, build_path_splitfile
, \
18 build_path_basename
, build_path_dirname
, build_path_retreat
, unique
26 class Generator(gen_base
.GeneratorBase
):
29 ('exe', 'target'): '$(EXEEXT)',
30 ('exe', 'object'): '.o',
31 ('lib', 'target'): '.la',
32 ('lib', 'object'): '.lo',
35 def __init__(self
, fname
, verfname
, options
=None):
36 gen_base
.GeneratorBase
.__init
__(self
, fname
, verfname
, options
)
37 self
.section_counter
= 0
38 self
.assume_shared_libs
= False
39 if ('--assume-shared-libs', '') in options
:
40 self
.assume_shared_libs
= True
42 def begin_section(self
, description
):
43 self
.section_counter
= self
.section_counter
+ 1
44 count
= self
.section_counter
46 self
.ofile
.write('\n########################################\n')
47 self
.ofile
.write('# Section %d: %s\n' % (count
, description
))
48 self
.ofile
.write('########################################\n\n')
51 self
.ofile
= open('build-outputs.mk', 'w')
52 self
.ofile
.write('# DO NOT EDIT -- AUTOMATICALLY GENERATED\n')
54 install_deps
= self
.graph
.get_deps(gen_base
.DT_INSTALL
)
55 install_sources
= self
.graph
.get_all_sources(gen_base
.DT_INSTALL
)
57 cp
= ConfigParser
.ConfigParser()
58 cp
.read('gen-make.opts')
59 if cp
.has_option('options', '--installed-libs'):
60 self
.installed_libs
= cp
.get('options', '--installed-libs').split(',')
62 self
.installed_libs
= []
64 # ensure consistency between runs
66 install_sources
.sort(lambda s1
, s2
: cmp(s1
.name
, s2
.name
))
68 ########################################
69 self
.begin_section('Global make variables')
71 for target
in install_sources
:
72 if isinstance(target
, gen_base
.TargetRaModule
) or \
73 isinstance(target
, gen_base
.TargetFsModule
):
74 # name of the module: strip 'libsvn_' and upper-case it
75 name
= string
.upper(target
.name
[7:])
77 # construct a list of the other .la libs to link against
78 retreat
= build_path_retreat(target
.path
)
79 if target
.name
in self
.installed_libs
:
81 link
= [ '-l%s-%s' % (target
.name
[3:], self
.version
) ]
83 deps
= [ target
.filename
]
84 link
= [ build_path_join(retreat
, target
.filename
) ]
85 for source
in self
.graph
.get_sources(gen_base
.DT_LINK
, target
.name
):
86 if not isinstance(source
, gen_base
.TargetLib
) or source
.external_lib
:
88 elif source
.name
in self
.installed_libs
:
90 deps
.append(source
.filename
)
91 link
.append(build_path_join(retreat
, source
.filename
))
93 self
.ofile
.write('%s_DEPS = %s\n'
94 '%s_LINK = %s\n\n' % (name
, string
.join(deps
, ' '),
95 name
, string
.join(link
, ' ')))
97 # write a list of directories in which things are built
98 # get all the test scripts' directories
99 script_dirs
= map(build_path_dirname
, self
.scripts
+ self
.bdb_scripts
)
101 # remove duplicate directories between targets and tests
102 build_dirs
= unique(self
.target_dirs
+ script_dirs
+ self
.swig_dirs
)
104 self
.ofile
.write('BUILD_DIRS = %s\n\n' % string
.join(build_dirs
))
106 # write lists of test files
107 # deps = all, progs = not including those marked "testing = skip"
108 self
.ofile
.write('BDB_TEST_DEPS = %s\n\n' %
109 string
.join(self
.bdb_test_deps
+ self
.bdb_scripts
))
110 self
.ofile
.write('BDB_TEST_PROGRAMS = %s\n\n' %
111 string
.join(self
.bdb_test_progs
+ self
.bdb_scripts
))
112 self
.ofile
.write('TEST_DEPS = %s\n\n' %
113 string
.join(self
.test_deps
+ self
.scripts
))
114 self
.ofile
.write('TEST_PROGRAMS = %s\n\n' %
115 string
.join(self
.test_progs
+ self
.scripts
))
117 # write list of all manpages
118 self
.ofile
.write('MANPAGES = %s\n\n' % string
.join(self
.manpages
))
120 # write a list of files to remove during "make clean"
122 for target
in install_sources
:
123 # .la files are handled by the standard 'clean' rule; clean all the
125 if not isinstance(target
, gen_base
.TargetScript
) \
126 and not isinstance(target
, gen_base
.TargetProject
) \
127 and not isinstance(target
, gen_base
.TargetI18N
) \
128 and not isinstance(target
, gen_base
.TargetJava
) \
129 and not target
.external_lib \
130 and target
.filename
[-3:] != '.la':
131 cfiles
.append(target
.filename
)
133 self
.ofile
.write('CLEAN_FILES = %s\n\n' % string
.join(cfiles
))
135 # this is here because autogen-standalone needs it too
136 self
.ofile
.write('SWIG_INCLUDES = -I$(abs_srcdir)/subversion/include \\\n'
137 ' -I$(abs_srcdir)/subversion/bindings/swig \\\n'
138 ' -I$(abs_srcdir)/subversion/bindings/swig/include \\\n'
139 ' -I$(abs_srcdir)/subversion/bindings/swig/proxy \\\n'
140 ' -I$(abs_builddir)/subversion/bindings/swig/proxy \\\n'
141 ' $(SVN_APR_INCLUDES) $(SVN_APRUTIL_INCLUDES)\n\n')
143 if self
.release_mode
:
144 self
.ofile
.write('RELEASE_MODE = 1\n\n')
146 ########################################
147 self
.begin_section('SWIG headers (wrappers and external runtimes)')
149 if not self
.release_mode
:
150 for swig
in (generator
.swig
.header_wrappers
,
151 generator
.swig
.checkout_swig_header
,
152 generator
.swig
.external_runtime
):
153 gen
= swig
.Generator(self
.conf
, "swig")
154 gen
.write_makefile_rules(self
.ofile
)
156 ########################################
157 self
.begin_section('SWIG autogen rules')
159 # write dependencies and build rules for generated .c files
160 swig_c_deps
= self
.graph
.get_deps(gen_base
.DT_SWIG_C
)
161 swig_c_deps
.sort(lambda (t1
, s1
), (t2
, s2
): cmp(t1
.filename
, t2
.filename
))
164 for lang
in self
.swig
.langs
:
165 swig_lang_deps
[lang
] = []
167 short
= self
.swig
.short
168 for objname
, sources
in swig_c_deps
:
170 swig_lang_deps
[lang
].append(str(objname
))
172 for lang
in self
.swig
.langs
:
173 lang_deps
= string
.join(swig_lang_deps
[lang
])
175 'autogen-swig-%s: %s\n' % (short
[lang
], lang_deps
) +
176 'autogen-swig: autogen-swig-%s\n' % short
[lang
] +
178 self
.ofile
.write('\n')
180 ########################################
181 self
.begin_section('Rules to build SWIG .c files from .i files')
183 for objname
, sources
in swig_c_deps
:
184 deps
= string
.join(map(str, sources
))
185 source
= str(sources
[0])
186 source_dir
= build_path_dirname(source
)
187 opts
= self
.swig
.opts
[objname
.lang
]
188 if not self
.release_mode
:
189 self
.ofile
.write('$(top_builddir)/%s: %s\n' % (objname
, deps
) +
190 '\t$(SWIG) $(SWIG_INCLUDES) %s ' % opts
+
191 '-o $@ $(top_srcdir)/%s\n' % source
194 self
.ofile
.write('\n')
196 ########################################
197 self
.begin_section('Individual target build rules')
199 for target_ob
in install_sources
:
201 if isinstance(target_ob
, gen_base
.TargetScript
):
202 # there is nothing to build
205 target
= target_ob
.name
206 if isinstance(target_ob
, gen_base
.TargetJava
):
207 path
= target_ob
.output_dir
209 path
= target_ob
.path
211 retreat
= build_path_retreat(path
)
213 # get the source items (.o and .la) for the link unit
218 header_class_filenames
= [ ]
222 for link_dep
in self
.graph
.get_sources(gen_base
.DT_LINK
, target_ob
.name
):
223 if isinstance(link_dep
, gen_base
.TargetJava
):
224 deps
.append(link_dep
.name
)
225 elif isinstance(link_dep
, gen_base
.TargetLinked
):
226 if link_dep
.external_lib
:
227 libs
.append(link_dep
.external_lib
)
228 elif link_dep
.external_project
:
229 # FIXME: This is a temporary workaround to fix build breakage
230 # expeditiously. It is of questionable validity for a build
231 # node to have external_project but not have external_lib.
233 elif link_dep
.name
in self
.installed_libs
:
234 libs
.append('-l%s-%s' % (link_dep
.name
[3:], self
.version
))
236 # append the output of the target to our stated dependencies
237 if not self
.assume_shared_libs
:
238 deps
.append(link_dep
.filename
)
240 # link against the library
241 libs
.append(build_path_join(retreat
, link_dep
.filename
))
242 elif isinstance(link_dep
, gen_base
.ObjectFile
):
243 # link in the object file
244 objects
.append(link_dep
.filename
)
245 for dep
in self
.graph
.get_sources(gen_base
.DT_OBJECT
, link_dep
, gen_base
.SourceFile
):
247 build_path_join('$(abs_srcdir)', dep
.filename
))
248 elif isinstance(link_dep
, gen_base
.HeaderFile
):
249 # link in the header file
250 # N.B. that filename_win contains the '_'-escaped class name
251 headers
.append(link_dep
.filename_win
)
252 header_classes
.append(link_dep
.classname
)
253 for dep
in self
.graph
.get_sources(gen_base
.DT_OBJECT
, link_dep
, gen_base
.ObjectFile
):
254 header_class_filenames
.append(dep
.filename
)
256 ### we don't know what this is, so we don't know what to do with it
257 raise UnknownDependency
259 for nonlib
in self
.graph
.get_sources(gen_base
.DT_NONLIB
, target_ob
.name
):
260 if isinstance(nonlib
, gen_base
.TargetLinked
):
261 if not nonlib
.external_lib
:
262 deps
.append(nonlib
.filename
)
264 targ_varname
= string
.replace(target
, '-', '_')
265 objnames
= string
.join(build_path_strip(path
, objects
))
267 # Output value of path variable
268 self
.ofile
.write('%s_PATH = %s\n' % (targ_varname
, path
))
270 # Add additional install dependencies if necessary
271 if target_ob
.add_install_deps
:
272 self
.ofile
.write('install-%s: %s\n'
273 % (target_ob
.install
, target_ob
.add_install_deps
))
275 if isinstance(target_ob
, gen_base
.TargetJava
):
279 '%s_DEPS = $(%s_HEADERS) $(%s_OBJECTS) %s %s\n'
281 % (targ_varname
, string
.join(headers
),
283 targ_varname
, string
.join(objects
),
285 targ_varname
, targ_varname
, targ_varname
, target_ob
.add_deps
,
288 target_ob
.name
, targ_varname
))
290 # Build the headers from the header_classes with one 'javah' call
293 '%s_CLASS_FILENAMES = %s\n'
295 '$(%s_HEADERS): $(%s_CLASS_FILENAMES)\n'
296 '\t%s -d %s -classpath %s:$(%s_CLASSPATH) $(%s_CLASSES)\n'
297 % (targ_varname
, string
.join(header_class_filenames
),
299 targ_varname
, string
.join(header_classes
),
301 targ_varname
, targ_varname
,
303 target_ob
.link_cmd
, target_ob
.output_dir
, target_ob
.classes
,
304 targ_varname
, targ_varname
))
306 # Build the objects from the object_srcs with one 'javac' call
310 '$(%s_OBJECTS): $(%s_SRC)\n'
311 '\t%s -d %s -classpath %s:$(%s_CLASSPATH) $(%s_SRC)\n'
312 % (targ_varname
, string
.join(object_srcs
),
314 targ_varname
, targ_varname
,
316 target_ob
.link_cmd
, target_ob
.output_dir
, target_ob
.classes
,
317 targ_varname
, targ_varname
))
319 # Once the bytecodes have been compiled up, we produce the
322 self
.ofile
.write('\n\t$(JAR) cf %s -C %s %s' %
323 (build_path_join(target_ob
.classes
, target_ob
.jar
),
325 string
.join(target_ob
.packages
, ' ')))
327 self
.ofile
.write('\n\n')
328 elif isinstance(target_ob
, gen_base
.TargetI18N
):
332 % (targ_varname
, target_ob
.add_deps
, string
.join(objects
+ deps
),
333 target_ob
.name
, targ_varname
))
339 '\tcd %s && %s -o %s %s $(%s_OBJECTS) %s $(LIBS)\n\n'
340 % (targ_varname
, target_ob
.add_deps
, string
.join(objects
+ deps
),
342 targ_varname
, objnames
,
344 target_ob
.filename
, targ_varname
,
346 path
, target_ob
.link_cmd
,
347 build_path_basename(target_ob
.filename
),
348 (isinstance(target_ob
, gen_base
.TargetLib
) and not
349 target_ob
.undefined_lib_symbols
) and '$(LT_NO_UNDEFINED)' or "",
350 targ_varname
, string
.join(gen_base
.unique(libs
)))
353 ########################################
354 self
.begin_section('Install-Group build targets')
356 for itype
, i_targets
in install_deps
:
358 # perl bindings do their own thing, "swig-pl" target is
359 # already specified in Makefile.in
360 if itype
== "swig-pl":
365 if hasattr(t
, 'filename'):
366 outputs
.append(t
.filename
)
367 self
.ofile
.write('%s: %s\n\n' % (itype
, string
.join(outputs
)))
369 ########################################
370 self
.begin_section('Install-Group install targets')
372 # for each install group, write a rule to install its outputs
373 for area
, inst_targets
in install_deps
:
375 # perl bindings do their own thing, "install-swig-pl" target is
376 # already specified in Makefile.in
377 if area
== "swig-pl":
380 # get the output files for these targets, sorted in dependency order
381 files
= gen_base
._sorted
_files
(self
.graph
, area
)
383 if area
== 'apache-mod':
384 self
.ofile
.write('install-mods-shared: %s\n' % (string
.join(files
),))
387 # cd to dirname before install to work around libtool 1.4.2 bug.
388 dirname
, fname
= build_path_splitfile(file)
389 base
, ext
= os
.path
.splitext(fname
)
390 name
= string
.replace(base
, 'mod_', '')
391 self
.ofile
.write('\tcd %s ; '
392 '$(MKDIR) "$(APACHE_LIBEXECDIR)" ; '
393 '$(INSTALL_MOD_SHARED) -n %s %s\n'
394 % (dirname
, name
, fname
))
396 la_tweaked
[file + '-a'] = None
398 for apmod
in inst_targets
:
399 for source
in self
.graph
.get_sources(gen_base
.DT_LINK
, apmod
.name
,
401 if not source
.external_lib
:
404 la_tweaked
[bt
+ '-a'] = None
405 la_tweaked
= la_tweaked
.keys()
408 # Construct a .libs directory within the Apache area and populate it
409 # with the appropriate files. Also drop the .la file in the target dir.
410 self
.ofile
.write('\ninstall-mods-static: %s\n'
411 '\t$(MKDIR) $(DESTDIR)%s\n'
412 % (string
.join(la_tweaked
+ self
.apache_files
),
413 build_path_join('$(APACHE_TARGET)', '.libs')))
414 for file in la_tweaked
:
415 dirname
, fname
= build_path_splitfile(file)
416 base
= os
.path
.splitext(fname
)[0]
417 self
.ofile
.write('\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
418 '\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
419 % (build_path_join(dirname
, '.libs', base
+ '.a'),
420 build_path_join('$(APACHE_TARGET)', '.libs',
423 build_path_join('$(APACHE_TARGET)', base
+ '.la')))
425 # copy the other files to the target dir
426 for file in self
.apache_files
:
427 self
.ofile
.write('\t$(INSTALL_MOD_STATIC) %s $(DESTDIR)%s\n'
428 % (file, build_path_join('$(APACHE_TARGET)',
429 build_path_basename(file))))
430 self
.ofile
.write('\n')
432 elif area
!= 'test' and area
!= 'bdb-test':
433 area_var
= string
.replace(area
, '-', '_')
434 upper_var
= string
.upper(area_var
)
435 self
.ofile
.write('install-%s: %s\n'
436 '\t$(MKDIR) $(DESTDIR)$(%sdir)\n'
437 % (area
, string
.join(files
), area_var
))
439 # cd to dirname before install to work around libtool 1.4.2 bug.
440 dirname
, fname
= build_path_splitfile(file)
442 lang
, objext
= os
.path
.splitext(fname
)
443 installdir
= '$(DESTDIR)$(%sdir)/%s/LC_MESSAGES' % (area_var
, lang
)
444 self
.ofile
.write('\t$(MKDIR) %s\n'
445 '\tcd %s ; $(INSTALL_%s) %s '
446 '%s/$(PACKAGE_NAME)%s\n'
448 dirname
, upper_var
, fname
,
451 self
.ofile
.write('\tcd %s ; $(INSTALL_%s) %s $(DESTDIR)%s\n'
452 % (dirname
, upper_var
, fname
,
453 build_path_join('$(%sdir)' % area_var
, fname
)))
454 # certain areas require hooks for extra install rules defined
456 ### we should turn AREA into an object, then test it instead of this
457 if area
[:5] == 'swig-' and area
[-4:] != '-lib' or \
458 area
[:7] == 'javahl-':
459 self
.ofile
.write('\t$(INSTALL_EXTRA_%s)\n' % upper_var
)
460 self
.ofile
.write('\n')
462 ########################################
463 self
.begin_section('The install-include rule')
465 includedir
= build_path_join('$(includedir)',
466 'subversion-%s' % self
.version
)
467 self
.ofile
.write('install-include: %s\n'
468 '\t$(MKDIR) $(DESTDIR)%s\n'
469 % (string
.join(self
.includes
), includedir
))
470 for file in self
.includes
:
471 self
.ofile
.write('\t$(INSTALL_INCLUDE) %s $(DESTDIR)%s\n'
472 % (build_path_join('$(abs_srcdir)', file),
473 build_path_join(includedir
,
474 build_path_basename(file))))
476 ########################################
477 self
.begin_section('Shortcut targets for manual builds of specific items')
479 for target
in install_sources
:
480 if not isinstance(target
, gen_base
.TargetScript
) and \
481 not isinstance(target
, gen_base
.TargetJava
) and \
482 not isinstance(target
, gen_base
.TargetI18N
):
483 self
.ofile
.write('%s: %s\n' % (target
.name
, target
.filename
))
485 ########################################
486 self
.begin_section('Rules to build all other kinds of object-like files')
488 # write dependencies and build rules (when not using suffix rules)
489 # for all other generated files which will not be installed
490 # (or will be installed, but not by the main generated build)
491 obj_deps
= self
.graph
.get_deps(gen_base
.DT_OBJECT
)
492 obj_deps
.sort(lambda (t1
, s1
), (t2
, s2
): cmp(t1
.filename
, t2
.filename
))
494 for objname
, sources
in obj_deps
:
495 deps
= string
.join(map(str, sources
))
496 self
.ofile
.write('%s: %s\n' % (objname
, deps
))
497 cmd
= objname
.compile_cmd
499 if not getattr(objname
, 'source_generated', 0):
500 self
.ofile
.write('\t%s %s\n\n'
501 % (cmd
, build_path_join('$(abs_srcdir)',
504 self
.ofile
.write('\t%s %s\n\n' % (cmd
, sources
[0]))
506 self
.ofile
.write('\n')
510 self
.write_standalone()
512 def write_standalone(self
):
513 """Write autogen-standalone.mk"""
515 standalone
= open("autogen-standalone.mk", "w")
516 standalone
.write('# DO NOT EDIT -- AUTOMATICALLY GENERATED\n')
517 standalone
.write('abs_srcdir = %s\n' % os
.getcwd())
518 standalone
.write('abs_builddir = %s\n' % os
.getcwd())
519 standalone
.write('top_srcdir = .\n')
520 standalone
.write('top_builddir = .\n')
521 standalone
.write('SWIG = swig\n')
522 standalone
.write('PYTHON = python\n')
523 standalone
.write('\n')
524 standalone
.write(open("build-outputs.mk","r").read())
527 class UnknownDependency(Exception):
528 "We don't know how to deal with the dependent to link it in."