From 7362b566426f4b98c9360a6ce97af846231088b1 Mon Sep 17 00:00:00 2001 From: Georgy Moshkin <gmoshkin@picodata.io> Date: Wed, 29 Mar 2023 17:42:04 +0300 Subject: [PATCH] build: export symbols explicitly from generated code --- build.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- src/main.rs | 3 +++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/build.rs b/build.rs index 678d5defb2..fa55431954 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; +use std::io::Write; use std::panic::Location; use std::path::Path; use std::process::Command; @@ -34,18 +36,11 @@ fn main() { std::env::set_var("MAKEFLAGS", makeflags); } - if cfg!(target_os = "macos") { - // We don't want to strip unused symbols from the static libraries on - // the linking stage. This leads to problems with tarantool's `crypto` - // module (some symbols are used only by the ffi calls inside `crypto.lua` - // file and we are in trouble if they are stripped by the linker). - rustc::link_arg("-C link-dead-code=on"); - } - for (var, value) in std::env::vars() { println!("[{}:{}] {var}={value}", file!(), line!()); } + generate_export_stubs(&out_dir); build_tarantool(build_root); build_http(build_root); @@ -53,6 +48,46 @@ fn main() { println!("cargo:rerun-if-changed=http/http"); } +fn generate_export_stubs(out_dir: &str) { + let mut symbols = HashSet::with_capacity(1024); + let exports = std::fs::read_to_string("tarantool-sys/extra/exports").unwrap(); + read_symbols_into(&exports, &mut symbols); + let exports = std::fs::read_to_string("tarantool-sys/extra/exports_libcurl").unwrap(); + read_symbols_into(&exports, &mut symbols); + + let mut code = Vec::with_capacity(2048); + writeln!(code, "pub fn export_symbols() {{").unwrap(); + writeln!(code, " extern \"C\" {{").unwrap(); + for symbol in &symbols { + writeln!(code, " static {symbol}: *const ();").unwrap(); + } + writeln!(code, " }}").unwrap(); + // TODO: use std::hint::black_box, when we move to rust 1.66 + writeln!(code, " fn black_box(_: *const ()) {{}}").unwrap(); + writeln!(code, " unsafe {{").unwrap(); + for symbol in &symbols { + writeln!(code, " black_box({symbol});").unwrap(); + } + writeln!(code, " }}").unwrap(); + writeln!(code, "}}").unwrap(); + + let gen_path = std::path::Path::new(out_dir).join("export_symbols.rs"); + std::fs::write(gen_path, code).unwrap(); + + fn read_symbols_into<'a>(file_contents: &'a str, symbols: &mut HashSet<&'a str>) { + for line in file_contents.lines() { + let line = line.trim(); + if line.starts_with('#') { + continue; + } + if line.is_empty() { + continue; + } + symbols.insert(line); + } + } +} + fn build_http(build_root: &Path) { let build_dir = build_root.join("tarantool-http"); let build_dir_str = build_dir.display().to_string(); @@ -173,9 +208,11 @@ fn build_tarantool(build_root: &Path) { rustc::link_lib_static("shutdown"); rustc::link_lib_static("swim_udp"); rustc::link_lib_static("swim_ev"); + rustc::link_lib_static("symbols"); rustc::link_lib_static("cpu_feature"); rustc::link_lib_static("luajit"); rustc::link_lib_static("yaml_static"); + rustc::link_lib_static("xxhash"); if cfg!(target_os = "macos") { // OpenMP and Libunwind are builtin to the compiler on macos diff --git a/src/main.rs b/src/main.rs index e6332d5303..e9b3b84597 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,9 +10,12 @@ use picodata::Entrypoint; use picodata::IpcMessage; use tarantool::fiber; +include!(concat!(env!("OUT_DIR"), "/export_symbols.rs")); + mod test; fn main() -> ! { + export_symbols(); match args::Picodata::parse() { args::Picodata::Run(args) => main_run(args), args::Picodata::Test(args) => test::main_test(args), -- GitLab