blob: 279a10f5f199743dfa643f1597bc3feb4237ab16 [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
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000217 # Compute the list of subdirectories to scan.
218 subpath_subdirs = {}
219 for ci in self.component_infos:
220 # Ignore root components.
221 if ci.subpath == '/':
222 continue
223
224 # Otherwise, append this subpath to the parent list.
225 parent_path = os.path.dirname(ci.subpath)
226 subpath_subdirs[parent_path] = parent_list = subpath_subdirs.get(
227 parent_path, set())
228 parent_list.add(os.path.basename(ci.subpath))
229
Daniel Dunbar43120df2011-11-03 17:56:21 +0000230 # Generate the build files.
231 for subpath, infos in info_basedir.items():
232 # Order the components by name to have a canonical ordering.
233 infos.sort(key = lambda ci: ci.name)
234
235 # Format the components into llvmbuild fragments.
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000236 fragments = []
237
238 # Add the common fragments.
239 subdirectories = subpath_subdirs.get(subpath)
240 if subdirectories:
241 fragment = """\
242subdirectories = %s
243""" % (" ".join(sorted(subdirectories)),)
244 fragments.append(("common", fragment))
245
246 # Add the component fragments.
247 num_common_fragments = len(fragments)
248 for ci in infos:
249 fragment = ci.get_llvmbuild_fragment()
250 if fragment is None:
251 continue
252
253 name = "component_%d" % (len(fragments) - num_common_fragments)
254 fragments.append((name, fragment))
255
Daniel Dunbar43120df2011-11-03 17:56:21 +0000256 if not fragments:
257 continue
258
259 assert subpath.startswith('/')
260 directory_path = os.path.join(output_path, subpath[1:])
261
262 # Create the directory if it does not already exist.
263 if not os.path.exists(directory_path):
264 os.makedirs(directory_path)
265
Daniel Dunbara3217162011-12-12 22:45:35 +0000266 # In an effort to preserve comments (which aren't parsed), read in
267 # the original file and extract the comments. We only know how to
268 # associate comments that prefix a section name.
269 f = open(infos[0]._source_path)
270 comments_map = {}
271 comment_block = ""
272 for ln in f:
273 if ln.startswith(';'):
274 comment_block += ln
275 elif ln.startswith('[') and ln.endswith(']\n'):
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000276 comments_map[ln[1:-2]] = comment_block
Daniel Dunbara3217162011-12-12 22:45:35 +0000277 else:
278 comment_block = ""
279 f.close()
280
281 # Create the LLVMBuild fil[e.
Daniel Dunbar43120df2011-11-03 17:56:21 +0000282 file_path = os.path.join(directory_path, 'LLVMBuild.txt')
283 f = open(file_path, "w")
Daniel Dunbarfb6d79a2011-11-03 17:56:31 +0000284
285 # Write the header.
286 header_fmt = ';===- %s %s-*- Conf -*--===;'
287 header_name = '.' + os.path.join(subpath, 'LLVMBuild.txt')
288 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
289 header_string = header_fmt % (header_name, header_pad)
290 print >>f, """\
291%s
292;
293; The LLVM Compiler Infrastructure
294;
295; This file is distributed under the University of Illinois Open Source
296; License. See LICENSE.TXT for details.
297;
298;===------------------------------------------------------------------------===;
299;
300; This is an LLVMBuild description file for the components in this subdirectory.
301;
302; For more information on the LLVMBuild system, please see:
303;
304; http://llvm.org/docs/LLVMBuild.html
305;
306;===------------------------------------------------------------------------===;
307""" % header_string
308
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000309 # Write out each fragment.each component fragment.
310 for name,fragment in fragments:
Daniel Dunbara3217162011-12-12 22:45:35 +0000311 comment = comments_map.get(name)
312 if comment is not None:
313 f.write(comment)
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000314 print >>f, "[%s]" % name
Daniel Dunbar43120df2011-11-03 17:56:21 +0000315 f.write(fragment)
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000316 if fragment is not fragments[-1][1]:
Daniel Dunbar4ab406d2011-12-12 19:48:00 +0000317 print >>f
Daniel Dunbarb0c594f2011-12-12 22:45:54 +0000318
Daniel Dunbar43120df2011-11-03 17:56:21 +0000319 f.close()
320
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000321 def write_library_table(self, output_path):
322 # Write out the mapping from component names to required libraries.
323 #
324 # We do this in topological order so that we know we can append the
325 # dependencies for added library groups.
326 entries = {}
327 for c in self.ordered_component_infos:
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000328 # Only certain components are in the table.
329 if c.type_name not in ('Library', 'LibraryGroup', 'TargetGroup'):
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000330 continue
331
332 # Compute the llvm-config "component name". For historical reasons,
333 # this is lowercased based on the library name.
334 llvmconfig_component_name = c.get_llvmconfig_component_name()
335
336 # Get the library name, or None for LibraryGroups.
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000337 if c.type_name == 'Library':
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000338 library_name = c.get_library_name()
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000339 else:
340 library_name = None
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000341
342 # Get the component names of all the required libraries.
343 required_llvmconfig_component_names = [
344 self.component_info_map[dep].get_llvmconfig_component_name()
345 for dep in c.required_libraries]
346
347 # Insert the entries for library groups we should add to.
348 for dep in c.add_to_library_groups:
349 entries[dep][2].append(llvmconfig_component_name)
350
351 # Add the entry.
352 entries[c.name] = (llvmconfig_component_name, library_name,
353 required_llvmconfig_component_names)
354
355 # Convert to a list of entries and sort by name.
356 entries = entries.values()
357
358 # Create an 'all' pseudo component. We keep the dependency list small by
359 # only listing entries that have no other dependents.
360 root_entries = set(e[0] for e in entries)
361 for _,_,deps in entries:
362 root_entries -= set(deps)
363 entries.append(('all', None, root_entries))
364
365 entries.sort()
366
367 # Compute the maximum number of required libraries, plus one so there is
368 # always a sentinel.
369 max_required_libraries = max(len(deps)
370 for _,_,deps in entries) + 1
371
372 # Write out the library table.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000373 make_install_dir(os.path.dirname(output_path))
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000374 f = open(output_path, 'w')
375 print >>f, """\
376//===- llvm-build generated file --------------------------------*- C++ -*-===//
377//
378// Component Library Depenedency Table
379//
380// Automatically generated file, do not edit!
381//
382//===----------------------------------------------------------------------===//
383"""
384 print >>f, 'struct AvailableComponent {'
385 print >>f, ' /// The name of the component.'
386 print >>f, ' const char *Name;'
387 print >>f, ''
388 print >>f, ' /// The name of the library for this component (or NULL).'
389 print >>f, ' const char *Library;'
390 print >>f, ''
391 print >>f, '\
392 /// The list of libraries required when linking this component.'
393 print >>f, ' const char *RequiredLibraries[%d];' % (
394 max_required_libraries)
395 print >>f, '} AvailableComponents[%d] = {' % len(entries)
396 for name,library_name,required_names in entries:
397 if library_name is None:
398 library_name_as_cstr = '0'
399 else:
400 # If we had a project level component, we could derive the
401 # library prefix.
402 library_name_as_cstr = '"libLLVM%s.a"' % library_name
403 print >>f, ' { "%s", %s, { %s } },' % (
404 name, library_name_as_cstr,
405 ', '.join('"%s"' % dep
406 for dep in required_names))
407 print >>f, '};'
408 f.close()
409
Daniel Dunbar5086de62011-11-29 00:06:50 +0000410 def get_required_libraries_for_component(self, ci, traverse_groups = False):
411 """
412 get_required_libraries_for_component(component_info) -> iter
413
414 Given a Library component info descriptor, return an iterator over all
415 of the directly required libraries for linking with this component. If
416 traverse_groups is True, then library and target groups will be
417 traversed to include their required libraries.
418 """
419
420 assert ci.type_name in ('Library', 'LibraryGroup', 'TargetGroup')
421
422 for name in ci.required_libraries:
423 # Get the dependency info.
424 dep = self.component_info_map[name]
425
426 # If it is a library, yield it.
427 if dep.type_name == 'Library':
428 yield dep
429 continue
430
431 # Otherwise if it is a group, yield or traverse depending on what
432 # was requested.
433 if dep.type_name in ('LibraryGroup', 'TargetGroup'):
434 if not traverse_groups:
435 yield dep
436 continue
437
438 for res in self.get_required_libraries_for_component(dep, True):
439 yield res
440
Daniel Dunbar16889612011-11-04 23:10:37 +0000441 def get_fragment_dependencies(self):
Daniel Dunbar02271a72011-11-03 22:46:19 +0000442 """
Daniel Dunbar16889612011-11-04 23:10:37 +0000443 get_fragment_dependencies() -> iter
Daniel Dunbar02271a72011-11-03 22:46:19 +0000444
Daniel Dunbar16889612011-11-04 23:10:37 +0000445 Compute the list of files (as absolute paths) on which the output
446 fragments depend (i.e., files for which a modification should trigger a
447 rebuild of the fragment).
Daniel Dunbar02271a72011-11-03 22:46:19 +0000448 """
449
450 # Construct a list of all the dependencies of the Makefile fragment
451 # itself. These include all the LLVMBuild files themselves, as well as
452 # all of our own sources.
Daniel Dunbar309fc862011-12-06 23:13:42 +0000453 #
454 # Many components may come from the same file, so we make sure to unique
455 # these.
456 build_paths = set()
Daniel Dunbar02271a72011-11-03 22:46:19 +0000457 for ci in self.component_infos:
Daniel Dunbar309fc862011-12-06 23:13:42 +0000458 p = os.path.join(self.source_root, ci.subpath[1:], 'LLVMBuild.txt')
459 if p not in build_paths:
460 yield p
461 build_paths.add(p)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000462
463 # Gather the list of necessary sources by just finding all loaded
464 # modules that are inside the LLVM source tree.
465 for module in sys.modules.values():
466 # Find the module path.
467 if not hasattr(module, '__file__'):
468 continue
469 path = getattr(module, '__file__')
470 if not path:
471 continue
472
473 # Strip off any compiled suffix.
474 if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
475 path = path[:-1]
476
477 # If the path exists and is in the source tree, consider it a
478 # dependency.
479 if (path.startswith(self.source_root) and os.path.exists(path)):
Daniel Dunbar16889612011-11-04 23:10:37 +0000480 yield path
481
482 def write_cmake_fragment(self, output_path):
483 """
484 write_cmake_fragment(output_path) -> None
485
486 Generate a CMake fragment which includes all of the collated LLVMBuild
487 information in a format that is easily digestible by a CMake. The exact
488 contents of this are closely tied to how the CMake configuration
489 integrates LLVMBuild, see CMakeLists.txt in the top-level.
490 """
491
492 dependencies = list(self.get_fragment_dependencies())
493
494 # Write out the CMake fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000495 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar16889612011-11-04 23:10:37 +0000496 f = open(output_path, 'w')
497
498 # Write the header.
499 header_fmt = '\
500#===-- %s - LLVMBuild Configuration for LLVM %s-*- CMake -*--===#'
501 header_name = os.path.basename(output_path)
502 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
503 header_string = header_fmt % (header_name, header_pad)
504 print >>f, """\
505%s
506#
507# The LLVM Compiler Infrastructure
508#
509# This file is distributed under the University of Illinois Open Source
510# License. See LICENSE.TXT for details.
511#
512#===------------------------------------------------------------------------===#
513#
514# This file contains the LLVMBuild project information in a format easily
515# consumed by the CMake based build system.
516#
517# This file is autogenerated by llvm-build, do not edit!
518#
519#===------------------------------------------------------------------------===#
520""" % header_string
521
522 # Write the dependency information in the best way we can.
523 print >>f, """
524# LLVMBuild CMake fragment dependencies.
525#
526# CMake has no builtin way to declare that the configuration depends on
527# a particular file. However, a side effect of configure_file is to add
528# said input file to CMake's internal dependency list. So, we use that
529# and a dummy output file to communicate the dependency information to
530# CMake.
531#
532# FIXME: File a CMake RFE to get a properly supported version of this
533# feature."""
534 for dep in dependencies:
535 print >>f, """\
536configure_file(\"%s\"
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000537 ${CMAKE_CURRENT_BINARY_DIR}/DummyConfigureOutput)""" % (
Daniel Dunbard5889d82011-11-17 01:19:53 +0000538 cmake_quote_path(dep),)
Daniel Dunbar57574fa2011-11-05 04:07:43 +0000539
Daniel Dunbar5086de62011-11-29 00:06:50 +0000540 # Write the properties we use to encode the required library dependency
541 # information in a form CMake can easily use directly.
542 print >>f, """
543# Explicit library dependency information.
544#
545# The following property assignments effectively create a map from component
546# names to required libraries, in a way that is easily accessed from CMake."""
547 for ci in self.ordered_component_infos:
548 # We only write the information for libraries currently.
549 if ci.type_name != 'Library':
550 continue
551
552 print >>f, """\
553set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)""" % (
554 ci.get_prefixed_library_name(), " ".join(sorted(
555 dep.get_prefixed_library_name()
556 for dep in self.get_required_libraries_for_component(ci))))
557
Daniel Dunbar16889612011-11-04 23:10:37 +0000558 f.close()
559
560 def write_make_fragment(self, output_path):
561 """
562 write_make_fragment(output_path) -> None
563
564 Generate a Makefile fragment which includes all of the collated
565 LLVMBuild information in a format that is easily digestible by a
566 Makefile. The exact contents of this are closely tied to how the LLVM
567 Makefiles integrate LLVMBuild, see Makefile.rules in the top-level.
568 """
569
570 dependencies = list(self.get_fragment_dependencies())
Daniel Dunbar02271a72011-11-03 22:46:19 +0000571
572 # Write out the Makefile fragment.
Daniel Dunbar195c6f32011-11-05 04:07:49 +0000573 make_install_dir(os.path.dirname(output_path))
Daniel Dunbar02271a72011-11-03 22:46:19 +0000574 f = open(output_path, 'w')
575
576 # Write the header.
577 header_fmt = '\
578#===-- %s - LLVMBuild Configuration for LLVM %s-*- Makefile -*--===#'
579 header_name = os.path.basename(output_path)
580 header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
581 header_string = header_fmt % (header_name, header_pad)
582 print >>f, """\
583%s
584#
585# The LLVM Compiler Infrastructure
586#
587# This file is distributed under the University of Illinois Open Source
588# License. See LICENSE.TXT for details.
589#
590#===------------------------------------------------------------------------===#
591#
592# This file contains the LLVMBuild project information in a format easily
593# consumed by the Makefile based build system.
594#
595# This file is autogenerated by llvm-build, do not edit!
596#
597#===------------------------------------------------------------------------===#
598""" % header_string
599
600 # Write the dependencies for the fragment.
601 #
602 # FIXME: Technically, we need to properly quote for Make here.
603 print >>f, """\
604# Clients must explicitly enable LLVMBUILD_INCLUDE_DEPENDENCIES to get
605# these dependencies. This is a compromise to help improve the
606# performance of recursive Make systems."""
607 print >>f, 'ifeq ($(LLVMBUILD_INCLUDE_DEPENDENCIES),1)'
608 print >>f, "# The dependencies for this Makefile fragment itself."
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000609 print >>f, "%s: \\" % (mk_quote_string_for_target(output_path),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000610 for dep in dependencies:
611 print >>f, "\t%s \\" % (dep,)
612 print >>f
613
614 # Generate dummy rules for each of the dependencies, so that things
615 # continue to work correctly if any of those files are moved or removed.
616 print >>f, """\
617# The dummy targets to allow proper regeneration even when files are moved or
618# removed."""
619 for dep in dependencies:
Daniel Dunbar20fb32b2011-11-04 23:40:11 +0000620 print >>f, "%s:" % (mk_quote_string_for_target(dep),)
Daniel Dunbar02271a72011-11-03 22:46:19 +0000621 print >>f, 'endif'
622
623 f.close()
624
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000625def add_magic_target_components(parser, project, opts):
626 """add_magic_target_components(project, opts) -> None
627
628 Add the "magic" target based components to the project, which can only be
629 determined based on the target configuration options.
630
631 This currently is responsible for populating the required_libraries list of
Daniel Dunbar83337302011-11-10 01:16:48 +0000632 the "all-targets", "Native", "NativeCodeGen", and "Engine" components.
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000633 """
634
635 # Determine the available targets.
636 available_targets = dict((ci.name,ci)
637 for ci in project.component_infos
638 if ci.type_name == 'TargetGroup')
639
640 # Find the configured native target.
641
642 # We handle a few special cases of target names here for historical
643 # reasons, as these are the names configure currently comes up with.
644 native_target_name = { 'x86' : 'X86',
645 'x86_64' : 'X86',
646 'Unknown' : None }.get(opts.native_target,
647 opts.native_target)
648 if native_target_name is None:
649 native_target = None
650 else:
651 native_target = available_targets.get(native_target_name)
652 if native_target is None:
653 parser.error("invalid native target: %r (not in project)" % (
654 opts.native_target,))
655 if native_target.type_name != 'TargetGroup':
656 parser.error("invalid native target: %r (not a target)" % (
657 opts.native_target,))
658
659 # Find the list of targets to enable.
660 if opts.enable_targets is None:
661 enable_targets = available_targets.values()
662 else:
Daniel Dunbar83337302011-11-10 01:16:48 +0000663 # We support both space separated and semi-colon separated lists.
664 if ' ' in opts.enable_targets:
665 enable_target_names = opts.enable_targets.split()
666 else:
667 enable_target_names = opts.enable_targets.split(';')
668
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000669 enable_targets = []
Daniel Dunbar83337302011-11-10 01:16:48 +0000670 for name in enable_target_names:
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000671 target = available_targets.get(name)
672 if target is None:
673 parser.error("invalid target to enable: %r (not in project)" % (
674 name,))
675 if target.type_name != 'TargetGroup':
676 parser.error("invalid target to enable: %r (not a target)" % (
677 name,))
678 enable_targets.append(target)
679
680 # Find the special library groups we are going to populate. We enforce that
681 # these appear in the project (instead of just adding them) so that they at
682 # least have an explicit representation in the project LLVMBuild files (and
683 # comments explaining how they are populated).
684 def find_special_group(name):
685 info = info_map.get(name)
686 if info is None:
687 fatal("expected project to contain special %r component" % (
688 name,))
689
690 if info.type_name != 'LibraryGroup':
691 fatal("special component %r should be a LibraryGroup" % (
692 name,))
693
694 if info.required_libraries:
695 fatal("special component %r must have empty %r list" % (
696 name, 'required_libraries'))
697 if info.add_to_library_groups:
698 fatal("special component %r must have empty %r list" % (
699 name, 'add_to_library_groups'))
700
Daniel Dunbar54d8c7f2011-12-12 22:45:41 +0000701 info._is_special_group = True
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000702 return info
703
704 info_map = dict((ci.name, ci) for ci in project.component_infos)
705 all_targets = find_special_group('all-targets')
706 native_group = find_special_group('Native')
707 native_codegen_group = find_special_group('NativeCodeGen')
708 engine_group = find_special_group('Engine')
709
710 # Set the enabled bit in all the target groups, and append to the
711 # all-targets list.
712 for ci in enable_targets:
713 all_targets.required_libraries.append(ci.name)
714 ci.enabled = True
715
716 # If we have a native target, then that defines the native and
717 # native_codegen libraries.
718 if native_target and native_target.enabled:
719 native_group.required_libraries.append(native_target.name)
720 native_codegen_group.required_libraries.append(
721 '%sCodeGen' % native_target.name)
722
723 # If we have a native target with a JIT, use that for the engine. Otherwise,
724 # use the interpreter.
725 if native_target and native_target.enabled and native_target.has_jit:
726 engine_group.required_libraries.append('JIT')
727 engine_group.required_libraries.append(native_group.name)
728 else:
729 engine_group.required_libraries.append('Interpreter')
730
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000731def main():
732 from optparse import OptionParser, OptionGroup
733 parser = OptionParser("usage: %prog [options]")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000734
735 group = OptionGroup(parser, "Input Options")
736 group.add_option("", "--source-root", dest="source_root", metavar="PATH",
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000737 help="Path to the LLVM source (inferred if not given)",
738 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000739 group.add_option("", "--llvmbuild-source-root",
740 dest="llvmbuild_source_root",
741 help=(
742 "If given, an alternate path to search for LLVMBuild.txt files"),
743 action="store", default=None, metavar="PATH")
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000744 group.add_option("", "--build-root", dest="build_root", metavar="PATH",
745 help="Path to the build directory (if needed) [%default]",
746 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000747 parser.add_option_group(group)
748
749 group = OptionGroup(parser, "Output Options")
750 group.add_option("", "--print-tree", dest="print_tree",
751 help="Print out the project component tree [%default]",
752 action="store_true", default=False)
753 group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
Daniel Dunbar43120df2011-11-03 17:56:21 +0000754 help="Write out the LLVMBuild.txt files to PATH",
755 action="store", default=None, metavar="PATH")
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000756 group.add_option("", "--write-library-table",
757 dest="write_library_table", metavar="PATH",
758 help="Write the C++ library dependency table to PATH",
759 action="store", default=None)
760 group.add_option("", "--write-cmake-fragment",
761 dest="write_cmake_fragment", metavar="PATH",
762 help="Write the CMake project information to PATH",
763 action="store", default=None)
764 group.add_option("", "--write-make-fragment",
Daniel Dunbar02271a72011-11-03 22:46:19 +0000765 dest="write_make_fragment", metavar="PATH",
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000766 help="Write the Makefile project information to PATH",
767 action="store", default=None)
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000768 group.add_option("", "--configure-target-def-file",
769 dest="configure_target_def_files",
770 help="""Configure the given file at SUBPATH (relative to
771the inferred or given source root, and with a '.in' suffix) by replacing certain
772substitution variables with lists of targets that support certain features (for
773example, targets with AsmPrinters) and write the result to the build root (as
774given by --build-root) at the same SUBPATH""",
775 metavar="SUBPATH", action="append", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000776 parser.add_option_group(group)
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000777
778 group = OptionGroup(parser, "Configuration Options")
779 group.add_option("", "--native-target",
780 dest="native_target", metavar="NAME",
781 help=("Treat the named target as the 'native' one, if "
782 "given [%default]"),
783 action="store", default=None)
784 group.add_option("", "--enable-targets",
785 dest="enable_targets", metavar="NAMES",
Daniel Dunbar83337302011-11-10 01:16:48 +0000786 help=("Enable the given space or semi-colon separated "
787 "list of targets, or all targets if not present"),
Daniel Dunbar02271a72011-11-03 22:46:19 +0000788 action="store", default=None)
Daniel Dunbar1e5b2432011-11-10 00:49:42 +0000789 parser.add_option_group(group)
790
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000791 (opts, args) = parser.parse_args()
792
793 # Determine the LLVM source path, if not given.
794 source_root = opts.source_root
795 if source_root:
796 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
797 'Function.cpp')):
798 parser.error('invalid LLVM source root: %r' % source_root)
799 else:
800 llvmbuild_path = os.path.dirname(__file__)
801 llvm_build_path = os.path.dirname(llvmbuild_path)
802 utils_path = os.path.dirname(llvm_build_path)
803 source_root = os.path.dirname(utils_path)
804 if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore',
805 'Function.cpp')):
806 parser.error('unable to infer LLVM source root, please specify')
807
Daniel Dunbardf578252011-11-03 17:56:06 +0000808 # Construct the LLVM project information.
809 llvmbuild_source_root = opts.llvmbuild_source_root or source_root
810 project_info = LLVMProjectInfo.load_from_path(
811 source_root, llvmbuild_source_root)
812
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000813 # Add the magic target based components.
814 add_magic_target_components(parser, project_info, opts)
815
Daniel Dunbarb4eaee72011-11-10 00:49:58 +0000816 # Validate the project component info.
817 project_info.validate_components()
818
Daniel Dunbar00b4b4f2011-11-03 17:56:18 +0000819 # Print the component tree, if requested.
820 if opts.print_tree:
821 project_info.print_tree()
822
Daniel Dunbar43120df2011-11-03 17:56:21 +0000823 # Write out the components, if requested. This is useful for auto-upgrading
824 # the schema.
825 if opts.write_llvmbuild:
826 project_info.write_components(opts.write_llvmbuild)
827
Daniel Dunbar16889612011-11-04 23:10:37 +0000828 # Write out the required library table, if requested.
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000829 if opts.write_library_table:
830 project_info.write_library_table(opts.write_library_table)
831
Daniel Dunbar16889612011-11-04 23:10:37 +0000832 # Write out the make fragment, if requested.
Daniel Dunbar02271a72011-11-03 22:46:19 +0000833 if opts.write_make_fragment:
834 project_info.write_make_fragment(opts.write_make_fragment)
835
Daniel Dunbar16889612011-11-04 23:10:37 +0000836 # Write out the cmake fragment, if requested.
837 if opts.write_cmake_fragment:
838 project_info.write_cmake_fragment(opts.write_cmake_fragment)
839
Daniel Dunbarb7f3bfc2011-11-11 00:24:00 +0000840 # Configure target definition files, if requested.
841 if opts.configure_target_def_files:
842 # Verify we were given a build root.
843 if not opts.build_root:
844 parser.error("must specify --build-root when using "
845 "--configure-target-def-file")
846
847 # Create the substitution list.
848 available_targets = [ci for ci in project_info.component_infos
849 if ci.type_name == 'TargetGroup']
850 substitutions = [
851 ("@LLVM_ENUM_TARGETS@",
852 ' '.join('LLVM_TARGET(%s)' % ci.name
853 for ci in available_targets)),
854 ("@LLVM_ENUM_ASM_PRINTERS@",
855 ' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
856 for ci in available_targets
857 if ci.has_asmprinter)),
858 ("@LLVM_ENUM_ASM_PARSERS@",
859 ' '.join('LLVM_ASM_PARSER(%s)' % ci.name
860 for ci in available_targets
861 if ci.has_asmparser)),
862 ("@LLVM_ENUM_DISASSEMBLERS@",
863 ' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
864 for ci in available_targets
865 if ci.has_disassembler))]
866
867 # Configure the given files.
868 for subpath in opts.configure_target_def_files:
869 inpath = os.path.join(source_root, subpath + '.in')
870 outpath = os.path.join(opts.build_root, subpath)
871 result = configutil.configure_file(inpath, outpath, substitutions)
872 if not result:
873 note("configured file %r hasn't changed" % outpath)
874
Daniel Dunbarad5e0122011-11-03 17:56:03 +0000875if __name__=='__main__':
876 main()