Use pregenerated asm files when not building from Git.
This commit is contained in:
parent
495d25f930
commit
25add85a54
@ -25,8 +25,7 @@ include = [
|
||||
"mk/bottom_of_makefile.mk",
|
||||
"mk/top_of_makefile.mk",
|
||||
|
||||
"pregenerated/msvc-ring-asm-i686.lib",
|
||||
"pregenerated/msvc-ring-asm-x86_64.lib",
|
||||
"pregenerated/*",
|
||||
|
||||
"build.rs",
|
||||
|
||||
@ -265,6 +264,8 @@ untrusted = "0.3.2"
|
||||
[target.'cfg(any(target_os = "redox", all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies]
|
||||
lazy_static = "0.2.1"
|
||||
|
||||
|
||||
# Keep this in sync with `[dependencies]` in pregenerate_asm/Cargo.toml.
|
||||
[build-dependencies]
|
||||
# we do not use the gcc parallel feature because we do the
|
||||
# parallelism ourself. This gives us a much higher level of
|
||||
|
189
build.rs
189
build.rs
@ -65,7 +65,9 @@
|
||||
extern crate gcc;
|
||||
extern crate rayon;
|
||||
|
||||
use std::env;
|
||||
// In the `pregenerate_asm_main()` case we don't want to access (Cargo)
|
||||
// environment variables at all, so avoid `use std::env` here.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::fs::{self, DirEntry};
|
||||
@ -214,6 +216,8 @@ const RING_PERL_INCLUDES: &'static [&'static str] =
|
||||
|
||||
const RING_BUILD_FILE: &'static [&'static str] = &["build.rs"];
|
||||
|
||||
const PREGENERATED: &'static str = "pregenerated";
|
||||
|
||||
fn c_flags(target: &Target) -> &'static [&'static str] {
|
||||
if target.env != "msvc" {
|
||||
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
||||
@ -317,6 +321,27 @@ const ASM_TARGETS:
|
||||
];
|
||||
|
||||
fn main() {
|
||||
if let Ok(package_name) = std::env::var("CARGO_PKG_NAME") {
|
||||
if package_name == "ring" {
|
||||
ring_build_rs_main();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pregenerate_asm_main();
|
||||
}
|
||||
|
||||
fn ring_build_rs_main() {
|
||||
use std::env;
|
||||
|
||||
let mut cfg = rayon::Configuration::new();
|
||||
if let Ok(amt) = std::env::var("NUM_JOBS") {
|
||||
if let Ok(amt) = amt.parse() {
|
||||
cfg = cfg.set_num_threads(amt);
|
||||
}
|
||||
}
|
||||
rayon::initialize(cfg).unwrap();
|
||||
|
||||
for (key, value) in env::vars() {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
@ -324,16 +349,38 @@ fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let out_dir = PathBuf::from(out_dir);
|
||||
|
||||
// copied from gcc
|
||||
let mut cfg = rayon::Configuration::new();
|
||||
if let Ok(amt) = env::var("NUM_JOBS") {
|
||||
if let Ok(amt) = amt.parse() {
|
||||
cfg = cfg.set_num_threads(amt);
|
||||
}
|
||||
}
|
||||
rayon::initialize(cfg).unwrap();
|
||||
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
|
||||
let (obj_ext, obj_opt) = if env == "msvc" {
|
||||
("obj", "/Fo")
|
||||
} else {
|
||||
("o", "-o")
|
||||
};
|
||||
|
||||
let _ = rayon::join(check_all_files_tracked, || build_c_code(out_dir));
|
||||
let target = Target {
|
||||
arch: arch,
|
||||
os: os,
|
||||
env: env,
|
||||
obj_ext: obj_ext,
|
||||
obj_opt: obj_opt,
|
||||
is_debug: env::var("PROFILE").unwrap() == "debug",
|
||||
};
|
||||
|
||||
let _ = rayon::join(check_all_files_tracked,
|
||||
|| build_c_code(out_dir, &target));
|
||||
}
|
||||
|
||||
fn pregenerate_asm_main() {
|
||||
let pregenerated = PathBuf::from(PREGENERATED);
|
||||
std::fs::create_dir(&pregenerated).unwrap();
|
||||
|
||||
for &(target_arch, target_os, perlasm_format) in ASM_TARGETS {
|
||||
let perlasm_src_dsts =
|
||||
perlasm_src_dsts(&pregenerated, target_arch, target_os,
|
||||
perlasm_format);
|
||||
perlasm(&perlasm_src_dsts, target_arch, perlasm_format, None);
|
||||
}
|
||||
}
|
||||
|
||||
struct Target {
|
||||
@ -342,35 +389,17 @@ struct Target {
|
||||
env: String,
|
||||
obj_ext: &'static str,
|
||||
obj_opt: &'static str,
|
||||
is_debug: bool,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn new() -> Target {
|
||||
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
|
||||
let (obj_ext, obj_opt) = if env == "msvc" {
|
||||
("obj", "/Fo")
|
||||
} else {
|
||||
("o", "-o")
|
||||
};
|
||||
|
||||
Target {
|
||||
arch: arch,
|
||||
os: os,
|
||||
env: env,
|
||||
obj_ext: obj_ext,
|
||||
obj_opt: obj_opt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arch(&self) -> &str { &self.arch }
|
||||
pub fn os(&self) -> &str { &self.os }
|
||||
pub fn env(&self) -> &str { &self.env }
|
||||
pub fn is_debug(&self) -> bool { self.is_debug }
|
||||
}
|
||||
|
||||
fn build_c_code(out_dir: PathBuf) {
|
||||
let target = Target::new();
|
||||
fn build_c_code(out_dir: PathBuf, target: &Target) {
|
||||
let mut lib_target = out_dir.clone();
|
||||
lib_target.push("libring-core.a");
|
||||
let lib_target = lib_target.as_path();
|
||||
@ -387,19 +416,6 @@ fn build_c_code(out_dir: PathBuf) {
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
let mut srcs = Vec::new();
|
||||
let mut perlasm_srcs = Vec::new();
|
||||
for &(archs, src_path) in RING_SRCS {
|
||||
if archs.is_empty() || archs.contains(&target.arch()) {
|
||||
let src_path = PathBuf::from(src_path);
|
||||
if src_path.extension().unwrap().to_str().unwrap() == "pl" {
|
||||
perlasm_srcs.push(src_path);
|
||||
} else {
|
||||
srcs.push(src_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_none_or_equals<T>(opt: Option<T>, other: T)
|
||||
-> bool where T: PartialEq {
|
||||
if let Some(value) = opt {
|
||||
@ -413,11 +429,30 @@ fn build_c_code(out_dir: PathBuf) {
|
||||
let &(entry_arch, entry_os, _) = *entry;
|
||||
entry_arch == target.arch() && is_none_or_equals(entry_os, target.os())
|
||||
}).unwrap();
|
||||
let additional = perlasm_srcs.par_iter()
|
||||
.weight_max()
|
||||
.map(|src_path|
|
||||
make_asm(&src_path, target.arch(), target.os(), perlasm_format,
|
||||
includes_modified, &out_dir))
|
||||
|
||||
let use_pregenerated = std::fs::metadata(".git").is_err();
|
||||
|
||||
let asm_dir = if use_pregenerated {
|
||||
PathBuf::from(PREGENERATED)
|
||||
} else {
|
||||
out_dir.clone()
|
||||
};
|
||||
|
||||
let perlasm_src_dsts =
|
||||
perlasm_src_dsts(&asm_dir, target.arch(), Some(target.os()),
|
||||
perlasm_format);
|
||||
|
||||
if !use_pregenerated {
|
||||
perlasm(&perlasm_src_dsts[..], target.arch(), perlasm_format,
|
||||
Some(includes_modified));
|
||||
}
|
||||
|
||||
let asm_srcs = perlasm_src_dsts.into_iter()
|
||||
.map(|(_src, dst)| dst)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let srcs = sources_for_arch(target.arch()).into_iter()
|
||||
.filter(|p| !is_perlasm(&p))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let test_srcs = RING_TEST_SRCS.iter()
|
||||
@ -427,13 +462,13 @@ fn build_c_code(out_dir: PathBuf) {
|
||||
// XXX: Ideally, ring-test would only be built for `cargo test`, but Cargo
|
||||
// can't do that yet.
|
||||
let ((), ()) = rayon::join(
|
||||
|| build_library("ring-core", lib_target, &additional[..], &srcs[..],
|
||||
|| build_library("ring-core", lib_target, &asm_srcs[..], &srcs[..],
|
||||
&target, out_dir.clone(), includes_modified),
|
||||
|| build_library("ring-test", test_target, &[], &test_srcs[..],
|
||||
&target, out_dir.clone(), includes_modified));
|
||||
|
||||
if target.env() != "msvc" {
|
||||
let libcxx = if use_libcxx(&target) {
|
||||
let libcxx = if use_libcxx(target) {
|
||||
"c++"
|
||||
} else {
|
||||
"stdc++"
|
||||
@ -555,7 +590,7 @@ fn cc(file: &Path, ext: &str, target: &Target, out_dir: &Path) -> Command {
|
||||
(_, "msvc") => {},
|
||||
_ => { let _ = c.flag("-g3"); },
|
||||
};
|
||||
if env::var("PROFILE").unwrap() != "debug" {
|
||||
if !target.is_debug() {
|
||||
let _ = c.define("NDEBUG", None);
|
||||
if target.env() == "msvc" {
|
||||
let _ = c.flag("/Oi"); // Generate intrinsic functions.
|
||||
@ -634,29 +669,61 @@ fn run_command_with_args<S>(command_name: S, args: &[String])
|
||||
}
|
||||
}
|
||||
|
||||
fn make_asm(p: &Path, arch: &str, os: &str, perlasm_format: &str,
|
||||
includes_modified: SystemTime, out_dir: &Path) -> PathBuf {
|
||||
let src_stem = p.file_stem().expect("source file without basename");
|
||||
fn sources_for_arch(arch: &str) -> Vec<PathBuf> {
|
||||
RING_SRCS.iter()
|
||||
.filter(|&&(ref archs, _)| archs.is_empty() || archs.contains(&arch))
|
||||
.map(|&(_, ref p)| PathBuf::from(p))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn perlasm_src_dsts(out_dir: &Path, arch: &str, os: Option<&str>,
|
||||
perlasm_format: &str) -> Vec<(PathBuf, PathBuf)> {
|
||||
sources_for_arch(arch).iter()
|
||||
.filter(|p| is_perlasm(p))
|
||||
.map(|src| (src.clone(), asm_path(out_dir, src, os, perlasm_format)))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn is_perlasm(path: &PathBuf) -> bool {
|
||||
path.extension().unwrap().to_str().unwrap() == "pl"
|
||||
}
|
||||
|
||||
fn asm_path(out_dir: &Path, src: &Path, os: Option<&str>, perlasm_format: &str)
|
||||
-> PathBuf {
|
||||
let src_stem = src.file_stem().expect("source file without basename");
|
||||
|
||||
let mut dst = PathBuf::from(out_dir);
|
||||
let dst_stem = src_stem.to_str().unwrap();
|
||||
let dst_extension = if os == "windows" { "asm" } else { "S" };
|
||||
let dst_extension = if os == Some("windows") { "asm" } else { "S" };
|
||||
let dst_filename =
|
||||
format!("{}-{}.{}", dst_stem, perlasm_format, dst_extension);
|
||||
dst.push(dst_filename);
|
||||
dst
|
||||
}
|
||||
|
||||
fn perlasm(src_dst: &[(PathBuf, PathBuf)], arch: &str,
|
||||
perlasm_format: &str, includes_modified: Option<SystemTime>) {
|
||||
for &(ref src, ref dst) in src_dst {
|
||||
if let Some(includes_modified) = includes_modified {
|
||||
if !need_run(src, dst, includes_modified) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if need_run(p, dst.as_path(), includes_modified) {
|
||||
let mut args = Vec::<String>::new();
|
||||
args.push(p.to_string_lossy().into_owned());
|
||||
args.push(src.to_string_lossy().into_owned());
|
||||
args.push(perlasm_format.to_owned());
|
||||
if arch == "x86" {
|
||||
args.push("-fPIC".into());
|
||||
args.push("-DOPENSSL_IA32_SSE2".into());
|
||||
}
|
||||
args.push(dst.to_str().expect("Could not convert path").into());
|
||||
// Work around PerlAsm issue for ARM and AAarch64 targets by replacing
|
||||
// back slashes with forward slashes.
|
||||
let dst =
|
||||
dst.to_str().expect("Could not convert path").replace("\\", "/");
|
||||
args.push(dst);
|
||||
run_command_with_args(&get_command("PERL_EXECUTABLE", "perl"), &args);
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
fn need_run(source: &Path, target: &Path, includes_modified: SystemTime)
|
||||
@ -679,7 +746,7 @@ fn file_modified(path: &Path) -> SystemTime {
|
||||
}
|
||||
|
||||
fn get_command(var: &str, default: &str) -> String {
|
||||
env::var(var).unwrap_or(default.into())
|
||||
std::env::var(var).unwrap_or(default.into())
|
||||
}
|
||||
|
||||
fn check_all_files_tracked() {
|
||||
|
@ -1,9 +1,15 @@
|
||||
|
||||
# This only works on Windows, using MinGW.
|
||||
set -eux -o pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
cargo clean
|
||||
rm -Rf pregenerated/msvc*.lib
|
||||
RING_PREGENERATED=GENERATE cargo build -vv --target=x86_64-pc-windows-msvc
|
||||
RING_PREGENERATED=GENERATE cargo build -vv --target=i686-pc-windows-msvc
|
||||
# Make sure the current tree isn't dirty.
|
||||
# https://stackoverflow.com/a/5737794
|
||||
if [[ $(git status --porcelain | wc -c) -ne 0 ]]; then
|
||||
echo Repository is dirty.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
(cd pregenerate_asm && cargo clean && cargo build)
|
||||
./pregenerate_asm/target/debug/pregenerate_asm
|
||||
cargo package --allow-dirty
|
||||
|
16
pregenerate_asm/Cargo.toml
Normal file
16
pregenerate_asm/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
authors = ["Brian Smith <brian@briansmith.org>"]
|
||||
name = "pregenerate_asm"
|
||||
version = "0.0.1"
|
||||
|
||||
[[bin]]
|
||||
name = "pregenerate_asm"
|
||||
path = "../build.rs"
|
||||
|
||||
# Keep this in sync with `[build-dependencies]` in ../Cargo.toml.
|
||||
[dependencies]
|
||||
# we do not use the gcc parallel feature because we do the
|
||||
# parallelism ourself. This gives us a much higher level of
|
||||
# control about what should be parallised in which way
|
||||
gcc = "0.3"
|
||||
rayon = "0.6"
|
Loading…
x
Reference in New Issue
Block a user