blob: 71e11d79cff4e4f2af5869e5760682d1b12ac4f4 [file] [log] [blame]
Daniel Dunbara3217162011-12-12 22:45:35 +00001import StringIO
Daniel Dunbarad5e0122011-11-03 17:56:03 +00002import os
Daniel Dunbar1cf14af2011-11-03 17:56:12 +00003import sys
Daniel Dunbarad5e0122011-11-03 17:56:03 +00004
Daniel Dunbardf578252011-11-03 17:56:06 +00005import componentinfo
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +00006import configutil
Daniel Dunbardf578252011-11-03 17:56:06 +00007
Daniel Dunbar1cf14af2011-11-03 17:56:12 +00008from util import *
9
10###
11
Daniel Dunbar57574fa2011-11-05 04:07:43 +000012def cmake_quote_string(value):
13 """
14 cmake_quote_string(value) -> str
15
16 Return a quoted form of the given value that is suitable for use in CMake
17 language files.
18 """
19
20 # Currently, we only handle escaping backslashes.
21 value = value.replace("\\", "\\\\")
22
23 return value
24
Daniel Dunbard5889d82011-11-17 01:19:53 +000025def cmake_quote_path(value):
26 """
27 cmake_quote_path(value) -> str
28
29 Return a quoted form of the given value that is suitable for use in CMake
30 language files.
31 """
32
33 # CMake has a bug in it's Makefile generator that doesn't properly quote
34 # strings it generates. So instead of using proper quoting, we just use "/"
35 # style paths. Currently, we only handle escaping backslashes.
36 value = value.replace("\\", "/")
37
38 return value
39
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000040def mk_quote_string_for_target(value):
41 """
42 mk_quote_string_for_target(target_name) -> str
43
44 Return a quoted form of the given target_name suitable for including in a
45 Makefile as a target name.
46 """
47
48 # The only quoting we currently perform is for ':', to support msys users.
49 return value.replace(":", "\\:")
50
Daniel Dunbar195c6f32011-11-05 04:07:49 +000051def make_install_dir(path):
52 """
53 make_install_dir(path) -> None
54
55 Create the given directory path for installation, including any parents.
56 """
57
58 # os.makedirs considers it an error to be called with an existant path.
59 if not os.path.exists(path):
60 os.makedirs(path)
61
Daniel Dunbar20fb32b2011-11-04 23:40:11 +000062###
63
Daniel Dunbardf578252011-11-03 17:56:06 +000064class LLVMProjectInfo(object):
65 @staticmethod
66 def load_infos_from_path(llvmbuild_source_root):
67 # FIXME: Implement a simple subpath file list cache, so we don't restat
68 # directories we have already traversed.
69
70 # First, discover all the LLVMBuild.txt files.
Daniel Dunbare10233b2011-11-03 19:45:52 +000071 #
72 # FIXME: We would like to use followlinks=True here, but that isn't
73 # compatible with Python 2.4. Instead, we will either have to special
74 # case projects we would expect to possibly be linked to, or implement
75 # our own walk that can follow links. For now, it doesn't matter since
76 # we haven't picked up the LLVMBuild system in any other LLVM projects.
77 for dirpath,dirnames,filenames in os.walk(llvmbuild_source_root):
Daniel Dunbardf578252011-11-03 17:56:06 +000078 # If there is no LLVMBuild.txt file in a directory, we don't recurse
79 # past it. This is a simple way to prune our search, although it
80 # makes it easy for users to add LLVMBuild.txt files in places they
81 # won't be seen.
82 if 'LLVMBuild.txt' not in filenames:
83 del dirnames[:]
84 continue
85
86 # Otherwise, load the LLVMBuild file in this directory.
87 assert dirpath.startswith(llvmbuild_source_root)
88 subpath = '/' + dirpath[len(llvmbuild_source_root)+1:]
89 llvmbuild_path = os.path.join(dirpath, 'LLVMBuild.txt')
90 for info in componentinfo.load_from_path(llvmbuild_path, subpath):
91 yield info
92
93 @staticmethod
94 def load_from_path(source_root, llvmbuild_source_root):
95 infos = list(
96 LLVMProjectInfo.load_infos_from_path(llvmbuild_source_root))
97
98 return LLVMProjectInfo(source_root, infos)
99
100 def __init__(self, source_root, component_infos):
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000101 # Store our simple ivars.
Daniel Dunbardf578252011-11-03 17:56:06 +0000102 self.source_root = source_root
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000103 self.component_infos = list(component_infos)
104 self.component_info_map = None
105 self.ordered_component_infos = None
106
107 def validate_components(self):
108 """validate_components() -> None
109
110 Validate that the project components are well-defined. Among other
111 things, this checks that:
112 - Components have valid references.
113 - Components references do not form cycles.
114
115 We also construct the map from component names to info, and the
116 topological ordering of components.
117 """
Daniel Dunbardf578252011-11-03 17:56:06 +0000118
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000119 # Create the component info map and validate that component names are
120 # unique.
121 self.component_info_map = {}
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000122 for ci in self.component_infos:
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000123 existing = self.component_info_map.get(ci.name)
124 if existing is not None:
125 # We found a duplicate component name, report it and error out.
126 fatal("found duplicate component %r (at %r and %r)" % (
127 ci.name, ci.subpath, existing.subpath))
128 self.component_info_map[ci.name] = ci
129
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000130 # Disallow 'all' as a component name, which is a special case.
131 if 'all' in self.component_info_map:
132 fatal("project is not allowed to define 'all' component")
133
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000134 # Add the root component.
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000135 if '$ROOT' in self.component_info_map:
136 fatal("project is not allowed to define $ROOT component")
137 self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo(
138 '/', '$ROOT', None)
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000139 self.component_infos.append(self.component_info_map['$ROOT'])
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000140
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000141 # Topologically order the component information according to their
142 # component references.
143 def visit_component_info(ci, current_stack, current_set):
144 # Check for a cycles.
145 if ci in current_set:
146 # We found a cycle, report it and error out.
147 cycle_description = ' -> '.join(
148 '%r (%s)' % (ci.name, relation)
149 for relation,ci in current_stack)
150 fatal("found cycle to %r after following: %s -> %s" % (
151 ci.name, cycle_description, ci.name))
152
153 # If we have already visited this item, we are done.
154 if ci not in components_to_visit:
155 return
156
157 # Otherwise, mark the component info as visited and traverse.
158 components_to_visit.remove(ci)
159
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000160 # Validate the parent reference, which we treat specially.
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000161 if ci.parent is not None:
162 parent = self.component_info_map.get(ci.parent)
163 if parent is None:
164 fatal("component %r has invalid reference %r (via %r)" % (
165 ci.name, ci.parent, 'parent'))
166 ci.set_parent_instance(parent)
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000167
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000168 for relation,referent_name in ci.get_component_references():
169 # Validate that the reference is ok.
170 referent = self.component_info_map.get(referent_name)
171 if referent is None:
172 fatal("component %r has invalid reference %r (via %r)" % (
173 ci.name, referent_name, relation))
174
175 # Visit the reference.
176 current_stack.append((relation,ci))
177 current_set.add(ci)
178 visit_component_info(referent, current_stack, current_set)
179 current_set.remove(ci)
180 current_stack.pop()
181
182 # Finally, add the component info to the ordered list.
183 self.ordered_component_infos.append(ci)
184
Daniel Dunbar86c119a2011-11-03 17:56:16 +0000185 # FIXME: We aren't actually correctly checking for cycles along the
186 # parent edges. Haven't decided how I want to handle this -- I thought
187 # about only checking cycles by relation type. If we do that, it falls
188 # out easily. If we don't, we should special case the check.
189
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000190 self.ordered_component_infos = []
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000191 components_to_visit = set(self.component_infos)
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000192 while components_to_visit:
193 visit_component_info(iter(components_to_visit).next(), [], set())
194
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000195 # Canonicalize children lists.
196 for c in self.ordered_component_infos:
197 c.children.sort(key = lambda c: c.name)
198
199 def print_tree(self):
200 def visit(node, depth = 0):
201 print '%s%-40s (%s)' % (' '*depth, node.name, node.type_name)
202 for c in node.children:
203 visit(c, depth + 1)
204 visit(self.component_info_map['$ROOT'])
205
Daniel Dunbar43120df2011-11-03 17:56:21 +0000206 def write_components(self, output_path):
207 # Organize all the components by the directory their LLVMBuild file
208 # should go in.
209 info_basedir = {}
210 for ci in self.component_infos:
211 # Ignore the $ROOT component.
212 if ci.parent is None:
213 continue
214
215 info_basedir[ci.subpath] = info_basedir.get(ci.subpath, []) + [ci]
216
217 # Generate the build files.
218 for subpath, infos in info_basedir.items():
219 # Order the components by name to have a canonical ordering.
220 infos.sort(key = lambda ci: ci.name)
221
222 # Format the components into llvmbuild fragments.
223 fragments = filter(None, [ci.get_llvmbuild_fragment()
224 for ci in infos])
225 if not fragments:
226 continue
227
228 assert subpath.startswith('/')
229 directory_path = os.path.join(output_path, subpath[1:])
230
231 # Create the directory if it does not already exist.
232 if not os.path.exists(directory_path):
233 os.makedirs(directory_path)
234
Daniel Dunbara3217162011-12-12 22:45:35 +0000235 # In an effort to preserve comments (which aren't parsed), read in
236 # the original file and extract the comments. We only know how to
237 # associate comments that prefix a section name.
238 f = open(infos[0]._source_path)
239 comments_map = {}
240 comment_block = ""
241 for ln in f:
242 if ln.startswith(';'):
243 comment_block += ln
244 elif ln.startswith('[') and ln.endswith(']\n'):
245 comments_map[ln[:-1]] = comment_block
246 else:
247 comment_block = ""
248 f.close()
249
250 # Create the LLVMBuild fil[e.
Daniel Dunbar43120df2011-11-03 17:56:21 +0000251 file_path = os.path.join(directory_path, 'LLVMBuild.txt')
252 f = open(file_path, "w")
Daniel Dunbarfb6d79a2011-11-03 17:56:31 +0000253
254 # Write the header.
255 header_fmt = ';===- %s %s-*- Conf -*--===;'
256 header_name = '.' + os.path.join(subpath, 'LLVMBuild.txt')
257 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
258 header_string = header_fmt % (header_name, header_pad)
259 print >>f, """\
260%s
261;
262; The LLVM Compiler Infrastructure
263;
264; This file is distributed under the University of Illinois Open Source
265; License. See LICENSE.TXT for details.
266;
267;===------------------------------------------------------------------------===;
268;
269; This is an LLVMBuild description file for the components in this subdirectory.
270;
271; For more information on the LLVMBuild system, please see:
272;
273; http://llvm.org/docs/LLVMBuild.html
274;
275;===------------------------------------------------------------------------===;
276""" % header_string
277
Daniel Dunbar43120df2011-11-03 17:56:21 +0000278 for i,fragment in enumerate(fragments):
Daniel Dunbara3217162011-12-12 22:45:35 +0000279 name = '[component_%d]' % i
280 comment = comments_map.get(name)
281 if comment is not None:
282 f.write(comment)
283 print >>f, name
Daniel Dunbar43120df2011-11-03 17:56:21 +0000284 f.write(fragment)
Daniel Dunbar4ab406d2011-12-12 19:48:00 +0000285 if fragment is not fragments[-1]:
286 print >>f
Daniel Dunbar43120df2011-11-03 17:56:21 +0000287 f.close()
288
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000289 def write_library_table(self, output_path):
290 # Write out the mapping from component names to required libraries.
291 #
292 # We do this in topological order so that we know we can append the
293 # dependencies for added library groups.
294 entries = {}
295 for c in self.ordered_component_infos:
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000296 # Only certain components are in the table.
297 if c.type_name not in ('Library', 'LibraryGroup', 'TargetGroup'):
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000298 continue
299
300 # Compute the llvm-config "component name". For historical reasons,
301 # this is lowercased based on the library name.
302 llvmconfig_component_name = c.get_llvmconfig_component_name()
303
304 # Get the library name, or None for LibraryGroups.
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000305 if c.type_name == 'Library':
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000306 library_name = c.get_library_name()
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000307 else:
308 library_name = None
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000309
310 # Get the component names of all the required libraries.
311 required_llvmconfig_component_names = [
312 self.component_info_map[dep].get_llvmconfig_component_name()
313 for dep in c.required_libraries]
314
315 # Insert the entries for library groups we should add to.
316 for dep in c.add_to_library_groups:
317 entries[dep][2].append(llvmconfig_component_name)
318
319 # Add the entry.
320 entries[c.name] = (llvmconfig_component_name, library_name,
321 required_llvmconfig_component_names)
322
323 # Convert to a list of entries and sort by name.
324 entries = entries.values()
325
326 # Create an 'all' pseudo component. We keep the dependency list small by
327 # only listing entries that have no other dependents.
328 root_entries = set(e[0] for e in entries)
329 for _,_,deps in entries:
330 root_entries -= set(deps)
331 entries.append(('all', None, root_entries))
332
333 entries.sort()
334
335 # Compute the maximum number of required libraries, plus one so there is
336 # always a sentinel.
337 max_required_libraries = max(len(deps)
338 for _,_,deps in entries) + 1
339
340 # Write out the library table.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000341 make_install_dir(os.path.dirname(output_path))
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000342 f = open(output_path, 'w')
343 print >>f, """\
344//===- llvm-build generated file --------------------------------*- C++ -*-===//
345//
346// Component Library Depenedency Table
347//
348// Automatically generated file, do not edit!
349//
350//===----------------------------------------------------------------------===//
351"""
352 print >>f, 'struct AvailableComponent {'
353 print >>f, ' /// The name of the component.'
354 print >>f, ' const char *Name;'
355 print >>f, ''
356 print >>f, ' /// The name of the library for this component (or NULL).'
357 print >>f, ' const char *Library;'
358 print >>f, ''
359 print >>f, '\
360 /// The list of libraries required when linking this component.'
361 print >>f, ' const char *RequiredLibraries[%d];' % (
362 max_required_libraries)
363 print >>f, '} AvailableComponents[%d] = {' % len(entries)
364 for name,library_name,required_names in entries:
365 if library_name is None:
366 library_name_as_cstr = '0'
367 else:
368 # If we had a project level component, we could derive the
369 # library prefix.
370 library_name_as_cstr = '"libLLVM%s.a"' % library_name
371 print >>f, ' { "%s", %s, { %s } },' % (
372 name, library_name_as_cstr,
373 ', '.join('"%s"' % dep
374 for dep in required_names))
375 print >>f, '};'
376 f.close()
377
Daniel Dunbar5086de62011-11-29 00:06:50 +0000378 def get_required_libraries_for_component(self, ci, traverse_groups = False):
379 """
380 get_required_libraries_for_component(component_info) -> iter
381
382 Given a Library component info descriptor, return an iterator over all
383 of the directly required libraries for linking with this component. If
384 traverse_groups is True, then library and target groups will be
385 traversed to include their required libraries.
386 """
387
388 assert ci.type_name in ('Library', 'LibraryGroup', 'TargetGroup')
389
390 for name in ci.required_libraries:
391 # Get the dependency info.
392 dep = self.component_info_map[name]
393
394 # If it is a library, yield it.
395 if dep.type_name == 'Library':
396 yield dep
397 continue
398
399 # Otherwise if it is a group, yield or traverse depending on what
400 # was requested.
401 if dep.type_name in ('LibraryGroup', 'TargetGroup'):
402 if not traverse_groups:
403 yield dep
404 continue
405
406 for res in self.get_required_libraries_for_component(dep, True):
407 yield res
408
Daniel Dunbar16889612011-11-04 23:10:37 +0000409 def get_fragment_dependencies(self):
Daniel Dunbar02271a72011-11-03 22:46:19 +0000410 """
Daniel Dunbar16889612011-11-04 23:10:37 +0000411 get_fragment_dependencies() -> iter
Daniel Dunbar02271a72011-11-03 22:46:19 +0000412
Daniel Dunbar16889612011-11-04 23:10:37 +0000413 Compute the list of files (as absolute paths) on which the output
414 fragments depend (i.e., files for which a modification should trigger a
415 rebuild of the fragment).
Daniel Dunbar02271a72011-11-03 22:46:19 +0000416 """
417
418 # Construct a list of all the dependencies of the Makefile fragment
419 # itself. These include all the LLVMBuild files themselves, as well as
420 # all of our own sources.
Daniel Dunbar309fc862011-12-06 23:13:42 +0000421 #
422 # Many components may come from the same file, so we make sure to unique
423 # these.
424 build_paths = set()
Daniel Dunbar02271a72011-11-03 22:46:19 +0000425 for ci in self.component_infos:
Daniel Dunbar309fc862011-12-06 23:13:42 +0000426 p = os.path.join(self.source_root, ci.subpath[1:], 'LLVMBuild.txt')
427 if p not in build_paths:
428 yield p
429 build_paths.add(p)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000430
431 # Gather the list of necessary sources by just finding all loaded
432 # modules that are inside the LLVM source tree.
433 for module in sys.modules.values():
434 # Find the module path.
435 if not hasattr(module, '__file__'):
436 continue
437 path = getattr(module, '__file__')
438 if not path:
439 continue
440
441 # Strip off any compiled suffix.
442 if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
443 path = path[:-1]
444
445 # If the path exists and is in the source tree, consider it a
446 # dependency.
447 if (path.startswith(self.source_root) and os.path.exists(path)):
Daniel Dunbar16889612011-11-04 23:10:37 +0000448 yield path
449
450 def write_cmake_fragment(self, output_path):
451 """
452 write_cmake_fragment(output_path) -> None
453
454 Generate a CMake fragment which includes all of the collated LLVMBuild
455 information in a format that is easily digestible by a CMake. The exact
456 contents of this are closely tied to how the CMake configuration
457 integrates LLVMBuild, see CMakeLists.txt in the top-level.
458 """
459
460 dependencies = list(self.get_fragment_dependencies())
461
462 # Write out the CMake fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000463 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar16889612011-11-04 23:10:37 +0000464 f = open(output_path, 'w')
465
466 # Write the header.
467 header_fmt = '\
468#===-- %s - LLVMBuild Configuration for LLVM %s-*- CMake -*--===#'
469 header_name = os.path.basename(output_path)
470 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
471 header_string = header_fmt % (header_name, header_pad)
472 print >>f, """\
473%s
474#
475# The LLVM Compiler Infrastructure
476#
477# This file is distributed under the University of Illinois Open Source
478# License. See LICENSE.TXT for details.
479#
480#===------------------------------------------------------------------------===#
481#
482# This file contains the LLVMBuild project information in a format easily
483# consumed by the CMake based build system.
484#
485# This file is autogenerated by llvm-build, do not edit!
486#
487#===------------------------------------------------------------------------===#
488""" % header_string
489
490 # Write the dependency information in the best way we can.
491 print >>f, """
492# LLVMBuild CMake fragment dependencies.
493#
494# CMake has no builtin way to declare that the configuration depends on
495# a particular file. However, a side effect of configure_file is to add
496# said input file to CMake's internal dependency list. So, we use that
497# and a dummy output file to communicate the dependency information to
498# CMake.
499#
500# FIXME: File a CMake RFE to get a properly supported version of this
501# feature."""
502 for dep in dependencies:
503 print >>f, """\
504configure_file(\"%s\"
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000505 ${CMAKE_CURRENT_BINARY_DIR}/DummyConfigureOutput)""" % (
Daniel Dunbard5889d82011-11-17 01:19:53 +0000506 cmake_quote_path(dep),)
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000507
Daniel Dunbar5086de62011-11-29 00:06:50 +0000508 # Write the properties we use to encode the required library dependency
509 # information in a form CMake can easily use directly.
510 print >>f, """
511# Explicit library dependency information.
512#
513# The following property assignments effectively create a map from component
514# names to required libraries, in a way that is easily accessed from CMake."""
515 for ci in self.ordered_component_infos:
516 # We only write the information for libraries currently.
517 if ci.type_name != 'Library':
518 continue
519
520 print >>f, """\
521set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)""" % (
522 ci.get_prefixed_library_name(), " ".join(sorted(
523 dep.get_prefixed_library_name()
524 for dep in self.get_required_libraries_for_component(ci))))
525
Daniel Dunbar16889612011-11-04 23:10:37 +0000526 f.close()
527
528 def write_make_fragment(self, output_path):
529 """
530 write_make_fragment(output_path) -> None
531
532 Generate a Makefile fragment which includes all of the collated
533 LLVMBuild information in a format that is easily digestible by a
534 Makefile. The exact contents of this are closely tied to how the LLVM
535 Makefiles integrate LLVMBuild, see Makefile.rules in the top-level.
536 """
537
538 dependencies = list(self.get_fragment_dependencies())
Daniel Dunbar02271a72011-11-03 22:46:19 +0000539
540 # Write out the Makefile fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000541 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar02271a72011-11-03 22:46:19 +0000542 f = open(output_path, 'w')
543
544 # Write the header.
545 header_fmt = '\
546#===-- %s - LLVMBuild Configuration for LLVM %s-*- Makefile -*--===#'
547 header_name = os.path.basename(output_path)
548 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
549 header_string = header_fmt % (header_name, header_pad)
550 print >>f, """\
551%s
552#
553# The LLVM Compiler Infrastructure
554#
555# This file is distributed under the University of Illinois Open Source
556# License. See LICENSE.TXT for details.
557#
558#===------------------------------------------------------------------------===#
559#
560# This file contains the LLVMBuild project information in a format easily
561# consumed by the Makefile based build system.
562#
563# This file is autogenerated by llvm-build, do not edit!
564#
565#===------------------------------------------------------------------------===#
566""" % header_string
567
568 # Write the dependencies for the fragment.
569 #
570 # FIXME: Technically, we need to properly quote for Make here.
571 print >>f, """\
572# Clients must explicitly enable LLVMBUILD_INCLUDE_DEPENDENCIES to get
573# these dependencies. This is a compromise to help improve the
574# performance of recursive Make systems."""
575 print >>f, 'ifeq ($(LLVMBUILD_INCLUDE_DEPENDENCIES),1)'
576 print >>f, "# The dependencies for this Makefile fragment itself."
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000577 print >>f, "%s: \\" % (mk_quote_string_for_target(output_path),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000578 for dep in dependencies:
579 print >>f, "\t%s \\" % (dep,)
580 print >>f
581
582 # Generate dummy rules for each of the dependencies, so that things
583 # continue to work correctly if any of those files are moved or removed.
584 print >>f, """\
585# The dummy targets to allow proper regeneration even when files are moved or
586# removed."""
587 for dep in dependencies:
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000588 print >>f, "%s:" % (mk_quote_string_for_target(dep),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000589 print >>f, 'endif'
590
591 f.close()
592
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000593def add_magic_target_components(parser, project, opts):
594 """add_magic_target_components(project, opts) -> None
595
596 Add the "magic" target based components to the project, which can only be
597 determined based on the target configuration options.
598
599 This currently is responsible for populating the required_libraries list of
Daniel Dunbar83337302011-11-10 01:16:48 +0000600 the "all-targets", "Native", "NativeCodeGen", and "Engine" components.
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000601 """
602
603 # Determine the available targets.
604 available_targets = dict((ci.name,ci)
605 for ci in project.component_infos
606 if ci.type_name == 'TargetGroup')
607
608 # Find the configured native target.
609
610 # We handle a few special cases of target names here for historical
611 # reasons, as these are the names configure currently comes up with.
612 native_target_name = { 'x86' : 'X86',
613 'x86_64' : 'X86',
614 'Unknown' : None }.get(opts.native_target,
615 opts.native_target)
616 if native_target_name is None:
617 native_target = None
618 else:
619 native_target = available_targets.get(native_target_name)
620 if native_target is None:
621 parser.error("invalid native target: %r (not in project)" % (
622 opts.native_target,))
623 if native_target.type_name != 'TargetGroup':
624 parser.error("invalid native target: %r (not a target)" % (
625 opts.native_target,))
626
627 # Find the list of targets to enable.
628 if opts.enable_targets is None:
629 enable_targets = available_targets.values()
630 else:
Daniel Dunbar83337302011-11-10 01:16:48 +0000631 # We support both space separated and semi-colon separated lists.
632 if ' ' in opts.enable_targets:
633 enable_target_names = opts.enable_targets.split()
634 else:
635 enable_target_names = opts.enable_targets.split(';')
636
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000637 enable_targets = []
Daniel Dunbar83337302011-11-10 01:16:48 +0000638 for name in enable_target_names:
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000639 target = available_targets.get(name)
640 if target is None:
641 parser.error("invalid target to enable: %r (not in project)" % (
642 name,))
643 if target.type_name != 'TargetGroup':
644 parser.error("invalid target to enable: %r (not a target)" % (
645 name,))
646 enable_targets.append(target)
647
648 # Find the special library groups we are going to populate. We enforce that
649 # these appear in the project (instead of just adding them) so that they at
650 # least have an explicit representation in the project LLVMBuild files (and
651 # comments explaining how they are populated).
652 def find_special_group(name):
653 info = info_map.get(name)
654 if info is None:
655 fatal("expected project to contain special %r component" % (
656 name,))
657
658 if info.type_name != 'LibraryGroup':
659 fatal("special component %r should be a LibraryGroup" % (
660 name,))
661
662 if info.required_libraries:
663 fatal("special component %r must have empty %r list" % (
664 name, 'required_libraries'))
665 if info.add_to_library_groups:
666 fatal("special component %r must have empty %r list" % (
667 name, 'add_to_library_groups'))
668
669 return info
670
671 info_map = dict((ci.name, ci) for ci in project.component_infos)
672 all_targets = find_special_group('all-targets')
673 native_group = find_special_group('Native')
674 native_codegen_group = find_special_group('NativeCodeGen')
675 engine_group = find_special_group('Engine')
676
677 # Set the enabled bit in all the target groups, and append to the
678 # all-targets list.
679 for ci in enable_targets:
680 all_targets.required_libraries.append(ci.name)
681 ci.enabled = True
682
683 # If we have a native target, then that defines the native and
684 # native_codegen libraries.
685 if native_target and native_target.enabled:
686 native_group.required_libraries.append(native_target.name)
687 native_codegen_group.required_libraries.append(
688 '%sCodeGen' % native_target.name)
689
690 # If we have a native target with a JIT, use that for the engine. Otherwise,
691 # use the interpreter.
692 if native_target and native_target.enabled and native_target.has_jit:
693 engine_group.required_libraries.append('JIT')
694 engine_group.required_libraries.append(native_group.name)
695 else:
696 engine_group.required_libraries.append('Interpreter')
697
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000698def main():
699 from optparse import OptionParser, OptionGroup
700 parser = OptionParser("usage: %prog [options]")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000701
702 group = OptionGroup(parser, "Input Options")
703 group.add_option("", "--source-root", dest="source_root", metavar="PATH",
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000704 help="Path to the LLVM source (inferred if not given)",
705 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000706 group.add_option("", "--llvmbuild-source-root",
707 dest="llvmbuild_source_root",
708 help=(
709 "If given, an alternate path to search for LLVMBuild.txt files"),
710 action="store", default=None, metavar="PATH")
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000711 group.add_option("", "--build-root", dest="build_root", metavar="PATH",
712 help="Path to the build directory (if needed) [%default]",
713 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000714 parser.add_option_group(group)
715
716 group = OptionGroup(parser, "Output Options")
717 group.add_option("", "--print-tree", dest="print_tree",
718 help="Print out the project component tree [%default]",
719 action="store_true", default=False)
720 group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
Daniel Dunbar43120df2011-11-03 17:56:21 +0000721 help="Write out the LLVMBuild.txt files to PATH",
722 action="store", default=None, metavar="PATH")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000723 group.add_option("", "--write-library-table",
724 dest="write_library_table", metavar="PATH",
725 help="Write the C++ library dependency table to PATH",
726 action="store", default=None)
727 group.add_option("", "--write-cmake-fragment",
728 dest="write_cmake_fragment", metavar="PATH",
729 help="Write the CMake project information to PATH",
730 action="store", default=None)
731 group.add_option("", "--write-make-fragment",
Daniel Dunbar02271a72011-11-03 22:46:19 +0000732 dest="write_make_fragment", metavar="PATH",
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000733 help="Write the Makefile project information to PATH",
734 action="store", default=None)
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000735 group.add_option("", "--configure-target-def-file",
736 dest="configure_target_def_files",
737 help="""Configure the given file at SUBPATH (relative to
738the inferred or given source root, and with a '.in' suffix) by replacing certain
739substitution variables with lists of targets that support certain features (for
740example, targets with AsmPrinters) and write the result to the build root (as
741given by --build-root) at the same SUBPATH""",
742 metavar="SUBPATH", action="append", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000743 parser.add_option_group(group)
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000744
745 group = OptionGroup(parser, "Configuration Options")
746 group.add_option("", "--native-target",
747 dest="native_target", metavar="NAME",
748 help=("Treat the named target as the 'native' one, if "
749 "given [%default]"),
750 action="store", default=None)
751 group.add_option("", "--enable-targets",
752 dest="enable_targets", metavar="NAMES",
Daniel Dunbar83337302011-11-10 01:16:48 +0000753 help=("Enable the given space or semi-colon separated "
754 "list of targets, or all targets if not present"),
Daniel Dunbar02271a72011-11-03 22:46:19 +0000755 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000756 parser.add_option_group(group)
757
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000758 (opts, args) = parser.parse_args()
759
760 # Determine the LLVM source path, if not given.
761 source_root = opts.source_root
762 if source_root:
763 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
764 'Function.cpp')):
765 parser.error('invalid LLVM source root: %r' % source_root)
766 else:
767 llvmbuild_path = os.path.dirname(__file__)
768 llvm_build_path = os.path.dirname(llvmbuild_path)
769 utils_path = os.path.dirname(llvm_build_path)
770 source_root = os.path.dirname(utils_path)
771 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
772 'Function.cpp')):
773 parser.error('unable to infer LLVM source root, please specify')
774
Daniel Dunbardf578252011-11-03 17:56:06 +0000775 # Construct the LLVM project information.
776 llvmbuild_source_root = opts.llvmbuild_source_root or source_root
777 project_info = LLVMProjectInfo.load_from_path(
778 source_root, llvmbuild_source_root)
779
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000780 # Add the magic target based components.
781 add_magic_target_components(parser, project_info, opts)
782
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000783 # Validate the project component info.
784 project_info.validate_components()
785
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000786 # Print the component tree, if requested.
787 if opts.print_tree:
788 project_info.print_tree()
789
Daniel Dunbar43120df2011-11-03 17:56:21 +0000790 # Write out the components, if requested. This is useful for auto-upgrading
791 # the schema.
792 if opts.write_llvmbuild:
793 project_info.write_components(opts.write_llvmbuild)
794
Daniel Dunbar16889612011-11-04 23:10:37 +0000795 # Write out the required library table, if requested.
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000796 if opts.write_library_table:
797 project_info.write_library_table(opts.write_library_table)
798
Daniel Dunbar16889612011-11-04 23:10:37 +0000799 # Write out the make fragment, if requested.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000800 if opts.write_make_fragment:
801 project_info.write_make_fragment(opts.write_make_fragment)
802
Daniel Dunbar16889612011-11-04 23:10:37 +0000803 # Write out the cmake fragment, if requested.
804 if opts.write_cmake_fragment:
805 project_info.write_cmake_fragment(opts.write_cmake_fragment)
806
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000807 # Configure target definition files, if requested.
808 if opts.configure_target_def_files:
809 # Verify we were given a build root.
810 if not opts.build_root:
811 parser.error("must specify --build-root when using "
812 "--configure-target-def-file")
813
814 # Create the substitution list.
815 available_targets = [ci for ci in project_info.component_infos
816 if ci.type_name == 'TargetGroup']
817 substitutions = [
818 ("@LLVM_ENUM_TARGETS@",
819 ' '.join('LLVM_TARGET(%s)' % ci.name
820 for ci in available_targets)),
821 ("@LLVM_ENUM_ASM_PRINTERS@",
822 ' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
823 for ci in available_targets
824 if ci.has_asmprinter)),
825 ("@LLVM_ENUM_ASM_PARSERS@",
826 ' '.join('LLVM_ASM_PARSER(%s)' % ci.name
827 for ci in available_targets
828 if ci.has_asmparser)),
829 ("@LLVM_ENUM_DISASSEMBLERS@",
830 ' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
831 for ci in available_targets
832 if ci.has_disassembler))]
833
834 # Configure the given files.
835 for subpath in opts.configure_target_def_files:
836 inpath = os.path.join(source_root, subpath + '.in')
837 outpath = os.path.join(opts.build_root, subpath)
838 result = configutil.configure_file(inpath, outpath, substitutions)
839 if not result:
840 note("configured file %r hasn't changed" % outpath)
841
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000842if __name__=='__main__':
843 main()