• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import absolute_import
2import os
3import sys
4
5import llvmbuild.componentinfo as componentinfo
6import llvmbuild.configutil as configutil
7
8from llvmbuild.util import fatal, note
9
10###
11
12def 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
25def 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
40def 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
51def 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 existent path.
59    if not os.path.exists(path):
60        os.makedirs(path)
61
62###
63
64class LLVMProjectInfo(object):
65    @staticmethod
66    def load_infos_from_path(llvmbuild_source_root):
67        def recurse(subpath):
68            # Load the LLVMBuild file.
69            llvmbuild_path = os.path.join(llvmbuild_source_root + subpath,
70                                          'LLVMBuild.txt')
71            if not os.path.exists(llvmbuild_path):
72                fatal("missing LLVMBuild.txt file at: %r" % (llvmbuild_path,))
73
74            # Parse the components from it.
75            common,info_iter = componentinfo.load_from_path(llvmbuild_path,
76                                                            subpath)
77            for info in info_iter:
78                yield info
79
80            # Recurse into the specified subdirectories.
81            for subdir in common.get_list("subdirectories"):
82                for item in recurse(os.path.join(subpath, subdir)):
83                    yield item
84
85        return recurse("/")
86
87    @staticmethod
88    def load_from_path(source_root, llvmbuild_source_root):
89        infos = list(
90            LLVMProjectInfo.load_infos_from_path(llvmbuild_source_root))
91
92        return LLVMProjectInfo(source_root, infos)
93
94    def __init__(self, source_root, component_infos):
95        # Store our simple ivars.
96        self.source_root = source_root
97        self.component_infos = list(component_infos)
98        self.component_info_map = None
99        self.ordered_component_infos = None
100
101    def validate_components(self):
102        """validate_components() -> None
103
104        Validate that the project components are well-defined. Among other
105        things, this checks that:
106          - Components have valid references.
107          - Components references do not form cycles.
108
109        We also construct the map from component names to info, and the
110        topological ordering of components.
111        """
112
113        # Create the component info map and validate that component names are
114        # unique.
115        self.component_info_map = {}
116        for ci in self.component_infos:
117            existing = self.component_info_map.get(ci.name)
118            if existing is not None:
119                # We found a duplicate component name, report it and error out.
120                fatal("found duplicate component %r (at %r and %r)" % (
121                        ci.name, ci.subpath, existing.subpath))
122            self.component_info_map[ci.name] = ci
123
124        # Disallow 'all' as a component name, which is a special case.
125        if 'all' in self.component_info_map:
126            fatal("project is not allowed to define 'all' component")
127
128        # Add the root component.
129        if '$ROOT' in self.component_info_map:
130            fatal("project is not allowed to define $ROOT component")
131        self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo(
132            '/', '$ROOT', None)
133        self.component_infos.append(self.component_info_map['$ROOT'])
134
135        # Topologically order the component information according to their
136        # component references.
137        def visit_component_info(ci, current_stack, current_set):
138            # Check for a cycles.
139            if ci in current_set:
140                # We found a cycle, report it and error out.
141                cycle_description = ' -> '.join(
142                    '%r (%s)' % (ci.name, relation)
143                    for relation,ci in current_stack)
144                fatal("found cycle to %r after following: %s -> %s" % (
145                        ci.name, cycle_description, ci.name))
146
147            # If we have already visited this item, we are done.
148            if ci not in components_to_visit:
149                return
150
151            # Otherwise, mark the component info as visited and traverse.
152            components_to_visit.remove(ci)
153
154            # Validate the parent reference, which we treat specially.
155            if ci.parent is not None:
156                parent = self.component_info_map.get(ci.parent)
157                if parent is None:
158                    fatal("component %r has invalid reference %r (via %r)" % (
159                            ci.name, ci.parent, 'parent'))
160                ci.set_parent_instance(parent)
161
162            for relation,referent_name in ci.get_component_references():
163                # Validate that the reference is ok.
164                referent = self.component_info_map.get(referent_name)
165                if referent is None:
166                    fatal("component %r has invalid reference %r (via %r)" % (
167                            ci.name, referent_name, relation))
168
169                # Visit the reference.
170                current_stack.append((relation,ci))
171                current_set.add(ci)
172                visit_component_info(referent, current_stack, current_set)
173                current_set.remove(ci)
174                current_stack.pop()
175
176            # Finally, add the component info to the ordered list.
177            self.ordered_component_infos.append(ci)
178
179        # FIXME: We aren't actually correctly checking for cycles along the
180        # parent edges. Haven't decided how I want to handle this -- I thought
181        # about only checking cycles by relation type. If we do that, it falls
182        # out easily. If we don't, we should special case the check.
183
184        self.ordered_component_infos = []
185        components_to_visit = sorted(
186            set(self.component_infos),
187            key = lambda c: c.name)
188        while components_to_visit:
189            visit_component_info(components_to_visit[0], [], set())
190
191        # Canonicalize children lists.
192        for c in self.ordered_component_infos:
193            c.children.sort(key = lambda c: c.name)
194
195    def print_tree(self):
196        def visit(node, depth = 0):
197            print('%s%-40s (%s)' % ('  '*depth, node.name, node.type_name))
198            for c in node.children:
199                visit(c, depth + 1)
200        visit(self.component_info_map['$ROOT'])
201
202    def write_components(self, output_path):
203        # Organize all the components by the directory their LLVMBuild file
204        # should go in.
205        info_basedir = {}
206        for ci in self.component_infos:
207            # Ignore the $ROOT component.
208            if ci.parent is None:
209                continue
210
211            info_basedir[ci.subpath] = info_basedir.get(ci.subpath, []) + [ci]
212
213        # Compute the list of subdirectories to scan.
214        subpath_subdirs = {}
215        for ci in self.component_infos:
216            # Ignore root components.
217            if ci.subpath == '/':
218                continue
219
220            # Otherwise, append this subpath to the parent list.
221            parent_path = os.path.dirname(ci.subpath)
222            subpath_subdirs[parent_path] = parent_list = subpath_subdirs.get(
223                parent_path, set())
224            parent_list.add(os.path.basename(ci.subpath))
225
226        # Generate the build files.
227        for subpath, infos in info_basedir.items():
228            # Order the components by name to have a canonical ordering.
229            infos.sort(key = lambda ci: ci.name)
230
231            # Format the components into llvmbuild fragments.
232            fragments = []
233
234            # Add the common fragments.
235            subdirectories = subpath_subdirs.get(subpath)
236            if subdirectories:
237                fragment = """\
238subdirectories = %s
239""" % (" ".join(sorted(subdirectories)),)
240                fragments.append(("common", fragment))
241
242            # Add the component fragments.
243            num_common_fragments = len(fragments)
244            for ci in infos:
245                fragment = ci.get_llvmbuild_fragment()
246                if fragment is None:
247                    continue
248
249                name = "component_%d" % (len(fragments) - num_common_fragments)
250                fragments.append((name, fragment))
251
252            if not fragments:
253                continue
254
255            assert subpath.startswith('/')
256            directory_path = os.path.join(output_path, subpath[1:])
257
258            # Create the directory if it does not already exist.
259            if not os.path.exists(directory_path):
260                os.makedirs(directory_path)
261
262            # In an effort to preserve comments (which aren't parsed), read in
263            # the original file and extract the comments. We only know how to
264            # associate comments that prefix a section name.
265            f = open(infos[0]._source_path)
266            comments_map = {}
267            comment_block = ""
268            for ln in f:
269                if ln.startswith(';'):
270                    comment_block += ln
271                elif ln.startswith('[') and ln.endswith(']\n'):
272                    comments_map[ln[1:-2]] = comment_block
273                else:
274                    comment_block = ""
275            f.close()
276
277            # Create the LLVMBuild fil[e.
278            file_path = os.path.join(directory_path, 'LLVMBuild.txt')
279            f = open(file_path, "w")
280
281            # Write the header.
282            header_fmt = ';===- %s %s-*- Conf -*--===;'
283            header_name = '.' + os.path.join(subpath, 'LLVMBuild.txt')
284            header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
285            header_string = header_fmt % (header_name, header_pad)
286            f.write("""\
287%s
288;
289;                     The LLVM Compiler Infrastructure
290;
291; This file is distributed under the University of Illinois Open Source
292; License. See LICENSE.TXT for details.
293;
294;===------------------------------------------------------------------------===;
295;
296; This is an LLVMBuild description file for the components in this subdirectory.
297;
298; For more information on the LLVMBuild system, please see:
299;
300;   http://llvm.org/docs/LLVMBuild.html
301;
302;===------------------------------------------------------------------------===;
303
304""" % header_string)
305
306            # Write out each fragment.each component fragment.
307            for name,fragment in fragments:
308                comment = comments_map.get(name)
309                if comment is not None:
310                    f.write(comment)
311                f.write("[%s]\n" % name)
312                f.write(fragment)
313                if fragment is not fragments[-1][1]:
314                    f.write('\n')
315
316            f.close()
317
318    def write_library_table(self, output_path, enabled_optional_components):
319        # Write out the mapping from component names to required libraries.
320        #
321        # We do this in topological order so that we know we can append the
322        # dependencies for added library groups.
323        entries = {}
324        for c in self.ordered_component_infos:
325            # Skip optional components which are not enabled.
326            if c.type_name == 'OptionalLibrary' \
327                and c.name not in enabled_optional_components:
328                continue
329
330            # Skip target groups which are not enabled.
331            tg = c.get_parent_target_group()
332            if tg and not tg.enabled:
333                continue
334
335            # Only certain components are in the table.
336            if c.type_name not in ('Library', 'OptionalLibrary', \
337                                   'LibraryGroup', 'TargetGroup'):
338                continue
339
340            # Compute the llvm-config "component name". For historical reasons,
341            # this is lowercased based on the library name.
342            llvmconfig_component_name = c.get_llvmconfig_component_name()
343
344            # Get the library name, or None for LibraryGroups.
345            if c.type_name == 'Library' or c.type_name == 'OptionalLibrary':
346                library_name = c.get_prefixed_library_name()
347                is_installed = c.installed
348            else:
349                library_name = None
350                is_installed = True
351
352            # Get the component names of all the required libraries.
353            required_llvmconfig_component_names = [
354                self.component_info_map[dep].get_llvmconfig_component_name()
355                for dep in c.required_libraries]
356
357            # Insert the entries for library groups we should add to.
358            for dep in c.add_to_library_groups:
359                entries[dep][2].append(llvmconfig_component_name)
360
361            # Add the entry.
362            entries[c.name] = (llvmconfig_component_name, library_name,
363                               required_llvmconfig_component_names,
364                               is_installed)
365
366        # Convert to a list of entries and sort by name.
367        entries = list(entries.values())
368
369        # Create an 'all' pseudo component. We keep the dependency list small by
370        # only listing entries that have no other dependents.
371        root_entries = set(e[0] for e in entries)
372        for _,_,deps,_ in entries:
373            root_entries -= set(deps)
374        entries.append(('all', None, root_entries, True))
375
376        entries.sort()
377
378        # Compute the maximum number of required libraries, plus one so there is
379        # always a sentinel.
380        max_required_libraries = max(len(deps)
381                                     for _,_,deps,_ in entries) + 1
382
383        # Write out the library table.
384        make_install_dir(os.path.dirname(output_path))
385        f = open(output_path, 'w')
386        f.write("""\
387//===- llvm-build generated file --------------------------------*- C++ -*-===//
388//
389// Component Library Depenedency Table
390//
391// Automatically generated file, do not edit!
392//
393//===----------------------------------------------------------------------===//
394
395""")
396        f.write('struct AvailableComponent {\n')
397        f.write('  /// The name of the component.\n')
398        f.write('  const char *Name;\n')
399        f.write('\n')
400        f.write('  /// The name of the library for this component (or NULL).\n')
401        f.write('  const char *Library;\n')
402        f.write('\n')
403        f.write('  /// Whether the component is installed.\n')
404        f.write('  bool IsInstalled;\n')
405        f.write('\n')
406        f.write('\
407  /// The list of libraries required when linking this component.\n')
408        f.write('  const char *RequiredLibraries[%d];\n' % (
409            max_required_libraries))
410        f.write('} AvailableComponents[%d] = {\n' % len(entries))
411        for name,library_name,required_names,is_installed in entries:
412            if library_name is None:
413                library_name_as_cstr = '0'
414            else:
415                library_name_as_cstr = '"lib%s.a"' % library_name
416            f.write('  { "%s", %s, %d, { %s } },\n' % (
417                name, library_name_as_cstr, is_installed,
418                ', '.join('"%s"' % dep
419                          for dep in required_names)))
420        f.write('};\n')
421        f.close()
422
423    def get_required_libraries_for_component(self, ci, traverse_groups = False):
424        """
425        get_required_libraries_for_component(component_info) -> iter
426
427        Given a Library component info descriptor, return an iterator over all
428        of the directly required libraries for linking with this component. If
429        traverse_groups is True, then library and target groups will be
430        traversed to include their required libraries.
431        """
432
433        assert ci.type_name in ('Library', 'LibraryGroup', 'TargetGroup')
434
435        for name in ci.required_libraries:
436            # Get the dependency info.
437            dep = self.component_info_map[name]
438
439            # If it is a library, yield it.
440            if dep.type_name == 'Library':
441                yield dep
442                continue
443
444            # Otherwise if it is a group, yield or traverse depending on what
445            # was requested.
446            if dep.type_name in ('LibraryGroup', 'TargetGroup'):
447                if not traverse_groups:
448                    yield dep
449                    continue
450
451                for res in self.get_required_libraries_for_component(dep, True):
452                    yield res
453
454    def get_fragment_dependencies(self):
455        """
456        get_fragment_dependencies() -> iter
457
458        Compute the list of files (as absolute paths) on which the output
459        fragments depend (i.e., files for which a modification should trigger a
460        rebuild of the fragment).
461        """
462
463        # Construct a list of all the dependencies of the Makefile fragment
464        # itself. These include all the LLVMBuild files themselves, as well as
465        # all of our own sources.
466        #
467        # Many components may come from the same file, so we make sure to unique
468        # these.
469        build_paths = set()
470        for ci in self.component_infos:
471            p = os.path.join(self.source_root, ci.subpath[1:], 'LLVMBuild.txt')
472            if p not in build_paths:
473                yield p
474                build_paths.add(p)
475
476        # Gather the list of necessary sources by just finding all loaded
477        # modules that are inside the LLVM source tree.
478        for module in sys.modules.values():
479            # Find the module path.
480            if not hasattr(module, '__file__'):
481                continue
482            path = getattr(module, '__file__')
483            if not path:
484                continue
485
486            # Strip off any compiled suffix.
487            if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
488                path = path[:-1]
489
490            # If the path exists and is in the source tree, consider it a
491            # dependency.
492            if (path.startswith(self.source_root) and os.path.exists(path)):
493                yield path
494
495    def write_cmake_fragment(self, output_path):
496        """
497        write_cmake_fragment(output_path) -> None
498
499        Generate a CMake fragment which includes all of the collated LLVMBuild
500        information in a format that is easily digestible by a CMake. The exact
501        contents of this are closely tied to how the CMake configuration
502        integrates LLVMBuild, see CMakeLists.txt in the top-level.
503        """
504
505        dependencies = list(self.get_fragment_dependencies())
506
507        # Write out the CMake fragment.
508        make_install_dir(os.path.dirname(output_path))
509        f = open(output_path, 'w')
510
511        # Write the header.
512        header_fmt = '\
513#===-- %s - LLVMBuild Configuration for LLVM %s-*- CMake -*--===#'
514        header_name = os.path.basename(output_path)
515        header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
516        header_string = header_fmt % (header_name, header_pad)
517        f.write("""\
518%s
519#
520#                     The LLVM Compiler Infrastructure
521#
522# This file is distributed under the University of Illinois Open Source
523# License. See LICENSE.TXT for details.
524#
525#===------------------------------------------------------------------------===#
526#
527# This file contains the LLVMBuild project information in a format easily
528# consumed by the CMake based build system.
529#
530# This file is autogenerated by llvm-build, do not edit!
531#
532#===------------------------------------------------------------------------===#
533
534""" % header_string)
535
536        # Write the dependency information in the best way we can.
537        f.write("""
538# LLVMBuild CMake fragment dependencies.
539#
540# CMake has no builtin way to declare that the configuration depends on
541# a particular file. However, a side effect of configure_file is to add
542# said input file to CMake's internal dependency list. So, we use that
543# and a dummy output file to communicate the dependency information to
544# CMake.
545#
546# FIXME: File a CMake RFE to get a properly supported version of this
547# feature.
548""")
549        for dep in dependencies:
550            f.write("""\
551configure_file(\"%s\"
552               ${CMAKE_CURRENT_BINARY_DIR}/DummyConfigureOutput)\n""" % (
553                cmake_quote_path(dep),))
554
555        # Write the properties we use to encode the required library dependency
556        # information in a form CMake can easily use directly.
557        f.write("""
558# Explicit library dependency information.
559#
560# The following property assignments effectively create a map from component
561# names to required libraries, in a way that is easily accessed from CMake.
562""")
563        for ci in self.ordered_component_infos:
564            # We only write the information for libraries currently.
565            if ci.type_name != 'Library':
566                continue
567
568            f.write("""\
569set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % (
570                ci.get_prefixed_library_name(), " ".join(sorted(
571                     dep.get_prefixed_library_name()
572                     for dep in self.get_required_libraries_for_component(ci)))))
573
574        f.close()
575
576    def write_cmake_exports_fragment(self, output_path):
577        """
578        write_cmake_exports_fragment(output_path) -> None
579
580        Generate a CMake fragment which includes LLVMBuild library
581        dependencies expressed similarly to how CMake would write
582        them via install(EXPORT).
583        """
584
585        dependencies = list(self.get_fragment_dependencies())
586
587        # Write out the CMake exports fragment.
588        make_install_dir(os.path.dirname(output_path))
589        f = open(output_path, 'w')
590
591        f.write("""\
592# Explicit library dependency information.
593#
594# The following property assignments tell CMake about link
595# dependencies of libraries imported from LLVM.
596""")
597        for ci in self.ordered_component_infos:
598            # We only write the information for libraries currently.
599            if ci.type_name != 'Library':
600                continue
601
602            # Skip disabled targets.
603            tg = ci.get_parent_target_group()
604            if tg and not tg.enabled:
605                continue
606
607            f.write("""\
608set_property(TARGET %s PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES %s)\n""" % (
609                ci.get_prefixed_library_name(), " ".join(sorted(
610                     dep.get_prefixed_library_name()
611                     for dep in self.get_required_libraries_for_component(ci)))))
612
613        f.close()
614
615    def write_make_fragment(self, output_path):
616        """
617        write_make_fragment(output_path) -> None
618
619        Generate a Makefile fragment which includes all of the collated
620        LLVMBuild information in a format that is easily digestible by a
621        Makefile. The exact contents of this are closely tied to how the LLVM
622        Makefiles integrate LLVMBuild, see Makefile.rules in the top-level.
623        """
624
625        dependencies = list(self.get_fragment_dependencies())
626
627        # Write out the Makefile fragment.
628        make_install_dir(os.path.dirname(output_path))
629        f = open(output_path, 'w')
630
631        # Write the header.
632        header_fmt = '\
633#===-- %s - LLVMBuild Configuration for LLVM %s-*- Makefile -*--===#'
634        header_name = os.path.basename(output_path)
635        header_pad = '-' * (80 - len(header_fmt % (header_name, '')))
636        header_string = header_fmt % (header_name, header_pad)
637        f.write("""\
638%s
639#
640#                     The LLVM Compiler Infrastructure
641#
642# This file is distributed under the University of Illinois Open Source
643# License. See LICENSE.TXT for details.
644#
645#===------------------------------------------------------------------------===#
646#
647# This file contains the LLVMBuild project information in a format easily
648# consumed by the Makefile based build system.
649#
650# This file is autogenerated by llvm-build, do not edit!
651#
652#===------------------------------------------------------------------------===#
653
654""" % header_string)
655
656        # Write the dependencies for the fragment.
657        #
658        # FIXME: Technically, we need to properly quote for Make here.
659        f.write("""\
660# Clients must explicitly enable LLVMBUILD_INCLUDE_DEPENDENCIES to get
661# these dependencies. This is a compromise to help improve the
662# performance of recursive Make systems.
663""")
664        f.write('ifeq ($(LLVMBUILD_INCLUDE_DEPENDENCIES),1)\n')
665        f.write("# The dependencies for this Makefile fragment itself.\n")
666        f.write("%s: \\\n" % (mk_quote_string_for_target(output_path),))
667        for dep in dependencies:
668            f.write("\t%s \\\n" % (dep,))
669        f.write('\n')
670
671        # Generate dummy rules for each of the dependencies, so that things
672        # continue to work correctly if any of those files are moved or removed.
673        f.write("""\
674# The dummy targets to allow proper regeneration even when files are moved or
675# removed.
676""")
677        for dep in dependencies:
678            f.write("%s:\n" % (mk_quote_string_for_target(dep),))
679        f.write('endif\n')
680
681        f.close()
682
683def add_magic_target_components(parser, project, opts):
684    """add_magic_target_components(project, opts) -> None
685
686    Add the "magic" target based components to the project, which can only be
687    determined based on the target configuration options.
688
689    This currently is responsible for populating the required_libraries list of
690    the "all-targets", "Native", "NativeCodeGen", and "Engine" components.
691    """
692
693    # Determine the available targets.
694    available_targets = dict((ci.name,ci)
695                             for ci in project.component_infos
696                             if ci.type_name == 'TargetGroup')
697
698    # Find the configured native target.
699
700    # We handle a few special cases of target names here for historical
701    # reasons, as these are the names configure currently comes up with.
702    native_target_name = { 'x86' : 'X86',
703                           'x86_64' : 'X86',
704                           'Unknown' : None }.get(opts.native_target,
705                                                  opts.native_target)
706    if native_target_name is None:
707        native_target = None
708    else:
709        native_target = available_targets.get(native_target_name)
710        if native_target is None:
711            parser.error("invalid native target: %r (not in project)" % (
712                    opts.native_target,))
713        if native_target.type_name != 'TargetGroup':
714            parser.error("invalid native target: %r (not a target)" % (
715                    opts.native_target,))
716
717    # Find the list of targets to enable.
718    if opts.enable_targets is None:
719        enable_targets = available_targets.values()
720    else:
721        # We support both space separated and semi-colon separated lists.
722        if opts.enable_targets == '':
723            enable_target_names = []
724        elif ' ' in opts.enable_targets:
725            enable_target_names = opts.enable_targets.split()
726        else:
727            enable_target_names = opts.enable_targets.split(';')
728
729        enable_targets = []
730        for name in enable_target_names:
731            target = available_targets.get(name)
732            if target is None:
733                parser.error("invalid target to enable: %r (not in project)" % (
734                        name,))
735            if target.type_name != 'TargetGroup':
736                parser.error("invalid target to enable: %r (not a target)" % (
737                        name,))
738            enable_targets.append(target)
739
740    # Find the special library groups we are going to populate. We enforce that
741    # these appear in the project (instead of just adding them) so that they at
742    # least have an explicit representation in the project LLVMBuild files (and
743    # comments explaining how they are populated).
744    def find_special_group(name):
745        info = info_map.get(name)
746        if info is None:
747            fatal("expected project to contain special %r component" % (
748                    name,))
749
750        if info.type_name != 'LibraryGroup':
751            fatal("special component %r should be a LibraryGroup" % (
752                    name,))
753
754        if info.required_libraries:
755            fatal("special component %r must have empty %r list" % (
756                    name, 'required_libraries'))
757        if info.add_to_library_groups:
758            fatal("special component %r must have empty %r list" % (
759                    name, 'add_to_library_groups'))
760
761        info._is_special_group = True
762        return info
763
764    info_map = dict((ci.name, ci) for ci in project.component_infos)
765    all_targets = find_special_group('all-targets')
766    native_group = find_special_group('Native')
767    native_codegen_group = find_special_group('NativeCodeGen')
768    engine_group = find_special_group('Engine')
769
770    # Set the enabled bit in all the target groups, and append to the
771    # all-targets list.
772    for ci in enable_targets:
773        all_targets.required_libraries.append(ci.name)
774        ci.enabled = True
775
776    # If we have a native target, then that defines the native and
777    # native_codegen libraries.
778    if native_target and native_target.enabled:
779        native_group.required_libraries.append(native_target.name)
780        native_codegen_group.required_libraries.append(
781            '%sCodeGen' % native_target.name)
782
783    # If we have a native target with a JIT, use that for the engine. Otherwise,
784    # use the interpreter.
785    if native_target and native_target.enabled and native_target.has_jit:
786        engine_group.required_libraries.append('JIT')
787        engine_group.required_libraries.append(native_group.name)
788    else:
789        engine_group.required_libraries.append('Interpreter')
790
791def main():
792    from optparse import OptionParser, OptionGroup
793    parser = OptionParser("usage: %prog [options]")
794
795    group = OptionGroup(parser, "Input Options")
796    group.add_option("", "--source-root", dest="source_root", metavar="PATH",
797                      help="Path to the LLVM source (inferred if not given)",
798                      action="store", default=None)
799    group.add_option("", "--llvmbuild-source-root",
800                     dest="llvmbuild_source_root",
801                     help=(
802            "If given, an alternate path to search for LLVMBuild.txt files"),
803                     action="store", default=None, metavar="PATH")
804    group.add_option("", "--build-root", dest="build_root", metavar="PATH",
805                      help="Path to the build directory (if needed) [%default]",
806                      action="store", default=None)
807    parser.add_option_group(group)
808
809    group = OptionGroup(parser, "Output Options")
810    group.add_option("", "--print-tree", dest="print_tree",
811                     help="Print out the project component tree [%default]",
812                     action="store_true", default=False)
813    group.add_option("", "--write-llvmbuild", dest="write_llvmbuild",
814                      help="Write out the LLVMBuild.txt files to PATH",
815                      action="store", default=None, metavar="PATH")
816    group.add_option("", "--write-library-table",
817                     dest="write_library_table", metavar="PATH",
818                     help="Write the C++ library dependency table to PATH",
819                     action="store", default=None)
820    group.add_option("", "--write-cmake-fragment",
821                     dest="write_cmake_fragment", metavar="PATH",
822                     help="Write the CMake project information to PATH",
823                     action="store", default=None)
824    group.add_option("", "--write-cmake-exports-fragment",
825                     dest="write_cmake_exports_fragment", metavar="PATH",
826                     help="Write the CMake exports information to PATH",
827                     action="store", default=None)
828    group.add_option("", "--write-make-fragment",
829                      dest="write_make_fragment", metavar="PATH",
830                     help="Write the Makefile project information to PATH",
831                     action="store", default=None)
832    group.add_option("", "--configure-target-def-file",
833                     dest="configure_target_def_files",
834                     help="""Configure the given file at SUBPATH (relative to
835the inferred or given source root, and with a '.in' suffix) by replacing certain
836substitution variables with lists of targets that support certain features (for
837example, targets with AsmPrinters) and write the result to the build root (as
838given by --build-root) at the same SUBPATH""",
839                     metavar="SUBPATH", action="append", default=None)
840    parser.add_option_group(group)
841
842    group = OptionGroup(parser, "Configuration Options")
843    group.add_option("", "--native-target",
844                      dest="native_target", metavar="NAME",
845                      help=("Treat the named target as the 'native' one, if "
846                            "given [%default]"),
847                      action="store", default=None)
848    group.add_option("", "--enable-targets",
849                      dest="enable_targets", metavar="NAMES",
850                      help=("Enable the given space or semi-colon separated "
851                            "list of targets, or all targets if not present"),
852                      action="store", default=None)
853    group.add_option("", "--enable-optional-components",
854                      dest="optional_components", metavar="NAMES",
855                      help=("Enable the given space or semi-colon separated "
856                            "list of optional components"),
857                      action="store", default="")
858    parser.add_option_group(group)
859
860    (opts, args) = parser.parse_args()
861
862    # Determine the LLVM source path, if not given.
863    source_root = opts.source_root
864    if source_root:
865        if not os.path.exists(os.path.join(source_root, 'lib', 'IR',
866                                           'Function.cpp')):
867            parser.error('invalid LLVM source root: %r' % source_root)
868    else:
869        llvmbuild_path = os.path.dirname(__file__)
870        llvm_build_path = os.path.dirname(llvmbuild_path)
871        utils_path = os.path.dirname(llvm_build_path)
872        source_root = os.path.dirname(utils_path)
873        if not os.path.exists(os.path.join(source_root, 'lib', 'IR',
874                                           'Function.cpp')):
875            parser.error('unable to infer LLVM source root, please specify')
876
877    # Construct the LLVM project information.
878    llvmbuild_source_root = opts.llvmbuild_source_root or source_root
879    project_info = LLVMProjectInfo.load_from_path(
880        source_root, llvmbuild_source_root)
881
882    # Add the magic target based components.
883    add_magic_target_components(parser, project_info, opts)
884
885    # Validate the project component info.
886    project_info.validate_components()
887
888    # Print the component tree, if requested.
889    if opts.print_tree:
890        project_info.print_tree()
891
892    # Write out the components, if requested. This is useful for auto-upgrading
893    # the schema.
894    if opts.write_llvmbuild:
895        project_info.write_components(opts.write_llvmbuild)
896
897    # Write out the required library table, if requested.
898    if opts.write_library_table:
899        project_info.write_library_table(opts.write_library_table,
900                                         opts.optional_components)
901
902    # Write out the make fragment, if requested.
903    if opts.write_make_fragment:
904        project_info.write_make_fragment(opts.write_make_fragment)
905
906    # Write out the cmake fragment, if requested.
907    if opts.write_cmake_fragment:
908        project_info.write_cmake_fragment(opts.write_cmake_fragment)
909    if opts.write_cmake_exports_fragment:
910        project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment)
911
912    # Configure target definition files, if requested.
913    if opts.configure_target_def_files:
914        # Verify we were given a build root.
915        if not opts.build_root:
916            parser.error("must specify --build-root when using "
917                         "--configure-target-def-file")
918
919        # Create the substitution list.
920        available_targets = [ci for ci in project_info.component_infos
921                             if ci.type_name == 'TargetGroup']
922        substitutions = [
923            ("@LLVM_ENUM_TARGETS@",
924             ' '.join('LLVM_TARGET(%s)' % ci.name
925                      for ci in available_targets)),
926            ("@LLVM_ENUM_ASM_PRINTERS@",
927             ' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
928                      for ci in available_targets
929                      if ci.has_asmprinter)),
930            ("@LLVM_ENUM_ASM_PARSERS@",
931             ' '.join('LLVM_ASM_PARSER(%s)' % ci.name
932                      for ci in available_targets
933                      if ci.has_asmparser)),
934            ("@LLVM_ENUM_DISASSEMBLERS@",
935             ' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
936                      for ci in available_targets
937                      if ci.has_disassembler))]
938
939        # Configure the given files.
940        for subpath in opts.configure_target_def_files:
941            inpath = os.path.join(source_root, subpath + '.in')
942            outpath = os.path.join(opts.build_root, subpath)
943            result = configutil.configure_file(inpath, outpath, substitutions)
944            if not result:
945                note("configured file %r hasn't changed" % outpath)
946
947if __name__=='__main__':
948    main()
949