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