about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2024-10-16 22:41:07 -0500
committerTrevor Gross <tmgross@umich.edu>2024-10-28 12:59:38 -0500
commit0acb3e2b50781a59c5932b4af71fe7a8b20d0e1a (patch)
tree46fc09b18d6125cb879443a1a49f3c5333b124b5 /library
parent56deb13bd4d767193bf49b3ff137533706398bbf (diff)
downloadrust-0acb3e2b50781a59c5932b4af71fe7a8b20d0e1a.tar.gz
rust-0acb3e2b50781a59c5932b4af71fe7a8b20d0e1a.zip
Collect all function names to an array
Use a build script for `libm-test` to enumerate all symbols provided by
`libm` and provide this list in a variable. This will allow us to make
sure no functions are missed anytime they must be manually listed.

Additionally, introduce some helper config options.
Diffstat (limited to 'library')
-rw-r--r--library/compiler-builtins/libm/crates/libm-test/build.rs100
-rw-r--r--library/compiler-builtins/libm/crates/libm-test/src/lib.rs3
2 files changed, 100 insertions, 3 deletions
diff --git a/library/compiler-builtins/libm/crates/libm-test/build.rs b/library/compiler-builtins/libm/crates/libm-test/build.rs
index 9653bd83013..472dec9d33e 100644
--- a/library/compiler-builtins/libm/crates/libm-test/build.rs
+++ b/library/compiler-builtins/libm/crates/libm-test/build.rs
@@ -1,10 +1,106 @@
+use std::fmt::Write;
+use std::path::PathBuf;
+use std::{env, fs};
+
 fn main() {
+    let cfg = Config::from_env();
+
+    emit_optimization_cfg(&cfg);
+    emit_cfg_shorthands(&cfg);
+    list_all_tests(&cfg);
+
     #[cfg(feature = "test-musl-serialized")]
-    musl_reference_tests::generate();
+    musl_serialized_tests::generate();
+}
+
+#[allow(dead_code)]
+struct Config {
+    manifest_dir: PathBuf,
+    out_dir: PathBuf,
+    opt_level: u8,
+    target_arch: String,
+    target_env: String,
+    target_family: Option<String>,
+    target_os: String,
+    target_string: String,
+    target_vendor: String,
+    target_features: Vec<String>,
+}
+
+impl Config {
+    fn from_env() -> Self {
+        let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
+            .map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
+            .unwrap_or_default();
+
+        Self {
+            manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
+            out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
+            opt_level: env::var("OPT_LEVEL").unwrap().parse().unwrap(),
+            target_arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
+            target_env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
+            target_family: env::var("CARGO_CFG_TARGET_FAMILY").ok(),
+            target_os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
+            target_string: env::var("TARGET").unwrap(),
+            target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
+            target_features,
+        }
+    }
+}
+
+/// Some tests are extremely slow. Emit a config option based on optimization level.
+fn emit_optimization_cfg(cfg: &Config) {
+    println!("cargo::rustc-check-cfg=cfg(optimizations_enabled)");
+
+    if cfg.opt_level >= 2 {
+        println!("cargo::rustc-cfg=optimizations_enabled");
+    }
+}
+
+/// Provide an alias for common longer config combinations.
+fn emit_cfg_shorthands(cfg: &Config) {
+    println!("cargo::rustc-check-cfg=cfg(x86_no_sse)");
+    if cfg.target_arch == "x86" && !cfg.target_features.iter().any(|f| f == "sse") {
+        // Shorthand to detect i586 targets
+        println!("cargo::rustc-cfg=x86_no_sse");
+    }
+}
+
+/// Create a list of all source files in an array. This can be used for making sure that
+/// all functions are tested or otherwise covered in some way.
+// FIXME: it would probably be better to use rustdoc JSON output to get public functions.
+fn list_all_tests(cfg: &Config) {
+    let math_src = cfg.manifest_dir.join("../../src/math");
+
+    let mut files = fs::read_dir(math_src)
+        .unwrap()
+        .map(|f| f.unwrap().path())
+        .filter(|entry| entry.is_file())
+        .map(|f| f.file_stem().unwrap().to_str().unwrap().to_owned())
+        .collect::<Vec<_>>();
+    files.sort();
+
+    let mut s = "pub const ALL_FUNCTIONS: &[&str] = &[".to_owned();
+    for f in files {
+        if f == "mod" {
+            // skip mod.rs
+            continue;
+        }
+        write!(s, "\"{f}\",").unwrap();
+    }
+    write!(s, "];").unwrap();
+
+    let outfile = cfg.out_dir.join("all_files.rs");
+    fs::write(outfile, s).unwrap();
 }
 
+/// At build time, generate the output of what the corresponding `*musl` target does with a range
+/// of inputs.
+///
+/// Serialize that target's output, run the same thing with our symbols, then load and compare
+/// the resulting values.
 #[cfg(feature = "test-musl-serialized")]
-mod musl_reference_tests {
+mod musl_serialized_tests {
     use std::path::PathBuf;
     use std::process::Command;
     use std::{env, fs};
diff --git a/library/compiler-builtins/libm/crates/libm-test/src/lib.rs b/library/compiler-builtins/libm/crates/libm-test/src/lib.rs
index 8b137891791..32c0618964f 100644
--- a/library/compiler-builtins/libm/crates/libm-test/src/lib.rs
+++ b/library/compiler-builtins/libm/crates/libm-test/src/lib.rs
@@ -1 +1,2 @@
-
+// List of all files present in libm's source
+include!(concat!(env!("OUT_DIR"), "/all_files.rs"));