--- /dev/null
+#!@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()