Skip to content

Commit 12e83af

Browse files
committed
build: Further split up build script.
Split up build/build.rs into build/build/*.rs and split build/cargo.rs into {build/main.rs, build/build/cargo.rs}. ``` git diff HEAD^1:build/build.rs build/build/c.rs git diff HEAD^1:build/build.rs build/build/core.rs git diff HEAD^1:build/build.rs build/build/target.rs git diff HEAD^1:build/cargo.rs build/main.rs git diff HEAD^1:build/cargo.rs build/build/cargo.rs ```
1 parent 76a60bb commit 12e83af

9 files changed

Lines changed: 550 additions & 436 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
build = "build/cargo.rs"
2+
build = "build/main.rs"
33
categories = ["cryptography", "no-std"]
44
description = "An experiment."
55
edition = "2024"

build/build/c.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright 2015-2026 Brian Smith.
2+
//
3+
// Permission to use, copy, modify, and/or distribute this software for any
4+
// purpose with or without fee is hereby granted, provided that the above
5+
// copyright notice and this permission notice appear in all copies.
6+
//
7+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10+
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12+
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13+
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14+
15+
//! A wrapper around cc-rs.
16+
17+
// Avoid `std::env` here. All configuration should be done through `Target`,
18+
// `Profile`, and `Tools`.
19+
use super::target::*;
20+
use std::path::{Path, PathBuf};
21+
22+
fn cpp_flags(compiler: &cc::Tool) -> &'static [&'static str] {
23+
if !compiler.is_like_msvc() {
24+
static NON_MSVC_FLAGS: &[&str] = &[
25+
"-fvisibility=hidden",
26+
"-std=c1x", // GCC 4.6 requires "c1x" instead of "c11"
27+
"-Wall",
28+
"-Wbad-function-cast",
29+
"-Wcast-align",
30+
"-Wcast-qual",
31+
"-Wconversion",
32+
"-Wmissing-field-initializers",
33+
"-Wmissing-include-dirs",
34+
"-Wnested-externs",
35+
"-Wredundant-decls",
36+
"-Wshadow",
37+
"-Wsign-compare",
38+
"-Wsign-conversion",
39+
"-Wstrict-prototypes",
40+
"-Wundef",
41+
"-Wuninitialized",
42+
];
43+
NON_MSVC_FLAGS
44+
} else {
45+
static MSVC_FLAGS: &[&str] = &[
46+
"/Gy", // Enable function-level linking.
47+
"/Zc:wchar_t",
48+
"/Zc:forScope",
49+
"/Zc:inline",
50+
// Warnings.
51+
"/W4",
52+
"/wd4127", // C4127: conditional expression is constant
53+
"/wd4464", // C4464: relative include path contains '..'
54+
"/wd5045", /* C5045: Compiler will insert Spectre mitigation for memory load if
55+
* /Qspectre switch specified */
56+
];
57+
MSVC_FLAGS
58+
}
59+
}
60+
61+
pub struct Profile {
62+
/// Is this a debug build? This affects whether assertions might be enabled
63+
/// in the C code. For packaged builds, this should always be `false`.
64+
pub is_debug: bool,
65+
66+
/// true: Force warnings to be treated as errors.
67+
/// false: Use the default behavior (perhaps determined by `$CFLAGS`, etc.)
68+
pub force_warnings_into_errors: bool,
69+
70+
pub is_git: bool,
71+
}
72+
73+
fn new_build(
74+
target: &Target,
75+
profile: &Profile,
76+
c_root_dir: &Path,
77+
include_dir: &Path,
78+
) -> cc::Build {
79+
let mut b = cc::Build::new();
80+
configure_cc(&mut b, target, profile, c_root_dir, include_dir);
81+
b
82+
}
83+
84+
pub fn build_library<'a>(
85+
target: &Target,
86+
profile: &Profile,
87+
c_root_dir: &Path,
88+
lib_name: &str,
89+
srcs: impl Iterator<Item = &'a PathBuf>,
90+
include_dir: &Path,
91+
preassembled_objs: &[PathBuf],
92+
) {
93+
let mut c = new_build(target, profile, c_root_dir, include_dir);
94+
95+
// Compile all the (dirty) source files into object files.
96+
srcs.for_each(|src| {
97+
c.file(c_root_dir.join(src));
98+
});
99+
100+
preassembled_objs.iter().for_each(|obj| {
101+
c.object(obj);
102+
});
103+
104+
// Rebuild the library if necessary.
105+
let lib_path = target.out_dir.join(format!("lib{lib_name}.a"));
106+
107+
// Handled below.
108+
let _ = c.cargo_metadata(false);
109+
110+
c.compile(
111+
lib_path
112+
.file_name()
113+
.and_then(|f| f.to_str())
114+
.expect("No filename"),
115+
);
116+
117+
// Link the library. This works even when the library doesn't need to be
118+
// rebuilt.
119+
println!("cargo:rustc-link-lib=static={lib_name}");
120+
println!(
121+
"cargo:rustc-link-search=native={}",
122+
target.out_dir.to_str().expect("Invalid path")
123+
);
124+
}
125+
126+
fn configure_cc(
127+
c: &mut cc::Build,
128+
target: &Target,
129+
profile: &Profile,
130+
c_root_dir: &Path,
131+
include_dir: &Path,
132+
) {
133+
// FIXME: On Windows AArch64 we currently must use Clang to compile C code.
134+
// clang-cl emulates the cl.exe command line, `$CFLAGS`, etc.
135+
if target.os == WINDOWS && target.arch == AARCH64 {
136+
let _: &_ = c.prefer_clang_cl_over_msvc(true);
137+
};
138+
let compiler = c.get_compiler();
139+
140+
let _ = c.include(c_root_dir.join("include"));
141+
let _ = c.include(include_dir);
142+
for f in cpp_flags(&compiler) {
143+
let _ = c.flag(f);
144+
}
145+
146+
if APPLE_ABI.contains(&target.os.as_str()) {
147+
// ``-gfull`` is required for Darwin's |-dead_strip|.
148+
let _ = c.flag("-gfull");
149+
} else if !compiler.is_like_msvc() {
150+
let _ = c.flag("-g3");
151+
};
152+
153+
if !profile.is_debug {
154+
let _ = c.define("NDEBUG", None);
155+
}
156+
157+
if target.arch == X86 {
158+
let is_msvc_not_clang_cl = compiler.is_like_msvc() && !compiler.is_like_clang_cl();
159+
if !is_msvc_not_clang_cl {
160+
let _ = c.flag("-msse2");
161+
}
162+
}
163+
164+
// Allow cross-compiling without a target sysroot for these targets.
165+
if (target.arch == WASM32)
166+
|| (target.os == "linux" && target.env == "musl" && target.arch != X86_64)
167+
{
168+
// TODO: Expand this to non-clang compilers in 0.17.0 if practical.
169+
if compiler.is_like_clang() {
170+
let _ = c.flag("-nostdlibinc");
171+
let _ = c.define("RING_CORE_NOSTDLIBINC", "1");
172+
}
173+
}
174+
175+
if profile.force_warnings_into_errors {
176+
c.warnings_into_errors(true);
177+
}
178+
}

