blob: 550c7403034d6eea00d7314baca0bee2ea64e3ca [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
Daniel Dunbar54d8c7f2011-12-12 22:45:41 +0000669 info._is_special_group = True
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000670 return info
671
672 info_map = dict((ci.name, ci) for ci in project.component_infos)
673 all_targets = find_special_group('all-targets')
674 native_group = find_special_group('Native')
675 native_codegen_group = find_special_group('NativeCodeGen')
676 engine_group = find_special_group('Engine')
677
678 # Set the enabled bit in all the target groups, and append to the
679 # all-targets list.
680 for ci in enable_targets:
681 all_targets.required_libraries.append(ci.name)
682 ci.enabled = True
683
684 # If we have a native target, then that defines the native and
685 # native_codegen libraries.
686 if native_target and native_target.enabled:
687 native_group.required_libraries.append(native_target.name)
688 native_codegen_group.required_libraries.append(
689 '%sCodeGen' % native_target.name)
690
691 # If we have a native target with a JIT, use that for the engine. Otherwise,
692 # use the interpreter.
693 if native_target and native_target.enabled and native_target.has_jit:
694 engine_group.required_libraries.append('JIT')
695 engine_group.required_libraries.append(native_group.name)
696 else:
697 engine_group.required_libraries.append('Interpreter')
698
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000699def main():
700 from optparse import OptionParser, OptionGroup
701 parser = OptionParser("usage: %prog [options]")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000702
703 group = OptionGroup(parser, "Input Options")
704 group.add_option("", "--source-root", dest="source_root", metavar="PATH",
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000705 help="Path to the LLVM source (inferred if not given)",
706 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000707 group.add_option("", "--llvmbuild-source-root",
708 dest="llvmbuild_source_root",
709 help=(
710 "If given, an alternate path to search for LLVMBuild.txt files"),
711 action="store", default=None, metavar="PATH")
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000712 group.add_option("", "--build-root", dest="build_root", metavar="PATH",
713 help="Path to the build directory (if needed) [%default]",
714 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000715 parser.add_option_group(group)
716
717 group = OptionGroup(parser, "Output Options")
718 group.add_option("", "--print-tree", dest="print_tree",
719 help="Print out the project component tree [%default]",
720 action="store_true", default=False)
721 group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
Daniel Dunbar43120df2011-11-03 17:56:21 +0000722 help="Write out the LLVMBuild.txt files to PATH",
723 action="store", default=None, metavar="PATH")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000724 group.add_option("", "--write-library-table",
725 dest="write_library_table", metavar="PATH",
726 help="Write the C++ library dependency table to PATH",
727 action="store", default=None)
728 group.add_option("", "--write-cmake-fragment",
729 dest="write_cmake_fragment", metavar="PATH",
730 help="Write the CMake project information to PATH",
731 action="store", default=None)
732 group.add_option("", "--write-make-fragment",
Daniel Dunbar02271a72011-11-03 22:46:19 +0000733 dest="write_make_fragment", metavar="PATH",
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000734 help="Write the Makefile project information to PATH",
735 action="store", default=None)
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000736 group.add_option("", "--configure-target-def-file",
737 dest="configure_target_def_files",
738 help="""Configure the given file at SUBPATH (relative to
739the inferred or given source root, and with a '.in' suffix) by replacing certain
740substitution variables with lists of targets that support certain features (for
741example, targets with AsmPrinters) and write the result to the build root (as
742given by --build-root) at the same SUBPATH""",
743 metavar="SUBPATH", action="append", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000744 parser.add_option_group(group)
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000745
746 group = OptionGroup(parser, "Configuration Options")
747 group.add_option("", "--native-target",
748 dest="native_target", metavar="NAME",
749 help=("Treat the named target as the 'native' one, if "
750 "given [%default]"),
751 action="store", default=None)
752 group.add_option("", "--enable-targets",
753 dest="enable_targets", metavar="NAMES",
Daniel Dunbar83337302011-11-10 01:16:48 +0000754 help=("Enable the given space or semi-colon separated "
755 "list of targets, or all targets if not present"),
Daniel Dunbar02271a72011-11-03 22:46:19 +0000756 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000757 parser.add_option_group(group)
758
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000759 (opts, args) = parser.parse_args()
760
761 # Determine the LLVM source path, if not given.
762 source_root = opts.source_root
763 if source_root:
764 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
765 'Function.cpp')):
766 parser.error('invalid LLVM source root: %r' % source_root)
767 else:
768 llvmbuild_path = os.path.dirname(__file__)
769 llvm_build_path = os.path.dirname(llvmbuild_path)
770 utils_path = os.path.dirname(llvm_build_path)
771 source_root = os.path.dirname(utils_path)
772 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
773 'Function.cpp')):
774 parser.error('unable to infer LLVM source root, please specify')
775
Daniel Dunbardf578252011-11-03 17:56:06 +0000776 # Construct the LLVM project information.
777 llvmbuild_source_root = opts.llvmbuild_source_root or source_root
778 project_info = LLVMProjectInfo.load_from_path(
779 source_root, llvmbuild_source_root)
780
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000781 # Add the magic target based components.
782 add_magic_target_components(parser, project_info, opts)
783
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000784 # Validate the project component info.
785 project_info.validate_components()
786
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000787 # Print the component tree, if requested.
788 if opts.print_tree:
789 project_info.print_tree()
790
Daniel Dunbar43120df2011-11-03 17:56:21 +0000791 # Write out the components, if requested. This is useful for auto-upgrading
792 # the schema.
793 if opts.write_llvmbuild:
794 project_info.write_components(opts.write_llvmbuild)
795
Daniel Dunbar16889612011-11-04 23:10:37 +0000796 # Write out the required library table, if requested.
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000797 if opts.write_library_table:
798 project_info.write_library_table(opts.write_library_table)
799
Daniel Dunbar16889612011-11-04 23:10:37 +0000800 # Write out the make fragment, if requested.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000801 if opts.write_make_fragment:
802 project_info.write_make_fragment(opts.write_make_fragment)
803
Daniel Dunbar16889612011-11-04 23:10:37 +0000804 # Write out the cmake fragment, if requested.
805 if opts.write_cmake_fragment:
806 project_info.write_cmake_fragment(opts.write_cmake_fragment)
807
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000808 # Configure target definition files, if requested.
809 if opts.configure_target_def_files:
810 # Verify we were given a build root.
811 if not opts.build_root:
812 parser.error("must specify --build-root when using "
813 "--configure-target-def-file")
814
815 # Create the substitution list.
816 available_targets = [ci for ci in project_info.component_infos
817 if ci.type_name == 'TargetGroup']
818 substitutions = [
819 ("@LLVM_ENUM_TARGETS@",
820 ' '.join('LLVM_TARGET(%s)' % ci.name
821 for ci in available_targets)),
822 ("@LLVM_ENUM_ASM_PRINTERS@",
823 ' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
824 for ci in available_targets
825 if ci.has_asmprinter)),
826 ("@LLVM_ENUM_ASM_PARSERS@",
827 ' '.join('LLVM_ASM_PARSER(%s)' % ci.name
828 for ci in available_targets
829 if ci.has_asmparser)),
830 ("@LLVM_ENUM_DISASSEMBLERS@",
831 ' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
832 for ci in available_targets
833 if ci.has_disassembler))]
834
835 # Configure the given files.
836 for subpath in opts.configure_target_def_files:
837 inpath = os.path.join(source_root, subpath + '.in')
838 outpath = os.path.join(opts.build_root, subpath)
839 result = configutil.configure_file(inpath, outpath, substitutions)
840 if not result:
841 note("configured file %r hasn't changed" % outpath)
842
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000843if __name__=='__main__':
844 main()