From 81f254c32a1d9a1dc899749d8e8b905e94283459 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 19 Jul 2018 11:37:57 +0200 Subject: [PATCH] Exfiltrate more linker flags with get_rust_ldflags.py --- BUILD.gn | 6 +++ ..._default_libs.cmd => get_rust_ldflags.cmd} | 0 ...tc_default_libs.py => get_rust_ldflags.py} | 50 ++++++++++++++++--- build_extra/rust/rust.gni | 31 ++++-------- 4 files changed, 60 insertions(+), 27 deletions(-) rename build_extra/rust/{get_rustc_default_libs.cmd => get_rust_ldflags.cmd} (100%) rename build_extra/rust/{get_rustc_default_libs.py => get_rust_ldflags.py} (54%) diff --git a/BUILD.gn b/BUILD.gn index b79fa9358f8f25..16e18d7249bcde 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -20,6 +20,12 @@ config("deno_config") { if (is_debug) { defines = [ "DEBUG" ] } + if (is_mac) { + libs = [ "resolv" ] + } + if (is_win) { + libs = [ "userenv.lib" ] + } } rust_executable("deno") { diff --git a/build_extra/rust/get_rustc_default_libs.cmd b/build_extra/rust/get_rust_ldflags.cmd similarity index 100% rename from build_extra/rust/get_rustc_default_libs.cmd rename to build_extra/rust/get_rust_ldflags.cmd diff --git a/build_extra/rust/get_rustc_default_libs.py b/build_extra/rust/get_rust_ldflags.py similarity index 54% rename from build_extra/rust/get_rustc_default_libs.py rename to build_extra/rust/get_rust_ldflags.py index 7e5f1b27b84940..8354155eea47c3 100755 --- a/build_extra/rust/get_rustc_default_libs.py +++ b/build_extra/rust/get_rust_ldflags.py @@ -64,13 +64,51 @@ def main(): os.close(argsfile_fd) os.unlink(argsfile_path) - # Write all linker inputs that are dependencies to stdout. - # Note that in addition to all .rlib files, we also capture a file named - # `crate_name.crate.allocator.rcgu.o`, which contains the implementation - # of `__rust_malloc()`, `__rust_free()` etc. + # From the list of captured linker arguments, build a list of ldflags that + # we actually need. + ldflags = [] + next_arg_is_flag_value = False for arg in args: - if arg.endswith(".rlib") or arg.endswith(".crate.allocator.rcgu.o"): - print(arg) + # Note that within the following if/elif blocks, `pass` means `arg` + # gets included in `ldflags`. The final `else` clause filters out + # unrecognized/unwanted flags. + if next_arg_is_flag_value: + # We're looking at a value that follows certain parametric flags, + # e.g. the path in '-L '. + next_arg_is_flag_value = False + elif arg.endswith(".rlib"): + # Built-in Rust library, e.g. `libstd-8524caae8408aac2.rlib`. + pass + elif arg.endswith(".crate.allocator.rcgu.o"): + # This file is needed because it contains certain allocator + # related symbols (e.g. `__rust_alloc`, `__rust_oom`). + # The Rust compiler normally generates this file just before + # linking an executable. We pass `-Csave-temps` to rustc so it + # doesn't delete the file when it's done linking. + pass + elif arg.endswith(".lib") and not arg.startswith("msvcrt"): + # Include most Windows static/import libraries (e.g. `ws2_32.lib`). + # However we exclude Rusts choice of C runtime (mvcrt*.lib), since + # it makes poor choices. + pass + elif arg == "-l" or arg == "-L": + # `-l `: Link with library (GCC style). + # `-L `: Linker search path (GCC style). + next_arg_is_flag_value = True # Ensure flag argument is captured. + elif arg == "-Wl,--start-group" or arg == "-Wl,--end-group": + # Start or end of an archive group (GCC style). + pass + elif arg.upper().startswith("/LIBPATH:"): + # `/LIBPATH:`: Linker search path (Microsoft style). + pass + else: + # No matches -- don't add this flag to ldflags. + continue + + ldflags += [arg] + + # Write the filtered ldflags to stdout, separated by newline characters. + sys.stdout.write("\n".join(ldflags)) if __name__ == '__main__': diff --git a/build_extra/rust/rust.gni b/build_extra/rust/rust.gni index 80ab646aed3b0e..ebdd33e07fc803 100644 --- a/build_extra/rust/rust.gni +++ b/build_extra/rust/rust.gni @@ -1,20 +1,12 @@ empty_rs_path = rebase_path("empty.rs", root_build_dir) -rust_default_libs_bin = - exec_script("get_rustc_default_libs.py", [ empty_rs_path ], "list lines") -rust_default_libs_test = exec_script("get_rustc_default_libs.py", - [ - empty_rs_path, - "--test", - ], - "list lines") - -rust_required_system_libs = [] -if (current_os == "mac") { - rust_required_system_libs += [ "resolv" ] -} -if (current_os == "win") { - rust_required_system_libs += [ "userenv.lib" ] -} +rust_bin_ldflags = + exec_script("get_rust_ldflags.py", [ empty_rs_path ], "list lines") +rust_test_ldflags = exec_script("get_rust_ldflags.py", + [ + empty_rs_path, + "--test", + ], + "list lines") declare_args() { # Absolute path of rust build files. @@ -186,7 +178,6 @@ template("rust_staticlib") { "testonly", ]) crate_type = "staticlib" - libs = rust_required_system_libs } } @@ -203,13 +194,11 @@ template("rust_executable") { forward_variables_from(invoker, "*") if (defined(is_test) && is_test) { - ldflags = rust_default_libs_test + ldflags = rust_test_ldflags } else { - ldflags = rust_default_libs_bin + ldflags = rust_bin_ldflags } - libs = rust_required_system_libs - if (!defined(deps)) { deps = [] }