Home | History | Annotate | Download | only in llvmbuild
      1 from __future__ import absolute_import
      2 import filecmp
      3 import os
      4 import sys
      5 
      6 import llvmbuild.componentinfo as componentinfo
      7 import llvmbuild.configutil as configutil
      8 
      9 from llvmbuild.util import fatal, note
     10 
     11 ###
     12 
     13 def 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 
     26 def 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 
     41 def 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 
     52 def 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 
     65 class 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 = """\
    239 subdirectories = %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 = '"lib%s.a"' % 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("""\
    591 configure_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("""\
    606 set_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("""\
    642 set_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'.
    723 LLVM_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 
    735 def 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 
    843 def 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
    887 the inferred or given source root, and with a '.in' suffix) by replacing certain
    888 substitution variables with lists of targets that support certain features (for
    889 example, targets with AsmPrinters) and write the result to the build root (as
    890 given 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 
   1002 if __name__=='__main__':
   1003     main()
   1004