blob: 51923ebad7b3ba204eec9b71bf117147a0d16460 [file] [log] [blame]
Daniel Dunbarad5e0122011-11-03 17:56:03 +00001import os
Daniel Dunbar1cf14af2011-11-03 17:56:12 +00002import sys
Daniel Dunbarad5e0122011-11-03 17:56:03 +00003
Daniel Dunbardf578252011-11-03 17:56:06 +00004import componentinfo
5
Daniel Dunbar1cf14af2011-11-03 17:56:12 +00006from util import *
7
8###
9
Daniel Dunbar57574fa2011-11-05 04:07:43 +000010def cmake_quote_string(value):
11 """
12 cmake_quote_string(value) -> str
13
14 Return a quoted form of the given value that is suitable for use in CMake
15 language files.
16 """
17
18 # Currently, we only handle escaping backslashes.
19 value = value.replace("\\", "\\\\")
20
21 return value
22
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000023def mk_quote_string_for_target(value):
24 """
25 mk_quote_string_for_target(target_name) -> str
26
27 Return a quoted form of the given target_name suitable for including in a
28 Makefile as a target name.
29 """
30
31 # The only quoting we currently perform is for ':', to support msys users.
32 return value.replace(":", "\\:")
33
Daniel Dunbar195c6f32011-11-05 04:07:49 +000034def make_install_dir(path):
35 """
36 make_install_dir(path) -> None
37
38 Create the given directory path for installation, including any parents.
39 """
40
41 # os.makedirs considers it an error to be called with an existant path.
42 if not os.path.exists(path):
43 os.makedirs(path)
44
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000045###
46
Daniel Dunbardf578252011-11-03 17:56:06 +000047class LLVMProjectInfo(object):
48 @staticmethod
49 def load_infos_from_path(llvmbuild_source_root):
50 # FIXME: Implement a simple subpath file list cache, so we don't restat
51 # directories we have already traversed.
52
53 # First, discover all the LLVMBuild.txt files.
Daniel Dunbare10233b2011-11-03 19:45:52 +000054 #
55 # FIXME: We would like to use followlinks=True here, but that isn't
56 # compatible with Python 2.4. Instead, we will either have to special
57 # case projects we would expect to possibly be linked to, or implement
58 # our own walk that can follow links. For now, it doesn't matter since
59 # we haven't picked up the LLVMBuild system in any other LLVM projects.
60 for dirpath,dirnames,filenames in os.walk(llvmbuild_source_root):
Daniel Dunbardf578252011-11-03 17:56:06 +000061 # If there is no LLVMBuild.txt file in a directory, we don't recurse
62 # past it. This is a simple way to prune our search, although it
63 # makes it easy for users to add LLVMBuild.txt files in places they
64 # won't be seen.
65 if 'LLVMBuild.txt' not in filenames:
66 del dirnames[:]
67 continue
68
69 # Otherwise, load the LLVMBuild file in this directory.
70 assert dirpath.startswith(llvmbuild_source_root)
71 subpath = '/' + dirpath[len(llvmbuild_source_root)+1:]
72 llvmbuild_path = os.path.join(dirpath, 'LLVMBuild.txt')
73 for info in componentinfo.load_from_path(llvmbuild_path, subpath):
74 yield info
75
76 @staticmethod
77 def load_from_path(source_root, llvmbuild_source_root):
78 infos = list(
79 LLVMProjectInfo.load_infos_from_path(llvmbuild_source_root))
80
81 return LLVMProjectInfo(source_root, infos)
82
83 def __init__(self, source_root, component_infos):
Daniel Dunbar1cf14af2011-11-03 17:56:12 +000084 # Store our simple ivars.
Daniel Dunbardf578252011-11-03 17:56:06 +000085 self.source_root = source_root
Daniel Dunbarb4eaee72011-11-10 00:49:58 +000086 self.component_infos = list(component_infos)
87 self.component_info_map = None
88 self.ordered_component_infos = None
89
90 def validate_components(self):
91 """validate_components() -> None
92
93 Validate that the project components are well-defined. Among other
94 things, this checks that:
95 - Components have valid references.
96 - Components references do not form cycles.
97
98 We also construct the map from component names to info, and the
99 topological ordering of components.
100 """
Daniel Dunbardf578252011-11-03 17:56:06 +0000101
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000102 # Create the component info map and validate that component names are
103 # unique.
104 self.component_info_map = {}
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000105 for ci in self.component_infos:
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000106 existing = self.component_info_map.get(ci.name)
107 if existing is not None:
108 # We found a duplicate component name, report it and error out.
109 fatal("found duplicate component %r (at %r and %r)" % (
110 ci.name, ci.subpath, existing.subpath))
111 self.component_info_map[ci.name] = ci
112
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000113 # Disallow 'all' as a component name, which is a special case.
114 if 'all' in self.component_info_map:
115 fatal("project is not allowed to define 'all' component")
116
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000117 # Add the root component.
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000118 if '$ROOT' in self.component_info_map:
119 fatal("project is not allowed to define $ROOT component")
120 self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo(
121 '/', '$ROOT', None)
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000122 self.component_infos.append(self.component_info_map['$ROOT'])
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000123
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000124 # Topologically order the component information according to their
125 # component references.
126 def visit_component_info(ci, current_stack, current_set):
127 # Check for a cycles.
128 if ci in current_set:
129 # We found a cycle, report it and error out.
130 cycle_description = ' -> '.join(
131 '%r (%s)' % (ci.name, relation)
132 for relation,ci in current_stack)
133 fatal("found cycle to %r after following: %s -> %s" % (
134 ci.name, cycle_description, ci.name))
135
136 # If we have already visited this item, we are done.
137 if ci not in components_to_visit:
138 return
139
140 # Otherwise, mark the component info as visited and traverse.
141 components_to_visit.remove(ci)
142
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000143 # Validate the parent reference, which we treat specially.
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000144 if ci.parent is not None:
145 parent = self.component_info_map.get(ci.parent)
146 if parent is None:
147 fatal("component %r has invalid reference %r (via %r)" % (
148 ci.name, ci.parent, 'parent'))
149 ci.set_parent_instance(parent)
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000150
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000151 for relation,referent_name in ci.get_component_references():
152 # Validate that the reference is ok.
153 referent = self.component_info_map.get(referent_name)
154 if referent is None:
155 fatal("component %r has invalid reference %r (via %r)" % (
156 ci.name, referent_name, relation))
157
158 # Visit the reference.
159 current_stack.append((relation,ci))
160 current_set.add(ci)
161 visit_component_info(referent, current_stack, current_set)
162 current_set.remove(ci)
163 current_stack.pop()
164
165 # Finally, add the component info to the ordered list.
166 self.ordered_component_infos.append(ci)
167
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000168 # FIXME: We aren't actually correctly checking for cycles along the
169 # parent edges. Haven't decided how I want to handle this -- I thought
170 # about only checking cycles by relation type. If we do that, it falls
171 # out easily. If we don't, we should special case the check.
172
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000173 self.ordered_component_infos = []
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000174 components_to_visit = set(self.component_infos)
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000175 while components_to_visit:
176 visit_component_info(iter(components_to_visit).next(), [], set())
177
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000178 # Canonicalize children lists.
179 for c in self.ordered_component_infos:
180 c.children.sort(key = lambda c: c.name)
181
182 def print_tree(self):
183 def visit(node, depth = 0):
184 print '%s%-40s (%s)' % (' '*depth, node.name, node.type_name)
185 for c in node.children:
186 visit(c, depth + 1)
187 visit(self.component_info_map['$ROOT'])
188
Daniel Dunbar43120df2011-11-03 17:56:21 +0000189 def write_components(self, output_path):
190 # Organize all the components by the directory their LLVMBuild file
191 # should go in.
192 info_basedir = {}
193 for ci in self.component_infos:
194 # Ignore the $ROOT component.
195 if ci.parent is None:
196 continue
197
198 info_basedir[ci.subpath] = info_basedir.get(ci.subpath, []) + [ci]
199
200 # Generate the build files.
201 for subpath, infos in info_basedir.items():
202 # Order the components by name to have a canonical ordering.
203 infos.sort(key = lambda ci: ci.name)
204
205 # Format the components into llvmbuild fragments.
206 fragments = filter(None, [ci.get_llvmbuild_fragment()
207 for ci in infos])
208 if not fragments:
209 continue
210
211 assert subpath.startswith('/')
212 directory_path = os.path.join(output_path, subpath[1:])
213
214 # Create the directory if it does not already exist.
215 if not os.path.exists(directory_path):
216 os.makedirs(directory_path)
217
218 # Create the LLVMBuild file.
219 file_path = os.path.join(directory_path, 'LLVMBuild.txt')
220 f = open(file_path, "w")
Daniel Dunbarfb6d79a2011-11-03 17:56:31 +0000221
222 # Write the header.
223 header_fmt = ';===- %s %s-*- Conf -*--===;'
224 header_name = '.' + os.path.join(subpath, 'LLVMBuild.txt')
225 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
226 header_string = header_fmt % (header_name, header_pad)
227 print >>f, """\
228%s
229;
230; The LLVM Compiler Infrastructure
231;
232; This file is distributed under the University of Illinois Open Source
233; License. See LICENSE.TXT for details.
234;
235;===------------------------------------------------------------------------===;
236;
237; This is an LLVMBuild description file for the components in this subdirectory.
238;
239; For more information on the LLVMBuild system, please see:
240;
241; http://llvm.org/docs/LLVMBuild.html
242;
243;===------------------------------------------------------------------------===;
244""" % header_string
245
Daniel Dunbar43120df2011-11-03 17:56:21 +0000246 for i,fragment in enumerate(fragments):
247 print >>f, '[component_%d]' % i
248 f.write(fragment)
249 print >>f
250 f.close()
251
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000252 def write_library_table(self, output_path):
253 # Write out the mapping from component names to required libraries.
254 #
255 # We do this in topological order so that we know we can append the
256 # dependencies for added library groups.
257 entries = {}
258 for c in self.ordered_component_infos:
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000259 # Only certain components are in the table.
260 if c.type_name not in ('Library', 'LibraryGroup', 'TargetGroup'):
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000261 continue
262
263 # Compute the llvm-config "component name". For historical reasons,
264 # this is lowercased based on the library name.
265 llvmconfig_component_name = c.get_llvmconfig_component_name()
266
267 # Get the library name, or None for LibraryGroups.
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000268 if c.type_name == 'Library':
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000269 library_name = c.get_library_name()
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000270 else:
271 library_name = None
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000272
273 # Get the component names of all the required libraries.
274 required_llvmconfig_component_names = [
275 self.component_info_map[dep].get_llvmconfig_component_name()
276 for dep in c.required_libraries]
277
278 # Insert the entries for library groups we should add to.
279 for dep in c.add_to_library_groups:
280 entries[dep][2].append(llvmconfig_component_name)
281
282 # Add the entry.
283 entries[c.name] = (llvmconfig_component_name, library_name,
284 required_llvmconfig_component_names)
285
286 # Convert to a list of entries and sort by name.
287 entries = entries.values()
288
289 # Create an 'all' pseudo component. We keep the dependency list small by
290 # only listing entries that have no other dependents.
291 root_entries = set(e[0] for e in entries)
292 for _,_,deps in entries:
293 root_entries -= set(deps)
294 entries.append(('all', None, root_entries))
295
296 entries.sort()
297
298 # Compute the maximum number of required libraries, plus one so there is
299 # always a sentinel.
300 max_required_libraries = max(len(deps)
301 for _,_,deps in entries) + 1
302
303 # Write out the library table.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000304 make_install_dir(os.path.dirname(output_path))
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000305 f = open(output_path, 'w')
306 print >>f, """\
307//===- llvm-build generated file --------------------------------*- C++ -*-===//
308//
309// Component Library Depenedency Table
310//
311// Automatically generated file, do not edit!
312//
313//===----------------------------------------------------------------------===//
314"""
315 print >>f, 'struct AvailableComponent {'
316 print >>f, ' /// The name of the component.'
317 print >>f, ' const char *Name;'
318 print >>f, ''
319 print >>f, ' /// The name of the library for this component (or NULL).'
320 print >>f, ' const char *Library;'
321 print >>f, ''
322 print >>f, '\
323 /// The list of libraries required when linking this component.'
324 print >>f, ' const char *RequiredLibraries[%d];' % (
325 max_required_libraries)
326 print >>f, '} AvailableComponents[%d] = {' % len(entries)
327 for name,library_name,required_names in entries:
328 if library_name is None:
329 library_name_as_cstr = '0'
330 else:
331 # If we had a project level component, we could derive the
332 # library prefix.
333 library_name_as_cstr = '"libLLVM%s.a"' % library_name
334 print >>f, ' { "%s", %s, { %s } },' % (
335 name, library_name_as_cstr,
336 ', '.join('"%s"' % dep
337 for dep in required_names))
338 print >>f, '};'
339 f.close()
340
Daniel Dunbar16889612011-11-04 23:10:37 +0000341 def get_fragment_dependencies(self):
Daniel Dunbar02271a72011-11-03 22:46:19 +0000342 """
Daniel Dunbar16889612011-11-04 23:10:37 +0000343 get_fragment_dependencies() -> iter
Daniel Dunbar02271a72011-11-03 22:46:19 +0000344
Daniel Dunbar16889612011-11-04 23:10:37 +0000345 Compute the list of files (as absolute paths) on which the output
346 fragments depend (i.e., files for which a modification should trigger a
347 rebuild of the fragment).
Daniel Dunbar02271a72011-11-03 22:46:19 +0000348 """
349
350 # Construct a list of all the dependencies of the Makefile fragment
351 # itself. These include all the LLVMBuild files themselves, as well as
352 # all of our own sources.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000353 for ci in self.component_infos:
Daniel Dunbar16889612011-11-04 23:10:37 +0000354 yield os.path.join(self.source_root, ci.subpath[1:],
355 'LLVMBuild.txt')
Daniel Dunbar02271a72011-11-03 22:46:19 +0000356
357 # Gather the list of necessary sources by just finding all loaded
358 # modules that are inside the LLVM source tree.
359 for module in sys.modules.values():
360 # Find the module path.
361 if not hasattr(module, '__file__'):
362 continue
363 path = getattr(module, '__file__')
364 if not path:
365 continue
366
367 # Strip off any compiled suffix.
368 if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
369 path = path[:-1]
370
371 # If the path exists and is in the source tree, consider it a
372 # dependency.
373 if (path.startswith(self.source_root) and os.path.exists(path)):
Daniel Dunbar16889612011-11-04 23:10:37 +0000374 yield path
375
376 def write_cmake_fragment(self, output_path):
377 """
378 write_cmake_fragment(output_path) -> None
379
380 Generate a CMake fragment which includes all of the collated LLVMBuild
381 information in a format that is easily digestible by a CMake. The exact
382 contents of this are closely tied to how the CMake configuration
383 integrates LLVMBuild, see CMakeLists.txt in the top-level.
384 """
385
386 dependencies = list(self.get_fragment_dependencies())
387
388 # Write out the CMake fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000389 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar16889612011-11-04 23:10:37 +0000390 f = open(output_path, 'w')
391
392 # Write the header.
393 header_fmt = '\
394#===-- %s - LLVMBuild Configuration for LLVM %s-*- CMake -*--===#'
395 header_name = os.path.basename(output_path)
396 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
397 header_string = header_fmt % (header_name, header_pad)
398 print >>f, """\
399%s
400#
401# The LLVM Compiler Infrastructure
402#
403# This file is distributed under the University of Illinois Open Source
404# License. See LICENSE.TXT for details.
405#
406#===------------------------------------------------------------------------===#
407#
408# This file contains the LLVMBuild project information in a format easily
409# consumed by the CMake based build system.
410#
411# This file is autogenerated by llvm-build, do not edit!
412#
413#===------------------------------------------------------------------------===#
414""" % header_string
415
416 # Write the dependency information in the best way we can.
417 print >>f, """
418# LLVMBuild CMake fragment dependencies.
419#
420# CMake has no builtin way to declare that the configuration depends on
421# a particular file. However, a side effect of configure_file is to add
422# said input file to CMake's internal dependency list. So, we use that
423# and a dummy output file to communicate the dependency information to
424# CMake.
425#
426# FIXME: File a CMake RFE to get a properly supported version of this
427# feature."""
428 for dep in dependencies:
429 print >>f, """\
430configure_file(\"%s\"
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000431 ${CMAKE_CURRENT_BINARY_DIR}/DummyConfigureOutput)""" % (
432 cmake_quote_string(dep),)
433
Daniel Dunbar16889612011-11-04 23:10:37 +0000434 f.close()
435
436 def write_make_fragment(self, output_path):
437 """
438 write_make_fragment(output_path) -> None
439
440 Generate a Makefile fragment which includes all of the collated
441 LLVMBuild information in a format that is easily digestible by a
442 Makefile. The exact contents of this are closely tied to how the LLVM
443 Makefiles integrate LLVMBuild, see Makefile.rules in the top-level.
444 """
445
446 dependencies = list(self.get_fragment_dependencies())
Daniel Dunbar02271a72011-11-03 22:46:19 +0000447
448 # Write out the Makefile fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000449 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar02271a72011-11-03 22:46:19 +0000450 f = open(output_path, 'w')
451
452 # Write the header.
453 header_fmt = '\
454#===-- %s - LLVMBuild Configuration for LLVM %s-*- Makefile -*--===#'
455 header_name = os.path.basename(output_path)
456 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
457 header_string = header_fmt % (header_name, header_pad)
458 print >>f, """\
459%s
460#
461# The LLVM Compiler Infrastructure
462#
463# This file is distributed under the University of Illinois Open Source
464# License. See LICENSE.TXT for details.
465#
466#===------------------------------------------------------------------------===#
467#
468# This file contains the LLVMBuild project information in a format easily
469# consumed by the Makefile based build system.
470#
471# This file is autogenerated by llvm-build, do not edit!
472#
473#===------------------------------------------------------------------------===#
474""" % header_string
475
476 # Write the dependencies for the fragment.
477 #
478 # FIXME: Technically, we need to properly quote for Make here.
479 print >>f, """\
480# Clients must explicitly enable LLVMBUILD_INCLUDE_DEPENDENCIES to get
481# these dependencies. This is a compromise to help improve the
482# performance of recursive Make systems."""
483 print >>f, 'ifeq ($(LLVMBUILD_INCLUDE_DEPENDENCIES),1)'
484 print >>f, "# The dependencies for this Makefile fragment itself."
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000485 print >>f, "%s: \\" % (mk_quote_string_for_target(output_path),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000486 for dep in dependencies:
487 print >>f, "\t%s \\" % (dep,)
488 print >>f
489
490 # Generate dummy rules for each of the dependencies, so that things
491 # continue to work correctly if any of those files are moved or removed.
492 print >>f, """\
493# The dummy targets to allow proper regeneration even when files are moved or
494# removed."""
495 for dep in dependencies:
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000496 print >>f, "%s:" % (mk_quote_string_for_target(dep),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000497 print >>f, 'endif'
498
499 f.close()
500
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000501def add_magic_target_components(parser, project, opts):
502 """add_magic_target_components(project, opts) -> None
503
504 Add the "magic" target based components to the project, which can only be
505 determined based on the target configuration options.
506
507 This currently is responsible for populating the required_libraries list of
Daniel Dunbar83337302011-11-10 01:16:48 +0000508 the "all-targets", "Native", "NativeCodeGen", and "Engine" components.
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000509 """
510
511 # Determine the available targets.
512 available_targets = dict((ci.name,ci)
513 for ci in project.component_infos
514 if ci.type_name == 'TargetGroup')
515
516 # Find the configured native target.
517
518 # We handle a few special cases of target names here for historical
519 # reasons, as these are the names configure currently comes up with.
520 native_target_name = { 'x86' : 'X86',
521 'x86_64' : 'X86',
522 'Unknown' : None }.get(opts.native_target,
523 opts.native_target)
524 if native_target_name is None:
525 native_target = None
526 else:
527 native_target = available_targets.get(native_target_name)
528 if native_target is None:
529 parser.error("invalid native target: %r (not in project)" % (
530 opts.native_target,))
531 if native_target.type_name != 'TargetGroup':
532 parser.error("invalid native target: %r (not a target)" % (
533 opts.native_target,))
534
535 # Find the list of targets to enable.
536 if opts.enable_targets is None:
537 enable_targets = available_targets.values()
538 else:
Daniel Dunbar83337302011-11-10 01:16:48 +0000539 # We support both space separated and semi-colon separated lists.
540 if ' ' in opts.enable_targets:
541 enable_target_names = opts.enable_targets.split()
542 else:
543 enable_target_names = opts.enable_targets.split(';')
544
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000545 enable_targets = []
Daniel Dunbar83337302011-11-10 01:16:48 +0000546 for name in enable_target_names:
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000547 target = available_targets.get(name)
548 if target is None:
549 parser.error("invalid target to enable: %r (not in project)" % (
550 name,))
551 if target.type_name != 'TargetGroup':
552 parser.error("invalid target to enable: %r (not a target)" % (
553 name,))
554 enable_targets.append(target)
555
556 # Find the special library groups we are going to populate. We enforce that
557 # these appear in the project (instead of just adding them) so that they at
558 # least have an explicit representation in the project LLVMBuild files (and
559 # comments explaining how they are populated).
560 def find_special_group(name):
561 info = info_map.get(name)
562 if info is None:
563 fatal("expected project to contain special %r component" % (
564 name,))
565
566 if info.type_name != 'LibraryGroup':
567 fatal("special component %r should be a LibraryGroup" % (
568 name,))
569
570 if info.required_libraries:
571 fatal("special component %r must have empty %r list" % (
572 name, 'required_libraries'))
573 if info.add_to_library_groups:
574 fatal("special component %r must have empty %r list" % (
575 name, 'add_to_library_groups'))
576
577 return info
578
579 info_map = dict((ci.name, ci) for ci in project.component_infos)
580 all_targets = find_special_group('all-targets')
581 native_group = find_special_group('Native')
582 native_codegen_group = find_special_group('NativeCodeGen')
583 engine_group = find_special_group('Engine')
584
585 # Set the enabled bit in all the target groups, and append to the
586 # all-targets list.
587 for ci in enable_targets:
588 all_targets.required_libraries.append(ci.name)
589 ci.enabled = True
590
591 # If we have a native target, then that defines the native and
592 # native_codegen libraries.
593 if native_target and native_target.enabled:
594 native_group.required_libraries.append(native_target.name)
595 native_codegen_group.required_libraries.append(
596 '%sCodeGen' % native_target.name)
597
598 # If we have a native target with a JIT, use that for the engine. Otherwise,
599 # use the interpreter.
600 if native_target and native_target.enabled and native_target.has_jit:
601 engine_group.required_libraries.append('JIT')
602 engine_group.required_libraries.append(native_group.name)
603 else:
604 engine_group.required_libraries.append('Interpreter')
605
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000606def main():
607 from optparse import OptionParser, OptionGroup
608 parser = OptionParser("usage: %prog [options]")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000609
610 group = OptionGroup(parser, "Input Options")
611 group.add_option("", "--source-root", dest="source_root", metavar="PATH",
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000612 help="Path to the LLVM source (inferred if not given)",
613 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000614 group.add_option("", "--llvmbuild-source-root",
615 dest="llvmbuild_source_root",
616 help=(
617 "If given, an alternate path to search for LLVMBuild.txt files"),
618 action="store", default=None, metavar="PATH")
619 parser.add_option_group(group)
620
621 group = OptionGroup(parser, "Output Options")
622 group.add_option("", "--print-tree", dest="print_tree",
623 help="Print out the project component tree [%default]",
624 action="store_true", default=False)
625 group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
Daniel Dunbar43120df2011-11-03 17:56:21 +0000626 help="Write out the LLVMBuild.txt files to PATH",
627 action="store", default=None, metavar="PATH")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000628 group.add_option("", "--write-library-table",
629 dest="write_library_table", metavar="PATH",
630 help="Write the C++ library dependency table to PATH",
631 action="store", default=None)
632 group.add_option("", "--write-cmake-fragment",
633 dest="write_cmake_fragment", metavar="PATH",
634 help="Write the CMake project information to PATH",
635 action="store", default=None)
636 group.add_option("", "--write-make-fragment",
Daniel Dunbar02271a72011-11-03 22:46:19 +0000637 dest="write_make_fragment", metavar="PATH",
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000638 help="Write the Makefile project information to PATH",
639 action="store", default=None)
640 parser.add_option_group(group)
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000641
642 group = OptionGroup(parser, "Configuration Options")
643 group.add_option("", "--native-target",
644 dest="native_target", metavar="NAME",
645 help=("Treat the named target as the 'native' one, if "
646 "given [%default]"),
647 action="store", default=None)
648 group.add_option("", "--enable-targets",
649 dest="enable_targets", metavar="NAMES",
Daniel Dunbar83337302011-11-10 01:16:48 +0000650 help=("Enable the given space or semi-colon separated "
651 "list of targets, or all targets if not present"),
Daniel Dunbar02271a72011-11-03 22:46:19 +0000652 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000653 parser.add_option_group(group)
654
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000655 (opts, args) = parser.parse_args()
656
657 # Determine the LLVM source path, if not given.
658 source_root = opts.source_root
659 if source_root:
660 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
661 'Function.cpp')):
662 parser.error('invalid LLVM source root: %r' % source_root)
663 else:
664 llvmbuild_path = os.path.dirname(__file__)
665 llvm_build_path = os.path.dirname(llvmbuild_path)
666 utils_path = os.path.dirname(llvm_build_path)
667 source_root = os.path.dirname(utils_path)
668 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
669 'Function.cpp')):
670 parser.error('unable to infer LLVM source root, please specify')
671
Daniel Dunbardf578252011-11-03 17:56:06 +0000672 # Construct the LLVM project information.
673 llvmbuild_source_root = opts.llvmbuild_source_root or source_root
674 project_info = LLVMProjectInfo.load_from_path(
675 source_root, llvmbuild_source_root)
676
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000677 # Add the magic target based components.
678 add_magic_target_components(parser, project_info, opts)
679
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000680 # Validate the project component info.
681 project_info.validate_components()
682
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000683 # Print the component tree, if requested.
684 if opts.print_tree:
685 project_info.print_tree()
686
Daniel Dunbar43120df2011-11-03 17:56:21 +0000687 # Write out the components, if requested. This is useful for auto-upgrading
688 # the schema.
689 if opts.write_llvmbuild:
690 project_info.write_components(opts.write_llvmbuild)
691
Daniel Dunbar16889612011-11-04 23:10:37 +0000692 # Write out the required library table, if requested.
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000693 if opts.write_library_table:
694 project_info.write_library_table(opts.write_library_table)
695
Daniel Dunbar16889612011-11-04 23:10:37 +0000696 # Write out the make fragment, if requested.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000697 if opts.write_make_fragment:
698 project_info.write_make_fragment(opts.write_make_fragment)
699
Daniel Dunbar16889612011-11-04 23:10:37 +0000700 # Write out the cmake fragment, if requested.
701 if opts.write_cmake_fragment:
702 project_info.write_cmake_fragment(opts.write_cmake_fragment)
703
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000704if __name__=='__main__':
705 main()