build/build/cargo.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright 2015-2016 Brian Smith.
2+
//
3+
// Permission to use, copy, modify, and/or distribute this software for any
4+
// purpose with or without fee is hereby granted, provided that the above
5+
// copyright notice and this permission notice appear in all copies.
6+
//
7+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10+
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12+
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13+
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14+
15+
//! Cargo-specific build logic that isn't specific to this project.
16+
17+
use super::{Profile, Target, target::Endian};
18+
// Avoid `std::env` here; use `self::env` instead.
19+
use std::{
20+
fs::{self},
21+
path::{Path, PathBuf},
22+
};
23+
24+
pub mod env {
25+
use std::ffi::OsString;
26+
27+
macro_rules! define_env {
28+
{ $vis:vis $NAME:ident : $ty:ident } => {
29+
$vis const $NAME: EnvVar = EnvVar {
30+
name: stringify!($NAME),
31+
ty: EnvVarTy::$ty,
32+
};
33+
};
34+
}
35+
36+
enum EnvVarTy {
37+
RerunIfChanged,
38+
SetByCargo,
39+
}
40+
41+
pub struct EnvVar {
42+
pub name: &'static str,
43+
ty: EnvVarTy,
44+
}
45+
46+
/// Read an environment variable and optionally tell Cargo that we depend on it.
47+
///
48+
/// The env var is static since we intend to only read a static set of environment
49+
/// variables.
50+
pub fn var_os(env_var: &'static EnvVar) -> Option<OsString> {
51+
match env_var.ty {
52+
EnvVarTy::RerunIfChanged => {
53+
println!("cargo:rerun-if-env-changed={}", env_var.name);
54+
}
55+
EnvVarTy::SetByCargo => {}
56+
}
57+
std::env::var_os(env_var.name)
58+
}
59+
60+
pub fn var(env_var: &'static EnvVar) -> Option<String> {
61+
var_os(env_var).and_then(|value| value.into_string().ok())
62+
}
63+
64+
// In alphabetical order
65+
define_env! { pub(super) CARGO_CFG_TARGET_ARCH: SetByCargo }
66+
define_env! { pub(super) CARGO_CFG_TARGET_ENDIAN: SetByCargo }
67+
define_env! { pub(super) CARGO_CFG_TARGET_ENV: SetByCargo }
68+
define_env! { pub(super) CARGO_CFG_TARGET_OS: SetByCargo }
69+
define_env! { pub(super) CARGO_MANIFEST_DIR: SetByCargo }
70+
define_env! { pub(super) CARGO_MANIFEST_LINKS: SetByCargo }
71+
define_env! { pub(super) CARGO_PKG_NAME: SetByCargo }
72+
define_env! { pub(super) CARGO_PKG_VERSION_MAJOR: SetByCargo }
73+
define_env! { pub(super) CARGO_PKG_VERSION_MINOR: SetByCargo }
74+
define_env! { pub(super) CARGO_PKG_VERSION_PATCH: SetByCargo }
75+
define_env! { pub(super) CARGO_PKG_VERSION_PRE: SetByCargo }
76+
define_env! { pub(super) DEBUG: SetByCargo }
77+
define_env! { pub(super) OUT_DIR: SetByCargo }
78+
79+
// XXX: These don't belong here.
80+
define_env! { pub PERL_EXECUTABLE: RerunIfChanged }
81+
define_env! { pub RING_PREGENERATE_ASM: RerunIfChanged }
82+
}
83+
84+
pub fn root_dir() -> PathBuf {
85+
// Avoid assuming the working directory is the same is the $CARGO_MANIFEST_DIR so that toolchains
86+
// which may assume other working directories can still build this code.
87+
PathBuf::from(
88+
env::var_os(&env::CARGO_MANIFEST_DIR).expect("CARGO_MANIFEST_DIR should always be set"),
89+
)
90+
}
91+
92+
pub fn extern_c_prefix(component: &str) -> String {
93+
// Keep in sync with `core_name_and_version!` in prefixed.rs.
94+
let core_name_and_version = [
95+
&env::var(&env::CARGO_PKG_NAME).unwrap(),
96+
component,
97+
&env::var(&env::CARGO_PKG_VERSION_MAJOR).unwrap(),
98+
&env::var(&env::CARGO_PKG_VERSION_MINOR).unwrap(),
99+
&env::var(&env::CARGO_PKG_VERSION_PATCH).unwrap(),
100+
&env::var(&env::CARGO_PKG_VERSION_PRE).unwrap(), // Often empty
101+
]
102+
.join("_");
103+
// Ensure `links` in Cargo.toml is consistent with the version.
104+
assert_eq!(
105+
&env::var(&env::CARGO_MANIFEST_LINKS).unwrap(),
106+
&core_name_and_version
107+
);
108+
core_name_and_version
109+
}
110+
111+
impl Target {
112+
pub fn new_from_env() -> Self {
113+
let arch = env::var(&env::CARGO_CFG_TARGET_ARCH).unwrap();
114+
let os = env::var(&env::CARGO_CFG_TARGET_OS).unwrap();
115+
let env = env::var(&env::CARGO_CFG_TARGET_ENV).unwrap();
116+
let endian = env::var(&env::CARGO_CFG_TARGET_ENDIAN).unwrap();
117+
let endian = if endian == "little" {
118+
Endian::Little
119+
} else {
120+
Endian::Other
121+
};
122+
123+
let out_dir = PathBuf::from(env::var_os(&env::OUT_DIR).unwrap());
124+
125+
Self {
126+
arch,
127+
os,
128+
env,
129+
endian,
130+
out_dir,
131+
}
132+
}
133+
}
134+
135+
impl Profile {
136+
pub fn new_from_env(root_dir: &Path) -> Self {
137+
let is_git = fs::metadata(root_dir.join(".git")).is_ok();
138+
139+
// Published builds are always built in release mode.
140+
let is_debug = is_git && env::var(&env::DEBUG).unwrap() != "false";
141+
142+
// During local development, force warnings in non-Rust code to be treated
143+
// as errors. Since warnings are highly compiler-dependent and compilers
144+
// don't maintain backward compatibility w.r.t. which warnings they issue,
145+
// don't do this for packaged builds.
146+
let force_warnings_into_errors = is_git;
147+
148+
Self {
149+
is_git,
150+
is_debug,
151+
force_warnings_into_errors,
152+
}
153+
}
154+
}
155+
156+
// TODO: We should emit `cargo:rerun-if-changed-env` for the various
157+
// environment variables that affect the build.
158+
pub fn emit_rerun_if_changed<'a>(paths: impl Iterator<Item = &'a Path>) {
159+
paths.for_each(|path| {
160+
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
161+
})
162+
}

0 commit comments

Comments
 (0)