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