diff --git a/llvm/utils/gn/build/symbol_exports.gni b/llvm/utils/gn/build/symbol_exports.gni new file mode 100644 index 000000000000..ed0e7df560e0 --- /dev/null +++ b/llvm/utils/gn/build/symbol_exports.gni @@ -0,0 +1,59 @@ +# This file defines a template for using .export files. +# +# Parameters: +# exports_file (required) +# Path of the .exports file to use. +# +# Example use: +# symbol_exports("my_exports") { +# exports_file = "//foo/bar/my.exports" +# } +# ... +# shared_library("my_target") { +# deps = [ ":my_exports" ] # Adds correct ldflags. +# ... +# } + +# Corresponds to add_llvm_symbol_exports() in the CMake build. +template("symbol_exports") { + # Create a platform-appropriate name for the temporary file. + linker_file = get_path_info(invoker.exports_file, "name") + if (current_os == "mac") { + linker_file = linker_file + "_symbols.txt" + } else if (current_os == "win") { + linker_file = linker_file + ".def" + } else { + linker_file = linker_file + ".script" + } + linker_file = "$target_gen_dir/$linker_file" + rebased_linker_file = rebase_path(linker_file, root_build_dir) + + config_name = "${target_name}_config" + config(config_name) { + # FIXME: With this setup, targets are not relinked automatically + # when the input exports file is touched but nothing else changes. + # https://groups.google.com/a/chromium.org/g/gn-dev/c/sN09GYS1ufE + visibility = [ ":$target_name" ] + if (current_os == "mac") { + ldflags = [ "-Wl,-exported_symbols_list,$rebased_linker_file" ] + } else if (current_os == "win") { + ldflags = [ "/DEF:$rebased_linker_file" ] + } else { + ldflags = [ "-Wl,--version-script,$rebased_linker_file" ] + } + } + + action(target_name) { + script = "//llvm/utils/gn/build/symbol_exports.py" + inputs = [ invoker.exports_file ] + outputs = [ linker_file ] + args = [ + "--format=" + current_os, + rebase_path(inputs[0], root_build_dir), + rebased_linker_file, + ] + + # Let targets depending on this receive the right ldflags. + public_configs = [ ":$config_name" ] + } +} diff --git a/llvm/utils/gn/build/symbol_exports.py b/llvm/utils/gn/build/symbol_exports.py new file mode 100644 index 000000000000..9d9c798db272 --- /dev/null +++ b/llvm/utils/gn/build/symbol_exports.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +"""Converts a .exports file to a format consumable by linkers. + +An .exports file is a file with one exported symbol per line. +This script converts a .exports file into a format that linkers +can understand: +- It prepends a `_` to each line for use with -exported_symbols_list for Darwin +- It writes a .def file for use with /DEF: for Windows +- It writes a linker script for use with --version-script elsewhere +""" + +import argparse +import sys + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--format', required=True, + choices=('linux','mac','win')) + parser.add_argument('source') + parser.add_argument('output') + args = parser.parse_args() + + symbols = open(args.source).readlines() + + if args.format == 'linux': + output_lines = (['FOO {\n', + ' global:\n',] + + [' %s;\n' % s.rstrip() for s in symbols] + + [' local: *;\n', + '}\n']) + elif args.format == 'mac': + output_lines = ['_' + s for s in symbols] + else: + assert args.format == 'win' + output_lines = ['EXPORTS\n'] + [' ' + s for s in symbols] + + open(args.output, 'w').writelines(output_lines) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn index d0cddcfaad04..e72af8fbc7a4 100644 --- a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn @@ -1,9 +1,9 @@ import("//clang/lib/ARCMigrate/enable.gni") +import("//llvm/utils/gn/build/symbol_exports.gni") import("//llvm/version.gni") # This build file is just enough to get check-clang to pass, it's missing # several things from the CMake build: -# - using libclang.exports # - a build target copying the Python bindings # - the GN linux build always builds without -fPIC (as if LLVM_ENABLE_PIC=OFF # in the CMake build), so libclang is always a static library on linux @@ -16,6 +16,10 @@ if (host_os != "win" && host_os != "mac") { libclang_target_type = "static_library" } +symbol_exports("exports") { + exports_file = "libclang.exports" +} + target(libclang_target_type, "libclang") { configs += [ "//llvm/utils/gn/build:clang_code" ] deps = [ @@ -37,6 +41,10 @@ target(libclang_target_type, "libclang") { deps += [ "//clang/lib/ARCMigrate" ] } + if (libclang_target_type == "shared_library") { + deps += [ ":exports" ] + } + defines = [] if (host_os == "win") { @@ -87,6 +95,4 @@ target(libclang_target_type, "libclang") { "-Wl,-rpath,@loader_path/../lib", ] } - - # FIXME: Use libclang.exports } diff --git a/llvm/utils/gn/secondary/llvm/lib/Transforms/Hello/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Transforms/Hello/BUILD.gn index 5ed1019c0933..a55d956ac3b6 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Transforms/Hello/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Transforms/Hello/BUILD.gn @@ -1,8 +1,16 @@ +import("//llvm/utils/gn/build/symbol_exports.gni") + assert(host_os != "win", "loadable modules not supported on win") +symbol_exports("exports") { + exports_file = "Hello.exports" +} + loadable_module("Hello") { output_name = "LLVMHello" deps = [ + ":exports", + # LLVMHello doesn't want to link in any LLVM code, it just # needs its headers. "//llvm/include/llvm/IR:public_tablegen", @@ -15,6 +23,4 @@ loadable_module("Hello") { # for loadable_modules for now. cflags = [ "-fPIC" ] } - - # FIXME: Use Hello.exports to remove all exports. } diff --git a/llvm/utils/gn/secondary/llvm/tools/bugpoint-passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/bugpoint-passes/BUILD.gn index f2ead028677a..1f7580bbbac6 100644 --- a/llvm/utils/gn/secondary/llvm/tools/bugpoint-passes/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/bugpoint-passes/BUILD.gn @@ -1,8 +1,16 @@ +import("//llvm/utils/gn/build/symbol_exports.gni") + assert(host_os != "win", "loadable modules not supported on win") +symbol_exports("exports") { + exports_file = "bugpoint.exports" +} + loadable_module("bugpoint-passes") { output_name = "BugpointPasses" deps = [ + ":exports", + # BugpointPasses doesn't want to link in any LLVM code, it just # needs its headers. "//llvm/include/llvm/IR:public_tablegen", @@ -15,6 +23,4 @@ loadable_module("bugpoint-passes") { # for loadable_modules for now. cflags = [ "-fPIC" ] } - - # FIXME: Use bugpoint.exports to remove all exports. } diff --git a/llvm/utils/gn/secondary/llvm/tools/lto/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/lto/BUILD.gn index 135b952c1535..418bdeb4fc06 100644 --- a/llvm/utils/gn/secondary/llvm/tools/lto/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/lto/BUILD.gn @@ -1,3 +1,4 @@ +import("//llvm/utils/gn/build/symbol_exports.gni") import("//llvm/version.gni") lto_target_type = "shared_library" @@ -7,6 +8,10 @@ if (host_os != "mac" && host_os != "win") { lto_target_type = "static_library" } +symbol_exports("exports") { + exports_file = "lto.exports" +} + target(lto_target_type, "lto") { output_name = "LTO" deps = [ @@ -24,6 +29,10 @@ target(lto_target_type, "lto") { "lto.cpp", ] + if (lto_target_type == "shared_library") { + deps += [ ":exports" ] + } + if (host_os == "mac") { ldflags = [ "-Wl,-compatibility_version,1", @@ -34,6 +43,4 @@ target(lto_target_type, "lto") { "-Wl,-rpath,@loader_path/../lib", ] } - - # FIXME: Use lto.exports }