mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 04:24:26 +00:00 
			
		
		
		
	 016bc61312
			
		
	
	
		016bc61312
		
			
		
	
	
	
	
		
			
			The `rustc` probe done in our build scripts needs to pass `--target` to get the correct configuration, which usually comes from the `TARGET` environment variable. However, for targets specified via a `target.json` file, `TARGET` gets set to the file name without an extension or path. `rustc` will check a search path to attempt to locate the file, but this is likely to fail since the directory where Cargo invokes build scripts (and hence where those scripts invoke `rustc`) might not have any relation to the JSON spec file. Resolve this for now by leaving `f16` and `f128` disabled if the `rustc` command fails. Result of the discussion at CARGO-14208 may eventually provide a better solution. A CI test is also added since custom JSON files are an edge case that could fail in other ways. I verified this fails without the fix here. The JSON file is the output for `thumbv7em-none-eabi`, just renamed so `rustc` doesn't identify it.
		
			
				
	
	
		
			174 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // Configuration shared with both libm and libm-test
 | |
| 
 | |
| use std::path::PathBuf;
 | |
| use std::process::{Command, Stdio};
 | |
| use std::{env, str};
 | |
| 
 | |
| #[allow(dead_code)]
 | |
| pub struct Config {
 | |
|     pub manifest_dir: PathBuf,
 | |
|     pub out_dir: PathBuf,
 | |
|     pub opt_level: String,
 | |
|     pub cargo_features: Vec<String>,
 | |
|     pub target_triple: String,
 | |
|     pub target_arch: String,
 | |
|     pub target_env: String,
 | |
|     pub target_family: Option<String>,
 | |
|     pub target_os: String,
 | |
|     pub target_string: String,
 | |
|     pub target_vendor: String,
 | |
|     pub target_features: Vec<String>,
 | |
|     pub reliable_f128: bool,
 | |
|     pub reliable_f16: bool,
 | |
| }
 | |
| 
 | |
| impl Config {
 | |
|     pub fn from_env() -> Self {
 | |
|         let target_triple = env::var("TARGET").unwrap();
 | |
|         let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
 | |
|             .map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
 | |
|             .unwrap_or_default();
 | |
|         let cargo_features = env::vars()
 | |
|             .filter_map(|(name, _value)| name.strip_prefix("CARGO_FEATURE_").map(ToOwned::to_owned))
 | |
|             .map(|s| s.to_lowercase().replace("_", "-"))
 | |
|             .collect();
 | |
| 
 | |
|         // Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
 | |
|         // to get consistent output regardless of channel (`f16`/`f128` config options are hidden
 | |
|         // on stable otherwise).
 | |
|         let mut cmd = Command::new(env::var("RUSTC").unwrap());
 | |
|         cmd.args(["--print=cfg", "--target", &target_triple])
 | |
|             .env("RUSTC_BOOTSTRAP", "1")
 | |
|             .stderr(Stdio::inherit());
 | |
|         let out = cmd
 | |
|             .output()
 | |
|             .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
 | |
|         let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
 | |
| 
 | |
|         // If we couldn't query `rustc` (e.g. a custom JSON target was used), make the safe
 | |
|         // choice and leave `f16` and `f128` disabled.
 | |
|         let rustc_output_ok = out.status.success();
 | |
|         let reliable_f128 =
 | |
|             rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f128");
 | |
|         let reliable_f16 =
 | |
|             rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f16");
 | |
| 
 | |
|         Self {
 | |
|             target_triple,
 | |
|             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(),
 | |
|             cargo_features,
 | |
|             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,
 | |
|             reliable_f128,
 | |
|             reliable_f16,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Libm gets most config options made available.
 | |
| #[allow(dead_code)]
 | |
| pub fn emit_libm_config(cfg: &Config) {
 | |
|     emit_intrinsics_cfg();
 | |
|     emit_arch_cfg();
 | |
|     emit_optimization_cfg(cfg);
 | |
|     emit_cfg_shorthands(cfg);
 | |
|     emit_cfg_env(cfg);
 | |
|     emit_f16_f128_cfg(cfg);
 | |
| }
 | |
| 
 | |
| /// Tests don't need most feature-related config.
 | |
| #[allow(dead_code)]
 | |
| pub fn emit_test_config(cfg: &Config) {
 | |
|     emit_optimization_cfg(cfg);
 | |
|     emit_cfg_shorthands(cfg);
 | |
|     emit_cfg_env(cfg);
 | |
|     emit_f16_f128_cfg(cfg);
 | |
| }
 | |
| 
 | |
| /// Simplify the feature logic for enabling intrinsics so code only needs to use
 | |
| /// `cfg(intrinsics_enabled)`.
 | |
| fn emit_intrinsics_cfg() {
 | |
|     println!("cargo:rustc-check-cfg=cfg(intrinsics_enabled)");
 | |
| 
 | |
|     // Disabled by default; `unstable-intrinsics` enables again; `force-soft-floats` overrides
 | |
|     // to disable.
 | |
|     if cfg!(feature = "unstable-intrinsics") && !cfg!(feature = "force-soft-floats") {
 | |
|         println!("cargo:rustc-cfg=intrinsics_enabled");
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Simplify the feature logic for enabling arch-specific features so code only needs to use
 | |
| /// `cfg(arch_enabled)`.
 | |
| fn emit_arch_cfg() {
 | |
|     println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
 | |
| 
 | |
|     // Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
 | |
|     if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
 | |
|         println!("cargo:rustc-cfg=arch_enabled");
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// 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 !matches!(cfg.opt_level.as_str(), "0" | "1") {
 | |
|         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");
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Reemit config that we make use of for test logging.
 | |
| fn emit_cfg_env(cfg: &Config) {
 | |
|     println!(
 | |
|         "cargo:rustc-env=CFG_CARGO_FEATURES={:?}",
 | |
|         cfg.cargo_features
 | |
|     );
 | |
|     println!("cargo:rustc-env=CFG_OPT_LEVEL={}", cfg.opt_level);
 | |
|     println!(
 | |
|         "cargo:rustc-env=CFG_TARGET_FEATURES={:?}",
 | |
|         cfg.target_features
 | |
|     );
 | |
| }
 | |
| 
 | |
| /// Configure whether or not `f16` and `f128` support should be enabled.
 | |
| fn emit_f16_f128_cfg(cfg: &Config) {
 | |
|     println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
 | |
|     println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
 | |
| 
 | |
|     // `unstable-float` enables these features.
 | |
|     if !cfg!(feature = "unstable-float") {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* See the compiler-builtins configure file for info about the meaning of these options */
 | |
| 
 | |
|     // If the feature is set, disable both of these types.
 | |
|     let no_f16_f128 = cfg.cargo_features.iter().any(|s| s == "no-f16-f128");
 | |
| 
 | |
|     println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
 | |
|     if cfg.reliable_f16 && !no_f16_f128 {
 | |
|         println!("cargo:rustc-cfg=f16_enabled");
 | |
|     }
 | |
| 
 | |
|     println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
 | |
|     if cfg.reliable_f128 && !no_f16_f128 {
 | |
|         println!("cargo:rustc-cfg=f128_enabled");
 | |
|     }
 | |
| }
 |