[gn build] Use .export files

Just fixing an old TODO, no dramatic behavior change.

Differential Revision: https://reviews.llvm.org/D102843
This commit is contained in:
Nico Weber 2021-05-20 09:55:27 -04:00
parent f21f1eea05
commit fc9696130c
6 changed files with 136 additions and 9 deletions

View File

@ -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" ]
}
}

View File

@ -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())

View File

@ -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
}

View File

@ -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.
}

View File

@ -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.
}

View File

@ -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
}