| #!@PYTHON_EXECUTABLE@ |
| # |
| #===- streamexecutor-config - Build config script for SE -----*- python -*--===# |
| # |
| # The LLVM Compiler Infrastructure |
| # |
| # This file is distributed under the University of Illinois Open Source |
| # License. See LICENSE.TXT for details. |
| # |
| #===------------------------------------------------------------------------===# |
| |
| r""" |
| Get configuration info needed to compile programs which use StreamExecutor. |
| |
| Runs llvm-config and adds StreamExecutor-specific flags to the output. Supports |
| only the subset of llvm-config flags that are relevant for applications |
| compiling against StreamExecutor. |
| |
| This utility will typically be used to construct a compile command line for an |
| application which depends on the StreamExecutor library. |
| |
| For example: |
| c++ example.cpp -o example \ |
| $(streamexecutor-config \ |
| --cppflags --cxxflags --ldflags --libs --system-libs) |
| """ |
| |
| import argparse |
| import errno |
| import os |
| import shlex |
| import subprocess |
| import sys |
| |
| def get_llvm_config_dir(): |
| """Gets the path to the llvm-config executable. |
| |
| Surrounding the cmake replacement with triple quotes should allow for paths |
| that contain quotes.""" |
| return r"""@LLVM_BINARY_DIR@/bin""" |
| |
| def get_cmake_install_prefix(): |
| """Gets the value of the cmake variable CMAKE_INSTALL_PREFIX. |
| |
| Surrounding the cmake replacement with triple quotes should allow for paths |
| that contain quotes.""" |
| return r"""@CMAKE_INSTALL_PREFIX@""" |
| |
| def cuddle_flag(flag, tokens): |
| """If flag appears by itself in tokens, combines it with the next token. |
| |
| >>> tokens = ['-I', '/usr/include'] |
| >>> cuddle_flag('-I', tokens) |
| >>> tokens |
| ['-I/usr/include'] |
| |
| >>> tokens = ['-L', '/usr/lib'] |
| >>> cuddle_flag('-L', tokens) |
| >>> tokens |
| ['-L/usr/lib'] |
| |
| >>> tokens = ['-I'] |
| >>> cuddle_flag('-I', tokens) |
| >>> tokens |
| ['-I'] |
| |
| >>> tokens = ['-I', '/usr/include', '-I', '/usr/local/include'] |
| >>> cuddle_flag('-I', tokens) |
| >>> tokens |
| ['-I/usr/include', '-I/usr/local/include'] |
| """ |
| start = 0 |
| while True: |
| try: |
| index = tokens.index(flag, start) |
| except ValueError: |
| return |
| if index + 1 < len(tokens): |
| follower = tokens.pop(index + 1) |
| tokens[index] = flag + follower |
| start = index + 1 |
| |
| def get_llvm_config_output_for_dir(llvm_config_dir, flags_string): |
| """Calls llvm-config at the given path and returns the output with -I and -L |
| flags cuddled.""" |
| output = subprocess.check_output( |
| ['%s/llvm-config' % llvm_config_dir] + flags_string.split()).strip() |
| tokens = shlex.split(output) |
| cuddle_flag('-I', tokens) |
| cuddle_flag('-L', tokens) |
| return ' '.join(tokens) |
| |
| def has_token(token, string): |
| """Checks if the given token appears in the string. |
| |
| The token argument must be a single shell token. |
| |
| >>> string = '-I/usr/include -L"/usr/lib"' |
| >>> has_token('-I/usr/include', string) |
| True |
| >>> has_token('-I/usr/local/include', string) |
| False |
| >>> has_token('-I"/usr/include"', string) |
| True |
| >>> has_token('-L"/usr/lib"', string) |
| True |
| >>> has_token('-L/usr/lib', string) |
| True |
| """ |
| split_token = shlex.split(token) |
| if len(split_token) > 1: |
| raise ValueError('has_token called with a multi-token token: ' + token) |
| escaped_token = split_token[0] |
| return escaped_token in shlex.split(string) |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| prog='streamexecutor-config', |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| description=__doc__) |
| |
| parser.add_argument( |
| '--cppflags', |
| action='store_true', |
| help= |
| 'C preprocessor flags for files that include StreamExecutor headers.') |
| |
| parser.add_argument( |
| '--cxxflags', |
| action='store_true', |
| help='C++ compiler flags for files that include StreamExecutor headers.') |
| |
| parser.add_argument( |
| '--ldflags', |
| action='store_true', |
| help='Print linker flags.') |
| |
| parser.add_argument( |
| '--libs', |
| action='store_true', |
| help='Libraries needed to link against StreamExecutor.') |
| |
| parser.add_argument( |
| '--system-libs', |
| action='store_true', |
| help='System libraries needed to link against StreamExecutor.') |
| |
| parser.add_argument( |
| '--llvm-config-dir', |
| default=get_llvm_config_dir(), |
| help='Directory containing the llvm-config executable. '\ |
| 'If not specified, defaults to the cmake-configured location') |
| |
| args = parser.parse_args() |
| |
| # Print the help message if the user did not pass any flag arguments. |
| if not any( |
| getattr(args, flag) |
| for flag in ('cppflags', 'cxxflags', 'ldflags', 'libs', 'system_libs')): |
| parser.print_help() |
| sys.exit(1) |
| |
| # Check for the presence of the llvm-config executable. |
| if not os.path.isfile('%s/llvm-config' % args.llvm_config_dir): |
| sys.exit('llvm-config not found in: ' + args.llvm_config_dir) |
| if not os.access('%s/llvm-config' % args.llvm_config_dir, os.X_OK): |
| sys.exit('llvm-config not executable in: ' + args.llvm_config_dir) |
| |
| # We will always use args.llvm_config_dir as the second argument to |
| # get_llvm_config_output_for_path. |
| get_llvm_config_output = lambda flags : get_llvm_config_output_for_dir( |
| args.llvm_config_dir, flags) |
| |
| all_flags = [] |
| |
| if args.cppflags: |
| llvm_flags = get_llvm_config_output('--cppflags') |
| all_flags.append(llvm_flags) |
| se_flag = "-I%s/include" % get_cmake_install_prefix() |
| if not has_token(token=se_flag, string=llvm_flags): |
| all_flags.append(se_flag) |
| |
| if args.cxxflags: |
| all_flags.append(get_llvm_config_output('--cxxflags')) |
| |
| if args.ldflags: |
| llvm_flags = get_llvm_config_output('--ldflags') |
| all_flags.append(llvm_flags) |
| se_flag = "-L%s/lib" % get_cmake_install_prefix() |
| if not has_token(token=se_flag, string=llvm_flags): |
| all_flags.append(se_flag) |
| |
| if args.libs: |
| llvm_flags = get_llvm_config_output('--libs support symbolize') |
| se_flag = '-lstreamexecutor' |
| if not has_token(token=se_flag, string=llvm_flags): |
| all_flags.append(se_flag) |
| all_flags.append(llvm_flags) |
| |
| if args.system_libs: |
| all_flags.append(get_llvm_config_output('--system-libs')) |
| |
| print(' '.join(all_flags)) |
| |
| if __name__ == '__main__': |
| main() |