blob: fa76aa5d8ed051f24859b3edde1c7def08108694 [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
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +00005import configutil
Daniel Dunbardf578252011-11-03 17:56:06 +00006
Daniel Dunbar1cf14af2011-11-03 17:56:12 +00007from util import *
8
9###
10
Daniel Dunbar57574fa2011-11-05 04:07:43 +000011def cmake_quote_string(value):
12 """
13 cmake_quote_string(value) -> str
14
15 Return a quoted form of the given value that is suitable for use in CMake
16 language files.
17 """
18
19 # Currently, we only handle escaping backslashes.
20 value = value.replace("\\", "\\\\")
21
22 return value
23
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000024def mk_quote_string_for_target(value):
25 """
26 mk_quote_string_for_target(target_name) -> str
27
28 Return a quoted form of the given target_name suitable for including in a
29 Makefile as a target name.
30 """
31
32 # The only quoting we currently perform is for ':', to support msys users.
33 return value.replace(":", "\\:")
34
Daniel Dunbar195c6f32011-11-05 04:07:49 +000035def make_install_dir(path):
36 """
37 make_install_dir(path) -> None
38
39 Create the given directory path for installation, including any parents.
40 """
41
42 # os.makedirs considers it an error to be called with an existant path.
43 if not os.path.exists(path):
44 os.makedirs(path)
45
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000046###
47
Daniel Dunbardf578252011-11-03 17:56:06 +000048class LLVMProjectInfo(object):
49 @staticmethod
50 def load_infos_from_path(llvmbuild_source_root):
51 # FIXME: Implement a simple subpath file list cache, so we don't restat
52 # directories we have already traversed.
53
54 # First, discover all the LLVMBuild.txt files.
Daniel Dunbare10233b2011-11-03 19:45:52 +000055 #
56 # FIXME: We would like to use followlinks=True here, but that isn't
57 # compatible with Python 2.4. Instead, we will either have to special
58 # case projects we would expect to possibly be linked to, or implement
59 # our own walk that can follow links. For now, it doesn't matter since
60 # we haven't picked up the LLVMBuild system in any other LLVM projects.
61 for dirpath,dirnames,filenames in os.walk(llvmbuild_source_root):
Daniel Dunbardf578252011-11-03 17:56:06 +000062 # If there is no LLVMBuild.txt file in a directory, we don't recurse
63 # past it. This is a simple way to prune our search, although it
64 # makes it easy for users to add LLVMBuild.txt files in places they
65 # won't be seen.
66 if 'LLVMBuild.txt' not in filenames:
67 del dirnames[:]
68 continue
69
70 # Otherwise, load the LLVMBuild file in this directory.
71 assert dirpath.startswith(llvmbuild_source_root)
72 subpath = '/' + dirpath[len(llvmbuild_source_root)+1:]
73 llvmbuild_path = os.path.join(dirpath, 'LLVMBuild.txt')
74 for info in componentinfo.load_from_path(llvmbuild_path, subpath):
75 yield info
76
77 @staticmethod
78 def load_from_path(source_root, llvmbuild_source_root):
79 infos = list(
80 LLVMProjectInfo.load_infos_from_path(llvmbuild_source_root))
81
82 return LLVMProjectInfo(source_root, infos)
83
84 def __init__(self, source_root, component_infos):
Daniel Dunbar1cf14af2011-11-03 17:56:12 +000085 # Store our simple ivars.
Daniel Dunbardf578252011-11-03 17:56:06 +000086 self.source_root = source_root
Daniel Dunbarb4eaee72011-11-10 00:49:58 +000087 self.component_infos = list(component_infos)
88 self.component_info_map = None
89 self.ordered_component_infos = None
90
91 def validate_components(self):
92 """validate_components() -> None
93
94 Validate that the project components are well-defined. Among other
95 things, this checks that:
96 - Components have valid references.
97 - Components references do not form cycles.
98
99 We also construct the map from component names to info, and the
100 topological ordering of components.
101 """
Daniel Dunbardf578252011-11-03 17:56:06 +0000102
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000103 # Create the component info map and validate that component names are
104 # unique.
105 self.component_info_map = {}
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000106 for ci in self.component_infos:
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000107 existing = self.component_info_map.get(ci.name)
108 if existing is not None:
109 # We found a duplicate component name, report it and error out.
110 fatal("found duplicate component %r (at %r and %r)" % (
111 ci.name, ci.subpath, existing.subpath))
112 self.component_info_map[ci.name] = ci
113
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000114 # Disallow 'all' as a component name, which is a special case.
115 if 'all' in self.component_info_map:
116 fatal("project is not allowed to define 'all' component")
117
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000118 # Add the root component.
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000119 if '$ROOT' in self.component_info_map:
120 fatal("project is not allowed to define $ROOT component")
121 self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo(
122 '/', '$ROOT', None)
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000123 self.component_infos.append(self.component_info_map['$ROOT'])
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000124
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000125 # Topologically order the component information according to their
126 # component references.
127 def visit_component_info(ci, current_stack, current_set):
128 # Check for a cycles.
129 if ci in current_set:
130 # We found a cycle, report it and error out.
131 cycle_description = ' -> '.join(
132 '%r (%s)' % (ci.name, relation)
133 for relation,ci in current_stack)
134 fatal("found cycle to %r after following: %s -> %s" % (
135 ci.name, cycle_description, ci.name))
136
137 # If we have already visited this item, we are done.
138 if ci not in components_to_visit:
139 return
140
141 # Otherwise, mark the component info as visited and traverse.
142 components_to_visit.remove(ci)
143
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000144 # Validate the parent reference, which we treat specially.
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000145 if ci.parent is not None:
146 parent = self.component_info_map.get(ci.parent)
147 if parent is None:
148 fatal("component %r has invalid reference %r (via %r)" % (
149 ci.name, ci.parent, 'parent'))
150 ci.set_parent_instance(parent)
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000151
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000152 for relation,referent_name in ci.get_component_references():
153 # Validate that the reference is ok.
154 referent = self.component_info_map.get(referent_name)
155 if referent is None:
156 fatal("component %r has invalid reference %r (via %r)" % (
157 ci.name, referent_name, relation))
158
159 # Visit the reference.
160 current_stack.append((relation,ci))
161 current_set.add(ci)
162 visit_component_info(referent, current_stack, current_set)
163 current_set.remove(ci)
164 current_stack.pop()
165
166 # Finally, add the component info to the ordered list.
167 self.ordered_component_infos.append(ci)
168
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000169 # FIXME: We aren't actually correctly checking for cycles along the
170 # parent edges. Haven't decided how I want to handle this -- I thought
171 # about only checking cycles by relation type. If we do that, it falls
172 # out easily. If we don't, we should special case the check.
173
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000174 self.ordered_component_infos = []
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000175 components_to_visit = set(self.component_infos)
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000176 while components_to_visit:
177 visit_component_info(iter(components_to_visit).next(), [], set())
178
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000179 # Canonicalize children lists.
180 for c in self.ordered_component_infos:
181 c.children.sort(key = lambda c: c.name)
182
183 def print_tree(self):
184 def visit(node, depth = 0):
185 print '%s%-40s (%s)' % (' '*depth, node.name, node.type_name)
186 for c in node.children:
187 visit(c, depth + 1)
188 visit(self.component_info_map['$ROOT'])
189
Daniel Dunbar43120df2011-11-03 17:56:21 +0000190 def write_components(self, output_path):
191 # Organize all the components by the directory their LLVMBuild file
192 # should go in.
193 info_basedir = {}
194 for ci in self.component_infos:
195 # Ignore the $ROOT component.
196 if ci.parent is None:
197 continue
198
199 info_basedir[ci.subpath] = info_basedir.get(ci.subpath, []) + [ci]
200
201 # Generate the build files.
202 for subpath, infos in info_basedir.items():
203 # Order the components by name to have a canonical ordering.
204 infos.sort(key = lambda ci: ci.name)
205
206 # Format the components into llvmbuild fragments.
207 fragments = filter(None, [ci.get_llvmbuild_fragment()
208 for ci in infos])
209 if not fragments:
210 continue
211
212 assert subpath.startswith('/')
213 directory_path = os.path.join(output_path, subpath[1:])
214
215 # Create the directory if it does not already exist.
216 if not os.path.exists(directory_path):
217 os.makedirs(directory_path)
218
219 # Create the LLVMBuild file.
220 file_path = os.path.join(directory_path, 'LLVMBuild.txt')
221 f = open(file_path, "w")
Daniel Dunbarfb6d79a2011-11-03 17:56:31 +0000222
223 # Write the header.
224 header_fmt = ';===- %s %s-*- Conf -*--===;'
225 header_name = '.' + os.path.join(subpath, 'LLVMBuild.txt')
226 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
227 header_string = header_fmt % (header_name, header_pad)
228 print >>f, """\
229%s
230;
231; The LLVM Compiler Infrastructure
232;
233; This file is distributed under the University of Illinois Open Source
234; License. See LICENSE.TXT for details.
235;
236;===------------------------------------------------------------------------===;
237;
238; This is an LLVMBuild description file for the components in this subdirectory.
239;
240; For more information on the LLVMBuild system, please see:
241;
242; http://llvm.org/docs/LLVMBuild.html
243;
244;===------------------------------------------------------------------------===;
245""" % header_string
246
Daniel Dunbar43120df2011-11-03 17:56:21 +0000247 for i,fragment in enumerate(fragments):
248 print >>f, '[component_%d]' % i
249 f.write(fragment)
250 print >>f
251 f.close()
252
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000253 def write_library_table(self, output_path):
254 # Write out the mapping from component names to required libraries.
255 #
256 # We do this in topological order so that we know we can append the
257 # dependencies for added library groups.
258 entries = {}
259 for c in self.ordered_component_infos:
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000260 # Only certain components are in the table.
261 if c.type_name not in ('Library', 'LibraryGroup', 'TargetGroup'):
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000262 continue
263
264 # Compute the llvm-config "component name". For historical reasons,
265 # this is lowercased based on the library name.
266 llvmconfig_component_name = c.get_llvmconfig_component_name()
267
268 # Get the library name, or None for LibraryGroups.
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000269 if c.type_name == 'Library':
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000270 library_name = c.get_library_name()
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000271 else:
272 library_name = None
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000273
274 # Get the component names of all the required libraries.
275 required_llvmconfig_component_names = [
276 self.component_info_map[dep].get_llvmconfig_component_name()
277 for dep in c.required_libraries]
278
279 # Insert the entries for library groups we should add to.
280 for dep in c.add_to_library_groups:
281 entries[dep][2].append(llvmconfig_component_name)
282
283 # Add the entry.
284 entries[c.name] = (llvmconfig_component_name, library_name,
285 required_llvmconfig_component_names)
286
287 # Convert to a list of entries and sort by name.
288 entries = entries.values()
289
290 # Create an 'all' pseudo component. We keep the dependency list small by
291 # only listing entries that have no other dependents.
292 root_entries = set(e[0] for e in entries)
293 for _,_,deps in entries:
294 root_entries -= set(deps)
295 entries.append(('all', None, root_entries))
296
297 entries.sort()
298
299 # Compute the maximum number of required libraries, plus one so there is
300 # always a sentinel.
301 max_required_libraries = max(len(deps)
302 for _,_,deps in entries) + 1
303
304 # Write out the library table.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000305 make_install_dir(os.path.dirname(output_path))
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000306 f = open(output_path, 'w')
307 print >>f, """\
308//===- llvm-build generated file --------------------------------*- C++ -*-===//
309//
310// Component Library Depenedency Table
311//
312// Automatically generated file, do not edit!
313//
314//===----------------------------------------------------------------------===//
315"""
316 print >>f, 'struct AvailableComponent {'
317 print >>f, ' /// The name of the component.'
318 print >>f, ' const char *Name;'
319 print >>f, ''
320 print >>f, ' /// The name of the library for this component (or NULL).'
321 print >>f, ' const char *Library;'
322 print >>f, ''
323 print >>f, '\
324 /// The list of libraries required when linking this component.'
325 print >>f, ' const char *RequiredLibraries[%d];' % (
326 max_required_libraries)
327 print >>f, '} AvailableComponents[%d] = {' % len(entries)
328 for name,library_name,required_names in entries:
329 if library_name is None:
330 library_name_as_cstr = '0'
331 else:
332 # If we had a project level component, we could derive the
333 # library prefix.
334 library_name_as_cstr = '"libLLVM%s.a"' % library_name
335 print >>f, ' { "%s", %s, { %s } },' % (
336 name, library_name_as_cstr,
337 ', '.join('"%s"' % dep
338 for dep in required_names))
339 print >>f, '};'
340 f.close()
341
Daniel Dunbar16889612011-11-04 23:10:37 +0000342 def get_fragment_dependencies(self):
Daniel Dunbar02271a72011-11-03 22:46:19 +0000343 """
Daniel Dunbar16889612011-11-04 23:10:37 +0000344 get_fragment_dependencies() -> iter
Daniel Dunbar02271a72011-11-03 22:46:19 +0000345
Daniel Dunbar16889612011-11-04 23:10:37 +0000346 Compute the list of files (as absolute paths) on which the output
347 fragments depend (i.e., files for which a modification should trigger a
348 rebuild of the fragment).
Daniel Dunbar02271a72011-11-03 22:46:19 +0000349 """
350
351 # Construct a list of all the dependencies of the Makefile fragment
352 # itself. These include all the LLVMBuild files themselves, as well as
353 # all of our own sources.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000354 for ci in self.component_infos:
Daniel Dunbar16889612011-11-04 23:10:37 +0000355 yield os.path.join(self.source_root, ci.subpath[1:],
356 'LLVMBuild.txt')
Daniel Dunbar02271a72011-11-03 22:46:19 +0000357
358 # Gather the list of necessary sources by just finding all loaded
359 # modules that are inside the LLVM source tree.
360 for module in sys.modules.values():
361 # Find the module path.
362 if not hasattr(module, '__file__'):
363 continue
364 path = getattr(module, '__file__')
365 if not path:
366 continue
367
368 # Strip off any compiled suffix.
369 if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
370 path = path[:-1]
371
372 # If the path exists and is in the source tree, consider it a
373 # dependency.
374 if (path.startswith(self.source_root) and os.path.exists(path)):
Daniel Dunbar16889612011-11-04 23:10:37 +0000375 yield path
376
377 def write_cmake_fragment(self, output_path):
378 """
379 write_cmake_fragment(output_path) -> None
380
381 Generate a CMake fragment which includes all of the collated LLVMBuild
382 information in a format that is easily digestible by a CMake. The exact
383 contents of this are closely tied to how the CMake configuration
384 integrates LLVMBuild, see CMakeLists.txt in the top-level.
385 """
386
387 dependencies = list(self.get_fragment_dependencies())
388
389 # Write out the CMake fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000390 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar16889612011-11-04 23:10:37 +0000391 f = open(output_path, 'w')
392
393 # Write the header.
394 header_fmt = '\
395#===-- %s - LLVMBuild Configuration for LLVM %s-*- CMake -*--===#'
396 header_name = os.path.basename(output_path)
397 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
398 header_string = header_fmt % (header_name, header_pad)
399 print >>f, """\
400%s
401#
402# The LLVM Compiler Infrastructure
403#
404# This file is distributed under the University of Illinois Open Source
405# License. See LICENSE.TXT for details.
406#
407#===------------------------------------------------------------------------===#
408#
409# This file contains the LLVMBuild project information in a format easily
410# consumed by the CMake based build system.
411#
412# This file is autogenerated by llvm-build, do not edit!
413#
414#===------------------------------------------------------------------------===#
415""" % header_string
416
417 # Write the dependency information in the best way we can.
418 print >>f, """
419# LLVMBuild CMake fragment dependencies.
420#
421# CMake has no builtin way to declare that the configuration depends on
422# a particular file. However, a side effect of configure_file is to add
423# said input file to CMake's internal dependency list. So, we use that
424# and a dummy output file to communicate the dependency information to
425# CMake.
426#
427# FIXME: File a CMake RFE to get a properly supported version of this
428# feature."""
429 for dep in dependencies:
430 print >>f, """\
431configure_file(\"%s\"
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000432 ${CMAKE_CURRENT_BINARY_DIR}/DummyConfigureOutput)""" % (
433 cmake_quote_string(dep),)
434
Daniel Dunbar16889612011-11-04 23:10:37 +0000435 f.close()
436
437 def write_make_fragment(self, output_path):
438 """
439 write_make_fragment(output_path) -> None
440
441 Generate a Makefile fragment which includes all of the collated
442 LLVMBuild information in a format that is easily digestible by a
443 Makefile. The exact contents of this are closely tied to how the LLVM
444 Makefiles integrate LLVMBuild, see Makefile.rules in the top-level.
445 """
446
447 dependencies = list(self.get_fragment_dependencies())
Daniel Dunbar02271a72011-11-03 22:46:19 +0000448
449 # Write out the Makefile fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000450 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar02271a72011-11-03 22:46:19 +0000451 f = open(output_path, 'w')
452
453 # Write the header.
454 header_fmt = '\
455#===-- %s - LLVMBuild Configuration for LLVM %s-*- Makefile -*--===#'
456 header_name = os.path.basename(output_path)
457 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
458 header_string = header_fmt % (header_name, header_pad)
459 print >>f, """\
460%s
461#
462# The LLVM Compiler Infrastructure
463#
464# This file is distributed under the University of Illinois Open Source
465# License. See LICENSE.TXT for details.
466#
467#===------------------------------------------------------------------------===#
468#
469# This file contains the LLVMBuild project information in a format easily
470# consumed by the Makefile based build system.
471#
472# This file is autogenerated by llvm-build, do not edit!
473#
474#===------------------------------------------------------------------------===#
475""" % header_string
476
477 # Write the dependencies for the fragment.
478 #
479 # FIXME: Technically, we need to properly quote for Make here.
480 print >>f, """\
481# Clients must explicitly enable LLVMBUILD_INCLUDE_DEPENDENCIES to get
482# these dependencies. This is a compromise to help improve the
483# performance of recursive Make systems."""
484 print >>f, 'ifeq ($(LLVMBUILD_INCLUDE_DEPENDENCIES),1)'
485 print >>f, "# The dependencies for this Makefile fragment itself."
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000486 print >>f, "%s: \\" % (mk_quote_string_for_target(output_path),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000487 for dep in dependencies:
488 print >>f, "\t%s \\" % (dep,)
489 print >>f
490
491 # Generate dummy rules for each of the dependencies, so that things
492 # continue to work correctly if any of those files are moved or removed.
493 print >>f, """\
494# The dummy targets to allow proper regeneration even when files are moved or
495# removed."""
496 for dep in dependencies:
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000497 print >>f, "%s:" % (mk_quote_string_for_target(dep),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000498 print >>f, 'endif'
499
500 f.close()
501
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000502def add_magic_target_components(parser, project, opts):
503 """add_magic_target_components(project, opts) -> None
504
505 Add the "magic" target based components to the project, which can only be
506 determined based on the target configuration options.
507
508 This currently is responsible for populating the required_libraries list of
Daniel Dunbar83337302011-11-10 01:16:48 +0000509 the "all-targets", "Native", "NativeCodeGen", and "Engine" components.
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000510 """
511
512 # Determine the available targets.
513 available_targets = dict((ci.name,ci)
514 for ci in project.component_infos
515 if ci.type_name == 'TargetGroup')
516
517 # Find the configured native target.
518
519 # We handle a few special cases of target names here for historical
520 # reasons, as these are the names configure currently comes up with.
521 native_target_name = { 'x86' : 'X86',
522 'x86_64' : 'X86',
523 'Unknown' : None }.get(opts.native_target,
524 opts.native_target)
525 if native_target_name is None:
526 native_target = None
527 else:
528 native_target = available_targets.get(native_target_name)
529 if native_target is None:
530 parser.error("invalid native target: %r (not in project)" % (
531 opts.native_target,))
532 if native_target.type_name != 'TargetGroup':
533 parser.error("invalid native target: %r (not a target)" % (
534 opts.native_target,))
535
536 # Find the list of targets to enable.
537 if opts.enable_targets is None:
538 enable_targets = available_targets.values()
539 else:
Daniel Dunbar83337302011-11-10 01:16:48 +0000540 # We support both space separated and semi-colon separated lists.
541 if ' ' in opts.enable_targets:
542 enable_target_names = opts.enable_targets.split()
543 else:
544 enable_target_names = opts.enable_targets.split(';')
545
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000546 enable_targets = []
Daniel Dunbar83337302011-11-10 01:16:48 +0000547 for name in enable_target_names:
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000548 target = available_targets.get(name)
549 if target is None:
550 parser.error("invalid target to enable: %r (not in project)" % (
551 name,))
552 if target.type_name != 'TargetGroup':
553 parser.error("invalid target to enable: %r (not a target)" % (
554 name,))
555 enable_targets.append(target)
556
557 # Find the special library groups we are going to populate. We enforce that
558 # these appear in the project (instead of just adding them) so that they at
559 # least have an explicit representation in the project LLVMBuild files (and
560 # comments explaining how they are populated).
561 def find_special_group(name):
562 info = info_map.get(name)
563 if info is None:
564 fatal("expected project to contain special %r component" % (
565 name,))
566
567 if info.type_name != 'LibraryGroup':
568 fatal("special component %r should be a LibraryGroup" % (
569 name,))
570
571 if info.required_libraries:
572 fatal("special component %r must have empty %r list" % (
573 name, 'required_libraries'))
574 if info.add_to_library_groups:
575 fatal("special component %r must have empty %r list" % (
576 name, 'add_to_library_groups'))
577
578 return info
579
580 info_map = dict((ci.name, ci) for ci in project.component_infos)
581 all_targets = find_special_group('all-targets')
582 native_group = find_special_group('Native')
583 native_codegen_group = find_special_group('NativeCodeGen')
584 engine_group = find_special_group('Engine')
585
586 # Set the enabled bit in all the target groups, and append to the
587 # all-targets list.
588 for ci in enable_targets:
589 all_targets.required_libraries.append(ci.name)
590 ci.enabled = True
591
592 # If we have a native target, then that defines the native and
593 # native_codegen libraries.
594 if native_target and native_target.enabled:
595 native_group.required_libraries.append(native_target.name)
596 native_codegen_group.required_libraries.append(
597 '%sCodeGen' % native_target.name)
598
599 # If we have a native target with a JIT, use that for the engine. Otherwise,
600 # use the interpreter.
601 if native_target and native_target.enabled and native_target.has_jit:
602 engine_group.required_libraries.append('JIT')
603 engine_group.required_libraries.append(native_group.name)
604 else:
605 engine_group.required_libraries.append('Interpreter')
606
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000607def main():
608 from optparse import OptionParser, OptionGroup
609 parser = OptionParser("usage: %prog [options]")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000610
611 group = OptionGroup(parser, "Input Options")
612 group.add_option("", "--source-root", dest="source_root", metavar="PATH",
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000613 help="Path to the LLVM source (inferred if not given)",
614 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000615 group.add_option("", "--llvmbuild-source-root",
616 dest="llvmbuild_source_root",
617 help=(
618 "If given, an alternate path to search for LLVMBuild.txt files"),
619 action="store", default=None, metavar="PATH")
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000620 group.add_option("", "--build-root", dest="build_root", metavar="PATH",
621 help="Path to the build directory (if needed) [%default]",
622 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000623 parser.add_option_group(group)
624
625 group = OptionGroup(parser, "Output Options")
626 group.add_option("", "--print-tree", dest="print_tree",
627 help="Print out the project component tree [%default]",
628 action="store_true", default=False)
629 group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
Daniel Dunbar43120df2011-11-03 17:56:21 +0000630 help="Write out the LLVMBuild.txt files to PATH",
631 action="store", default=None, metavar="PATH")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000632 group.add_option("", "--write-library-table",
633 dest="write_library_table", metavar="PATH",
634 help="Write the C++ library dependency table to PATH",
635 action="store", default=None)
636 group.add_option("", "--write-cmake-fragment",
637 dest="write_cmake_fragment", metavar="PATH",
638 help="Write the CMake project information to PATH",
639 action="store", default=None)
640 group.add_option("", "--write-make-fragment",
Daniel Dunbar02271a72011-11-03 22:46:19 +0000641 dest="write_make_fragment", metavar="PATH",
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000642 help="Write the Makefile project information to PATH",
643 action="store", default=None)
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000644 group.add_option("", "--configure-target-def-file",
645 dest="configure_target_def_files",
646 help="""Configure the given file at SUBPATH (relative to
647the inferred or given source root, and with a '.in' suffix) by replacing certain
648substitution variables with lists of targets that support certain features (for
649example, targets with AsmPrinters) and write the result to the build root (as
650given by --build-root) at the same SUBPATH""",
651 metavar="SUBPATH", action="append", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000652 parser.add_option_group(group)
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000653
654 group = OptionGroup(parser, "Configuration Options")
655 group.add_option("", "--native-target",
656 dest="native_target", metavar="NAME",
657 help=("Treat the named target as the 'native' one, if "
658 "given [%default]"),
659 action="store", default=None)
660 group.add_option("", "--enable-targets",
661 dest="enable_targets", metavar="NAMES",
Daniel Dunbar83337302011-11-10 01:16:48 +0000662 help=("Enable the given space or semi-colon separated "
663 "list of targets, or all targets if not present"),
Daniel Dunbar02271a72011-11-03 22:46:19 +0000664 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000665 parser.add_option_group(group)
666
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000667 (opts, args) = parser.parse_args()
668
669 # Determine the LLVM source path, if not given.
670 source_root = opts.source_root
671 if source_root:
672 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
673 'Function.cpp')):
674 parser.error('invalid LLVM source root: %r' % source_root)
675 else:
676 llvmbuild_path = os.path.dirname(__file__)
677 llvm_build_path = os.path.dirname(llvmbuild_path)
678 utils_path = os.path.dirname(llvm_build_path)
679 source_root = os.path.dirname(utils_path)
680 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
681 'Function.cpp')):
682 parser.error('unable to infer LLVM source root, please specify')
683
Daniel Dunbardf578252011-11-03 17:56:06 +0000684 # Construct the LLVM project information.
685 llvmbuild_source_root = opts.llvmbuild_source_root or source_root
686 project_info = LLVMProjectInfo.load_from_path(
687 source_root, llvmbuild_source_root)
688
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000689 # Add the magic target based components.
690 add_magic_target_components(parser, project_info, opts)
691
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000692 # Validate the project component info.
693 project_info.validate_components()
694
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000695 # Print the component tree, if requested.
696 if opts.print_tree:
697 project_info.print_tree()
698
Daniel Dunbar43120df2011-11-03 17:56:21 +0000699 # Write out the components, if requested. This is useful for auto-upgrading
700 # the schema.
701 if opts.write_llvmbuild:
702 project_info.write_components(opts.write_llvmbuild)
703
Daniel Dunbar16889612011-11-04 23:10:37 +0000704 # Write out the required library table, if requested.
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000705 if opts.write_library_table:
706 project_info.write_library_table(opts.write_library_table)
707
Daniel Dunbar16889612011-11-04 23:10:37 +0000708 # Write out the make fragment, if requested.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000709 if opts.write_make_fragment:
710 project_info.write_make_fragment(opts.write_make_fragment)
711
Daniel Dunbar16889612011-11-04 23:10:37 +0000712 # Write out the cmake fragment, if requested.
713 if opts.write_cmake_fragment:
714 project_info.write_cmake_fragment(opts.write_cmake_fragment)
715
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000716 # Configure target definition files, if requested.
717 if opts.configure_target_def_files:
718 # Verify we were given a build root.
719 if not opts.build_root:
720 parser.error("must specify --build-root when using "
721 "--configure-target-def-file")
722
723 # Create the substitution list.
724 available_targets = [ci for ci in project_info.component_infos
725 if ci.type_name == 'TargetGroup']
726 substitutions = [
727 ("@LLVM_ENUM_TARGETS@",
728 ' '.join('LLVM_TARGET(%s)' % ci.name
729 for ci in available_targets)),
730 ("@LLVM_ENUM_ASM_PRINTERS@",
731 ' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
732 for ci in available_targets
733 if ci.has_asmprinter)),
734 ("@LLVM_ENUM_ASM_PARSERS@",
735 ' '.join('LLVM_ASM_PARSER(%s)' % ci.name
736 for ci in available_targets
737 if ci.has_asmparser)),
738 ("@LLVM_ENUM_DISASSEMBLERS@",
739 ' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
740 for ci in available_targets
741 if ci.has_disassembler))]
742
743 # Configure the given files.
744 for subpath in opts.configure_target_def_files:
745 inpath = os.path.join(source_root, subpath + '.in')
746 outpath = os.path.join(opts.build_root, subpath)
747 result = configutil.configure_file(inpath, outpath, substitutions)
748 if not result:
749 note("configured file %r hasn't changed" % outpath)
750
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000751if __name__=='__main__':
752 main()