2016-02-04 14:40:20 -10:00
|
|
|
// Copyright 2015-2016 Brian Smith.
|
2015-07-30 19:48:38 -04:00
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
|
|
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
2016-10-26 09:02:30 -10:00
|
|
|
// TODO: Deny `unused_qualifications` after
|
|
|
|
// https://github.com/rust-lang/rust/issues/37345 is fixed.
|
2016-02-04 14:40:20 -10:00
|
|
|
#![deny(
|
|
|
|
const_err,
|
|
|
|
dead_code,
|
|
|
|
deprecated,
|
|
|
|
exceeding_bitshifts,
|
|
|
|
fat_ptr_transmutes,
|
|
|
|
improper_ctypes,
|
|
|
|
missing_copy_implementations,
|
|
|
|
missing_debug_implementations,
|
|
|
|
mutable_transmutes,
|
|
|
|
no_mangle_const_items,
|
|
|
|
non_camel_case_types,
|
|
|
|
non_shorthand_field_patterns,
|
|
|
|
non_snake_case,
|
|
|
|
non_upper_case_globals,
|
|
|
|
overflowing_literals,
|
|
|
|
path_statements,
|
|
|
|
plugin_as_library,
|
|
|
|
private_no_mangle_fns,
|
|
|
|
private_no_mangle_statics,
|
|
|
|
stable_features,
|
|
|
|
trivial_casts,
|
|
|
|
trivial_numeric_casts,
|
|
|
|
unconditional_recursion,
|
|
|
|
unknown_crate_types,
|
|
|
|
unknown_lints,
|
|
|
|
unreachable_code,
|
|
|
|
unsafe_code,
|
|
|
|
unstable_features,
|
|
|
|
unused_allocation,
|
|
|
|
unused_assignments,
|
|
|
|
unused_attributes,
|
|
|
|
unused_comparisons,
|
|
|
|
unused_extern_crates,
|
|
|
|
unused_features,
|
|
|
|
unused_import_braces,
|
|
|
|
unused_imports,
|
|
|
|
unused_must_use,
|
|
|
|
unused_mut,
|
|
|
|
unused_parens,
|
|
|
|
unused_results,
|
|
|
|
unused_unsafe,
|
|
|
|
unused_variables,
|
|
|
|
variant_size_differences,
|
|
|
|
warnings,
|
|
|
|
while_true,
|
|
|
|
)]
|
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
extern crate gcc;
|
2017-02-07 23:29:00 +01:00
|
|
|
extern crate rayon;
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
// In the `pregenerate_asm_main()` case we don't want to access (Cargo)
|
|
|
|
// environment variables at all, so avoid `use std::env` here.
|
|
|
|
|
2016-10-26 09:58:25 -10:00
|
|
|
use std::path::{Path, PathBuf};
|
2017-02-19 23:22:21 -10:00
|
|
|
use std::process::Command;
|
2017-02-07 23:19:36 +01:00
|
|
|
use std::fs::{self, DirEntry};
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
use std::time::SystemTime;
|
2017-04-07 16:04:06 -07:00
|
|
|
use rayon::iter::{ParallelIterator, IndexedParallelIterator,
|
|
|
|
IntoParallelIterator, IntoParallelRefIterator};
|
2015-11-11 12:28:43 -10:00
|
|
|
|
2017-03-17 10:28:50 -10:00
|
|
|
const X86: &'static str = "x86";
|
|
|
|
const X86_64: &'static str = "x86_64";
|
|
|
|
const AARCH64: &'static str = "aarch64";
|
|
|
|
const ARM: &'static str = "arm";
|
2015-07-30 19:48:38 -04:00
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
2017-03-17 10:28:50 -10:00
|
|
|
const RING_SRCS: &'static [(&'static [&'static str], &'static str)] = &[
|
|
|
|
(&[], "crypto/aes/aes.c"),
|
|
|
|
(&[], "crypto/bn/add.c"),
|
|
|
|
(&[], "crypto/bn/bn.c"),
|
|
|
|
(&[], "crypto/bn/cmp.c"),
|
|
|
|
(&[], "crypto/bn/convert.c"),
|
|
|
|
(&[], "crypto/bn/div.c"),
|
|
|
|
(&[], "crypto/bn/exponentiation.c"),
|
|
|
|
(&[], "crypto/bn/gcd.c"),
|
|
|
|
(&[], "crypto/bn/generic.c"),
|
|
|
|
(&[], "crypto/bn/montgomery.c"),
|
|
|
|
(&[], "crypto/bn/montgomery_inv.c"),
|
|
|
|
(&[], "crypto/bn/mul.c"),
|
|
|
|
(&[], "crypto/bn/random.c"),
|
|
|
|
(&[], "crypto/bn/shift.c"),
|
|
|
|
(&[], "crypto/cipher/e_aes.c"),
|
|
|
|
(&[], "crypto/crypto.c"),
|
|
|
|
(&[], "crypto/curve25519/curve25519.c"),
|
|
|
|
(&[], "crypto/ec/ecp_nistz.c"),
|
|
|
|
(&[], "crypto/ec/ecp_nistz256.c"),
|
|
|
|
(&[], "crypto/ec/gfp_p256.c"),
|
|
|
|
(&[], "crypto/ec/gfp_p384.c"),
|
2017-03-17 11:36:03 -10:00
|
|
|
(&[], "crypto/limbs/limbs.c"),
|
2017-03-17 10:28:50 -10:00
|
|
|
(&[], "crypto/mem.c"),
|
|
|
|
(&[], "crypto/modes/gcm.c"),
|
|
|
|
(&[], "crypto/rand/sysrand.c"),
|
|
|
|
|
|
|
|
(&[X86_64, X86], "crypto/cpu-intel.c"),
|
|
|
|
|
|
|
|
(&[X86], "crypto/aes/asm/aes-586.pl"),
|
|
|
|
(&[X86], "crypto/aes/asm/aesni-x86.pl"),
|
|
|
|
(&[X86], "crypto/aes/asm/vpaes-x86.pl"),
|
|
|
|
(&[X86], "crypto/bn/asm/x86-mont.pl"),
|
|
|
|
(&[X86], "crypto/chacha/asm/chacha-x86.pl"),
|
|
|
|
(&[X86], "crypto/ec/asm/ecp_nistz256-x86.pl"),
|
|
|
|
(&[X86], "crypto/modes/asm/ghash-x86.pl"),
|
|
|
|
(&[X86], "crypto/poly1305/asm/poly1305-x86.pl"),
|
|
|
|
(&[X86], "crypto/sha/asm/sha256-586.pl"),
|
|
|
|
(&[X86], "crypto/sha/asm/sha512-586.pl"),
|
|
|
|
|
|
|
|
(&[X86_64], "crypto/curve25519/x25519-x86_64.c"),
|
|
|
|
|
|
|
|
(&[X86_64], "crypto/aes/asm/aes-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/aes/asm/aesni-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/aes/asm/bsaes-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/aes/asm/vpaes-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/bn/asm/x86_64-mont.pl"),
|
|
|
|
(&[X86_64], "crypto/bn/asm/x86_64-mont5.pl"),
|
|
|
|
(&[X86_64], "crypto/chacha/asm/chacha-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/curve25519/asm/x25519-asm-x86_64.S"),
|
|
|
|
(&[X86_64], "crypto/ec/asm/ecp_nistz256-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/ec/asm/p256-x86_64-asm.pl"),
|
|
|
|
(&[X86_64], "crypto/modes/asm/aesni-gcm-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/modes/asm/ghash-x86_64.pl"),
|
|
|
|
(&[X86_64], "crypto/poly1305/asm/poly1305-x86_64.pl"),
|
2017-03-18 13:26:00 -10:00
|
|
|
(&[X86_64], SHA512_X86_64),
|
2017-03-17 10:28:50 -10:00
|
|
|
|
2017-03-17 11:36:03 -10:00
|
|
|
(&[AARCH64, ARM], "crypto/aes/asm/aesv8-armx.pl"),
|
2017-03-17 10:28:50 -10:00
|
|
|
(&[AARCH64, ARM], "crypto/cpu-arm-linux.c"),
|
|
|
|
(&[AARCH64, ARM], "crypto/cpu-arm.c"),
|
|
|
|
(&[AARCH64, ARM], "crypto/modes/asm/ghashv8-armx.pl"),
|
|
|
|
|
|
|
|
(&[ARM], "crypto/aes/asm/aes-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/aes/asm/bsaes-armv7.pl"),
|
|
|
|
(&[ARM], "crypto/bn/asm/armv4-mont.pl"),
|
|
|
|
(&[ARM], "crypto/chacha/asm/chacha-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/curve25519/asm/x25519-asm-arm.S"),
|
|
|
|
(&[ARM], "crypto/ec/asm/ecp_nistz256-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/modes/asm/ghash-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/poly1305/asm/poly1305-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/sha/asm/sha256-armv4.pl"),
|
|
|
|
(&[ARM], "crypto/sha/asm/sha512-armv4.pl"),
|
|
|
|
|
|
|
|
(&[AARCH64], "crypto/bn/asm/armv8-mont.pl"),
|
2017-03-17 11:36:03 -10:00
|
|
|
(&[AARCH64], "crypto/cpu-aarch64-linux.c"),
|
2017-03-17 10:28:50 -10:00
|
|
|
(&[AARCH64], "crypto/chacha/asm/chacha-armv8.pl"),
|
|
|
|
(&[AARCH64], "crypto/ec/asm/ecp_nistz256-armv8.pl"),
|
|
|
|
(&[AARCH64], "crypto/poly1305/asm/poly1305-armv8.pl"),
|
2017-03-18 13:26:00 -10:00
|
|
|
(&[AARCH64], SHA512_ARMV8),
|
2017-03-17 10:28:50 -10:00
|
|
|
];
|
|
|
|
|
2017-03-18 13:26:00 -10:00
|
|
|
const SHA256_X86_64: &'static str = "crypto/sha/asm/sha256-x86_64.pl";
|
|
|
|
const SHA512_X86_64: &'static str = "crypto/sha/asm/sha512-x86_64.pl";
|
|
|
|
|
|
|
|
const SHA256_ARMV8: &'static str = "crypto/sha/asm/sha256-armv8.pl";
|
|
|
|
const SHA512_ARMV8: &'static str = "crypto/sha/asm/sha512-armv8.pl";
|
|
|
|
|
2017-03-17 10:28:50 -10:00
|
|
|
const RING_TEST_SRCS: &'static [&'static str] = &[
|
|
|
|
("crypto/bn/bn_test.cc"),
|
|
|
|
("crypto/constant_time_test.c"),
|
|
|
|
("crypto/test/bn_test_convert.c"),
|
|
|
|
("crypto/test/bn_test_new.c"),
|
|
|
|
("crypto/test/file_test.cc"),
|
|
|
|
];
|
2015-07-30 19:48:38 -04:00
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
2017-03-17 11:28:43 -10:00
|
|
|
const RING_INCLUDES: &'static [&'static str] =
|
2017-03-17 11:36:03 -10:00
|
|
|
&["crypto/bn/internal.h",
|
2017-02-07 23:19:36 +01:00
|
|
|
"crypto/cipher/internal.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"crypto/curve25519/internal.h",
|
2017-03-17 11:28:43 -10:00
|
|
|
"crypto/ec/ecp_nistz256_table.inl",
|
|
|
|
"crypto/ec/ecp_nistz384.inl",
|
2017-02-07 23:19:36 +01:00
|
|
|
"crypto/ec/ecp_nistz.h",
|
|
|
|
"crypto/ec/ecp_nistz384.h",
|
|
|
|
"crypto/ec/ecp_nistz256.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"crypto/internal.h",
|
2017-02-07 23:19:36 +01:00
|
|
|
"crypto/limbs/limbs.h",
|
2017-03-17 11:28:43 -10:00
|
|
|
"crypto/limbs/limbs.inl",
|
2017-03-17 11:36:03 -10:00
|
|
|
"crypto/modes/internal.h",
|
2017-03-17 11:28:43 -10:00
|
|
|
"crypto/test/bn_test_lib.h",
|
|
|
|
"crypto/test/bn_test_util.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"crypto/test/file_test.h",
|
|
|
|
"crypto/test/scoped_types.h",
|
|
|
|
"include/openssl/aes.h",
|
2017-02-07 23:19:36 +01:00
|
|
|
"include/openssl/arm_arch.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"include/openssl/base.h",
|
|
|
|
"include/openssl/bn.h",
|
2017-02-07 23:19:36 +01:00
|
|
|
"include/openssl/cpu.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"include/openssl/err.h",
|
|
|
|
"include/openssl/mem.h",
|
|
|
|
"include/openssl/opensslconf.h",
|
2017-02-07 23:19:36 +01:00
|
|
|
"include/openssl/rsa.h",
|
2017-03-17 11:36:03 -10:00
|
|
|
"include/openssl/type_check.h"];
|
2016-08-15 13:34:13 -10:00
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
|
|
const RING_PERL_INCLUDES: &'static [&'static str] =
|
2017-03-17 11:36:03 -10:00
|
|
|
&["crypto/perlasm/arm-xlate.pl",
|
2017-02-07 23:19:36 +01:00
|
|
|
"crypto/perlasm/x86gas.pl",
|
|
|
|
"crypto/perlasm/x86nasm.pl",
|
|
|
|
"crypto/perlasm/x86asm.pl",
|
2017-03-17 11:36:03 -10:00
|
|
|
"crypto/perlasm/x86_64-xlate.pl"];
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-02-07 23:32:13 +01:00
|
|
|
const RING_BUILD_FILE: &'static [&'static str] = &["build.rs"];
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
const PREGENERATED: &'static str = "pregenerated";
|
|
|
|
|
2017-02-19 23:22:21 -10:00
|
|
|
fn c_flags(target: &Target) -> &'static [&'static str] {
|
2017-03-18 10:16:16 -10:00
|
|
|
if target.env != MSVC {
|
2017-02-19 23:22:21 -10:00
|
|
|
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
|
|
|
"-std=c1x", // GCC 4.6 requires "c1x" instead of "c11"
|
|
|
|
"-Wbad-function-cast",
|
|
|
|
"-Wmissing-prototypes",
|
|
|
|
"-Wnested-externs",
|
|
|
|
"-Wstrict-prototypes"
|
|
|
|
];
|
|
|
|
NON_MSVC_FLAGS
|
|
|
|
} else {
|
|
|
|
&[]
|
|
|
|
}
|
|
|
|
}
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-02-19 23:22:21 -10:00
|
|
|
fn cxx_flags(target: &Target) -> &'static [&'static str] {
|
2017-03-18 10:16:16 -10:00
|
|
|
if target.env != MSVC {
|
2017-02-19 23:22:21 -10:00
|
|
|
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
|
|
|
"-std=c++0x" // GCC 4.6 requires "c++0x" instead of "c++11"
|
|
|
|
];
|
|
|
|
NON_MSVC_FLAGS
|
|
|
|
} else {
|
|
|
|
&[]
|
|
|
|
}
|
|
|
|
}
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-02-19 23:22:21 -10:00
|
|
|
fn cpp_flags(target: &Target) -> &'static [&'static str] {
|
2017-03-18 10:16:16 -10:00
|
|
|
if target.env != MSVC {
|
2017-02-19 23:22:21 -10:00
|
|
|
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
|
|
|
"-fdata-sections",
|
|
|
|
"-ffunction-sections",
|
|
|
|
"-pedantic",
|
|
|
|
"-pedantic-errors",
|
|
|
|
"-Wall",
|
|
|
|
"-Werror",
|
|
|
|
"-Wextra",
|
|
|
|
"-Wcast-align",
|
|
|
|
"-Wcast-qual",
|
|
|
|
"-Wenum-compare",
|
|
|
|
"-Wfloat-equal",
|
|
|
|
"-Wformat=2",
|
|
|
|
"-Winline",
|
|
|
|
"-Winvalid-pch",
|
|
|
|
"-Wmissing-declarations",
|
|
|
|
"-Wmissing-field-initializers",
|
|
|
|
"-Wmissing-include-dirs",
|
|
|
|
"-Wredundant-decls",
|
|
|
|
"-Wshadow",
|
|
|
|
"-Wsign-compare",
|
|
|
|
"-Wundef",
|
|
|
|
"-Wuninitialized",
|
|
|
|
"-Wwrite-strings",
|
|
|
|
"-fno-strict-aliasing",
|
|
|
|
"-fvisibility=hidden",
|
|
|
|
"-Wno-cast-align"
|
|
|
|
];
|
|
|
|
NON_MSVC_FLAGS
|
|
|
|
} else {
|
|
|
|
static MSVC_FLAGS: &'static [&'static str] = &[
|
|
|
|
"/GS", // Buffer security checks.
|
2017-03-18 16:58:14 -10:00
|
|
|
"/Gy", // Enable function-level linking.
|
|
|
|
|
|
|
|
"/EHsc", // C++ exceptions only, only in C++.
|
|
|
|
"/GR-", // Disable RTTI.
|
2017-02-19 23:22:21 -10:00
|
|
|
|
|
|
|
"/Zc:wchar_t",
|
|
|
|
"/Zc:forScope",
|
|
|
|
"/Zc:inline",
|
|
|
|
"/Zc:rvalueCast",
|
|
|
|
|
|
|
|
// Warnings.
|
|
|
|
"/sdl",
|
|
|
|
"/Wall",
|
|
|
|
"/WX",
|
|
|
|
"/wd4127", // C4127: conditional expression is constant
|
|
|
|
"/wd4464", // C4464: relative include path contains '..'
|
|
|
|
"/wd4514", // C4514: <name>: unreferenced inline function has be
|
|
|
|
"/wd4710", // C4710: function not inlined
|
|
|
|
"/wd4711", // C4711: function 'function' selected for inline expansion
|
|
|
|
"/wd4820", // C4820: <struct>: <n> bytes padding added after <name>
|
|
|
|
];
|
|
|
|
MSVC_FLAGS
|
|
|
|
}
|
|
|
|
}
|
2017-02-07 23:19:36 +01:00
|
|
|
|
|
|
|
const LD_FLAGS: &'static [&'static str] = &[];
|
|
|
|
|
2017-03-15 20:47:06 -10:00
|
|
|
// None means "any OS" or "any target". The first match in sequence order is
|
|
|
|
// taken.
|
|
|
|
const ASM_TARGETS:
|
|
|
|
&'static [(&'static str, Option<&'static str>, &'static str)] =
|
|
|
|
&[
|
|
|
|
("x86_64", Some("macos"), "macosx"),
|
2017-03-18 10:16:16 -10:00
|
|
|
("x86_64", Some(WINDOWS), "nasm"),
|
2017-03-15 20:47:06 -10:00
|
|
|
("x86_64", None, "elf"),
|
|
|
|
("aarch64", Some("ios"), "ios64"),
|
|
|
|
("aarch64", None, "linux64"),
|
2017-03-18 10:16:16 -10:00
|
|
|
("x86", Some(WINDOWS), "win32n"),
|
2017-03-15 20:47:06 -10:00
|
|
|
("x86", None, "elf"),
|
|
|
|
("arm", Some("ios"), "ios32"),
|
|
|
|
("arm", None, "linux32"),
|
|
|
|
];
|
|
|
|
|
2017-03-18 10:16:16 -10:00
|
|
|
const WINDOWS: &'static str = "windows";
|
|
|
|
const MSVC: &'static str = "msvc";
|
|
|
|
const MSVC_OBJ_OPT: &'static str = "/Fo";
|
|
|
|
const MSVC_OBJ_EXT: &'static str = "obj";
|
|
|
|
|
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
fn main() {
|
2017-03-16 12:43:18 -10:00
|
|
|
if let Ok(package_name) = std::env::var("CARGO_PKG_NAME") {
|
|
|
|
if package_name == "ring" {
|
|
|
|
ring_build_rs_main();
|
|
|
|
return;
|
|
|
|
}
|
2016-04-16 17:11:20 -10:00
|
|
|
}
|
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
pregenerate_asm_main();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ring_build_rs_main() {
|
|
|
|
use std::env;
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-02-07 23:29:00 +01:00
|
|
|
let mut cfg = rayon::Configuration::new();
|
2017-03-16 12:43:18 -10:00
|
|
|
if let Ok(amt) = std::env::var("NUM_JOBS") {
|
2017-02-07 23:29:00 +01:00
|
|
|
if let Ok(amt) = amt.parse() {
|
2017-04-07 16:04:06 -07:00
|
|
|
cfg = cfg.num_threads(amt);
|
2017-02-07 23:29:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rayon::initialize(cfg).unwrap();
|
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
for (key, value) in env::vars() {
|
|
|
|
println!("{}: {}", key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
let out_dir = env::var("OUT_DIR").unwrap();
|
|
|
|
let out_dir = PathBuf::from(out_dir);
|
|
|
|
|
|
|
|
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();
|
2017-04-11 18:05:10 -10:00
|
|
|
let (obj_ext, obj_opt) = if os == WINDOWS {
|
2017-03-18 10:16:16 -10:00
|
|
|
(MSVC_OBJ_EXT, MSVC_OBJ_OPT)
|
2017-03-16 12:43:18 -10:00
|
|
|
} else {
|
|
|
|
("o", "-o")
|
|
|
|
};
|
|
|
|
|
|
|
|
let target = Target {
|
|
|
|
arch: arch,
|
|
|
|
os: os,
|
|
|
|
env: env,
|
|
|
|
obj_ext: obj_ext,
|
|
|
|
obj_opt: obj_opt,
|
2017-03-18 17:29:36 -10:00
|
|
|
is_debug: env::var("DEBUG").unwrap() != "false",
|
2017-03-16 12:43:18 -10:00
|
|
|
};
|
|
|
|
|
2017-04-11 17:55:39 -10:00
|
|
|
let pregenerated =
|
|
|
|
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
|
|
|
|
.join(PREGENERATED);
|
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
let _ = rayon::join(check_all_files_tracked,
|
2017-04-11 17:55:39 -10:00
|
|
|
|| build_c_code(&target, pregenerated, &out_dir));
|
2017-03-16 12:43:18 -10:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pregenerate_asm_main() {
|
|
|
|
let pregenerated = PathBuf::from(PREGENERATED);
|
|
|
|
std::fs::create_dir(&pregenerated).unwrap();
|
2017-03-18 10:16:16 -10:00
|
|
|
let pregenerated_tmp = pregenerated.join("tmp");
|
|
|
|
std::fs::create_dir(&pregenerated_tmp).unwrap();
|
2017-03-16 12:43:18 -10:00
|
|
|
|
|
|
|
for &(target_arch, target_os, perlasm_format) in ASM_TARGETS {
|
2017-03-18 10:16:16 -10:00
|
|
|
// For Windows, package pregenerated object files instead of
|
|
|
|
// pregenerated assembly language source files, so that the user
|
|
|
|
// doesn't need to install the assembler.
|
|
|
|
let asm_dir = if target_os == Some(WINDOWS) {
|
|
|
|
&pregenerated_tmp
|
|
|
|
} else {
|
|
|
|
&pregenerated
|
|
|
|
};
|
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
let perlasm_src_dsts =
|
2017-03-18 10:16:16 -10:00
|
|
|
perlasm_src_dsts(&asm_dir, target_arch, target_os, perlasm_format);
|
2017-03-16 12:43:18 -10:00
|
|
|
perlasm(&perlasm_src_dsts, target_arch, perlasm_format, None);
|
2017-03-18 10:16:16 -10:00
|
|
|
|
|
|
|
if target_os == Some(WINDOWS) {
|
|
|
|
//let lib_name = ring_asm_name(target_arch);
|
|
|
|
let srcs = asm_srcs(perlasm_src_dsts);
|
|
|
|
for src in srcs {
|
|
|
|
let src_path = PathBuf::from(src);
|
|
|
|
let obj_path =
|
|
|
|
obj_path(&pregenerated, &src_path, MSVC_OBJ_EXT);
|
|
|
|
run_command(yasm(&src_path, target_arch, &obj_path));
|
|
|
|
}
|
|
|
|
}
|
2017-03-16 12:43:18 -10:00
|
|
|
}
|
2015-07-30 19:48:38 -04:00
|
|
|
}
|
2016-08-14 20:39:12 -10:00
|
|
|
|
2017-03-04 12:46:36 -10:00
|
|
|
struct Target {
|
|
|
|
arch: String,
|
|
|
|
os: String,
|
|
|
|
env: String,
|
2017-02-19 23:22:21 -10:00
|
|
|
obj_ext: &'static str,
|
|
|
|
obj_opt: &'static str,
|
2017-03-16 12:43:18 -10:00
|
|
|
is_debug: bool,
|
2017-03-04 12:46:36 -10:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Target {
|
|
|
|
pub fn arch(&self) -> &str { &self.arch }
|
|
|
|
pub fn os(&self) -> &str { &self.os }
|
|
|
|
pub fn env(&self) -> &str { &self.env }
|
2017-03-16 12:43:18 -10:00
|
|
|
pub fn is_debug(&self) -> bool { self.is_debug }
|
2017-03-04 12:46:36 -10:00
|
|
|
}
|
|
|
|
|
2017-04-11 17:55:39 -10:00
|
|
|
fn build_c_code(target: &Target, pregenerated: PathBuf, out_dir: &Path) {
|
2017-03-17 11:28:43 -10:00
|
|
|
let includes_modified = RING_INCLUDES.par_iter()
|
2017-04-07 16:04:06 -07:00
|
|
|
.with_max_len(1)
|
2017-02-07 23:29:00 +01:00
|
|
|
.chain(RING_BUILD_FILE.par_iter())
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
.chain(RING_PERL_INCLUDES.par_iter())
|
|
|
|
.map(|f| file_modified(Path::new(*f)))
|
|
|
|
.max()
|
|
|
|
.unwrap();
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-03-15 20:47:06 -10:00
|
|
|
fn is_none_or_equals<T>(opt: Option<T>, other: T)
|
|
|
|
-> bool where T: PartialEq {
|
|
|
|
if let Some(value) = opt {
|
|
|
|
value == other
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let &(_, _, perlasm_format) = ASM_TARGETS.iter().find(|entry| {
|
|
|
|
let &(entry_arch, entry_os, _) = *entry;
|
|
|
|
entry_arch == target.arch() && is_none_or_equals(entry_os, target.os())
|
|
|
|
}).unwrap();
|
2017-03-16 12:43:18 -10:00
|
|
|
|
|
|
|
let use_pregenerated = std::fs::metadata(".git").is_err();
|
|
|
|
|
2017-03-18 10:54:33 -10:00
|
|
|
let asm_dir = if use_pregenerated { &pregenerated } else { out_dir };
|
2017-03-16 12:43:18 -10:00
|
|
|
|
|
|
|
let perlasm_src_dsts =
|
2017-03-18 10:54:33 -10:00
|
|
|
perlasm_src_dsts(asm_dir, target.arch(), Some(target.os()),
|
2017-03-16 12:43:18 -10:00
|
|
|
perlasm_format);
|
|
|
|
|
|
|
|
if !use_pregenerated {
|
|
|
|
perlasm(&perlasm_src_dsts[..], target.arch(), perlasm_format,
|
|
|
|
Some(includes_modified));
|
|
|
|
}
|
|
|
|
|
2017-03-18 10:16:16 -10:00
|
|
|
let mut asm_srcs = asm_srcs(perlasm_src_dsts);
|
|
|
|
|
|
|
|
// For Windows we also pregenerate the object files for non-Git builds so
|
|
|
|
// the user doesn't need to install the assembler. On other platforms we
|
|
|
|
// assume the C compiler also assembles.
|
|
|
|
if use_pregenerated && target.os() == WINDOWS {
|
|
|
|
asm_srcs = asm_srcs.iter()
|
|
|
|
.map(|src| obj_path(&pregenerated, src.as_path(), target.obj_ext))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
}
|
2017-03-16 12:43:18 -10:00
|
|
|
|
2017-03-18 10:31:13 -10:00
|
|
|
let core_srcs = sources_for_arch(target.arch()).into_iter()
|
2017-03-16 12:43:18 -10:00
|
|
|
.filter(|p| !is_perlasm(&p))
|
2017-03-17 10:28:50 -10:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
let test_srcs = RING_TEST_SRCS.iter()
|
|
|
|
.map(PathBuf::from)
|
2017-03-29 13:47:01 -04:00
|
|
|
// Allow the C++-based tests to be disabled
|
|
|
|
.filter(|p| cfg!(feature = "bn_tests") ||
|
|
|
|
p.extension().unwrap().to_str().unwrap() != "cc")
|
|
|
|
// Avoid the libstdc++ vs libc++ issue for macOS/iOS, and g++ issue on
|
|
|
|
// musl by just avoiding all the C++-based tests.
|
|
|
|
.filter(|p| !(target.os() == "macos" || target.os == "ios" ||
|
|
|
|
target.env() == "musl") ||
|
2017-03-18 22:55:24 -10:00
|
|
|
p.extension().unwrap().to_str().unwrap() != "cc")
|
2017-03-17 10:28:50 -10:00
|
|
|
.collect::<Vec<_>>();
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-03-18 10:31:13 -10:00
|
|
|
let libs = [
|
|
|
|
("ring-core", &core_srcs[..], &asm_srcs[..]),
|
|
|
|
("ring-test", &test_srcs[..], &[]),
|
|
|
|
];
|
|
|
|
|
2017-03-16 11:22:45 -10:00
|
|
|
// XXX: Ideally, ring-test would only be built for `cargo test`, but Cargo
|
|
|
|
// can't do that yet.
|
2017-03-18 10:31:13 -10:00
|
|
|
libs.into_par_iter()
|
2017-04-07 16:04:06 -07:00
|
|
|
.with_max_len(1)
|
2017-03-18 10:31:13 -10:00
|
|
|
.for_each(|&(lib_name, srcs, additional_srcs)|
|
|
|
|
build_library(&target, &out_dir, lib_name, srcs, additional_srcs,
|
|
|
|
includes_modified));
|
2017-03-16 01:00:15 -10:00
|
|
|
|
2017-03-18 22:55:24 -10:00
|
|
|
if target.env() != "msvc" &&
|
2017-03-29 13:47:01 -04:00
|
|
|
target.env() != "musl" &&
|
|
|
|
cfg!(feature = "bn_tests") &&
|
2017-03-18 22:55:24 -10:00
|
|
|
!(target.os() == "macos" || target.os() == "ios") {
|
2017-03-16 12:43:18 -10:00
|
|
|
let libcxx = if use_libcxx(target) {
|
2017-02-19 23:22:21 -10:00
|
|
|
"c++"
|
|
|
|
} else {
|
|
|
|
"stdc++"
|
|
|
|
};
|
|
|
|
println!("cargo:rustc-flags=-l dylib={}", libcxx);
|
|
|
|
}
|
|
|
|
|
2017-03-16 01:00:15 -10:00
|
|
|
println!("cargo:rustc-link-search=native={}",
|
|
|
|
out_dir.to_str().expect("Invalid path"));
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
|
2017-02-07 23:29:00 +01:00
|
|
|
|
2017-03-18 10:31:13 -10:00
|
|
|
fn build_library(target: &Target, out_dir: &Path, lib_name: &str,
|
|
|
|
srcs: &[PathBuf], additional_srcs: &[PathBuf],
|
2017-03-18 10:54:33 -10:00
|
|
|
includes_modified: SystemTime) {
|
2017-02-07 23:29:00 +01:00
|
|
|
// Compile all the (dirty) source files into object files.
|
2017-03-18 10:31:13 -10:00
|
|
|
let objs = additional_srcs.into_par_iter().chain(srcs.into_par_iter())
|
2017-04-07 16:04:06 -07:00
|
|
|
.with_max_len(1)
|
2017-03-17 10:28:50 -10:00
|
|
|
.filter(|f|
|
|
|
|
target.env() != "msvc" ||
|
|
|
|
f.extension().unwrap().to_str().unwrap() != "S")
|
2017-03-18 10:54:33 -10:00
|
|
|
.map(|f| compile(f, target, out_dir, includes_modified))
|
2017-02-07 23:29:00 +01:00
|
|
|
.map(|v| vec![v])
|
|
|
|
.reduce(Vec::new,
|
|
|
|
&|mut a: Vec<String>, b: Vec<String>| -> Vec<String> {
|
|
|
|
a.extend(b.into_iter());
|
|
|
|
a
|
|
|
|
});
|
|
|
|
|
2017-03-18 10:54:33 -10:00
|
|
|
// Rebuild the library if necessary.
|
2017-03-18 10:31:13 -10:00
|
|
|
let lib_path = PathBuf::from(out_dir).join(format!("lib{}.a", lib_name));
|
|
|
|
|
2017-02-07 23:29:00 +01:00
|
|
|
if objs.par_iter()
|
2017-04-07 16:04:06 -07:00
|
|
|
.with_max_len(1)
|
2017-02-07 23:19:36 +01:00
|
|
|
.map(|f| Path::new(f))
|
2017-03-18 10:31:13 -10:00
|
|
|
.any(|p| need_run(&p, &lib_path, includes_modified)) {
|
2017-02-07 23:19:36 +01:00
|
|
|
let mut c = gcc::Config::new();
|
|
|
|
|
|
|
|
for f in LD_FLAGS {
|
|
|
|
let _ = c.flag(&f);
|
|
|
|
}
|
2017-03-04 12:46:36 -10:00
|
|
|
match target.os() {
|
2017-02-07 23:19:36 +01:00
|
|
|
"macos" => {
|
|
|
|
let _ = c.flag("-fPIC");
|
|
|
|
let _ = c.flag("-Wl,-dead_strip");
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
let _ = c.flag("-Wl,--gc-sections".into());
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for o in objs {
|
|
|
|
let _ = c.object(o);
|
|
|
|
}
|
2017-03-16 01:00:15 -10:00
|
|
|
|
|
|
|
// Handled below.
|
|
|
|
let _ = c.cargo_metadata(false);
|
|
|
|
|
2017-03-18 10:31:13 -10:00
|
|
|
c.compile(lib_path.file_name()
|
2017-02-07 23:19:36 +01:00
|
|
|
.and_then(|f| f.to_str())
|
|
|
|
.expect("No filename"));
|
|
|
|
}
|
2017-03-16 01:00:15 -10:00
|
|
|
|
|
|
|
// Link the library. This works even when the library doesn't need to be
|
|
|
|
// rebuilt.
|
|
|
|
println!("cargo:rustc-link-lib=static={}", lib_name);
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
|
2017-03-18 10:54:33 -10:00
|
|
|
fn compile(p: &Path, target: &Target, out_dir: &Path,
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
includes_modified: SystemTime) -> String {
|
2017-03-18 10:16:16 -10:00
|
|
|
let ext = p.extension().unwrap().to_str().unwrap();
|
|
|
|
if ext == "obj" {
|
|
|
|
p.to_str().expect("Invalid path").into()
|
|
|
|
} else {
|
|
|
|
let mut out_path = out_dir.clone().join(p.file_name().unwrap());
|
|
|
|
out_path.set_extension(target.obj_ext);
|
|
|
|
if need_run(&p, &out_path, includes_modified) {
|
2017-04-01 23:14:37 +08:00
|
|
|
let cmd = if target.os() != WINDOWS || ext != "asm" {
|
2017-03-18 10:16:16 -10:00
|
|
|
cc(p, ext, target, &out_path)
|
|
|
|
} else {
|
|
|
|
yasm(p, target.arch(), &out_path)
|
|
|
|
};
|
|
|
|
|
|
|
|
run_command(cmd);
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
2017-03-18 10:16:16 -10:00
|
|
|
out_path.to_str().expect("Invalid path").into()
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
2017-03-18 10:16:16 -10:00
|
|
|
}
|
|
|
|
|
|
|
|
fn obj_path(out_dir: &Path, src: &Path, obj_ext: &str) -> PathBuf {
|
|
|
|
let mut out_path = out_dir.clone().join(src.file_name().unwrap());
|
|
|
|
out_path.set_extension(obj_ext);
|
|
|
|
out_path
|
2016-10-26 11:44:22 +02:00
|
|
|
}
|
|
|
|
|
2017-03-17 10:28:50 -10:00
|
|
|
fn cc(file: &Path, ext: &str, target: &Target, out_dir: &Path) -> Command {
|
2017-02-19 23:22:21 -10:00
|
|
|
let mut c = gcc::Config::new();
|
|
|
|
let _ = c.include("include");
|
|
|
|
match ext {
|
|
|
|
"c" => {
|
|
|
|
for f in c_flags(target) {
|
|
|
|
let _ = c.flag(f);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"cc" => {
|
|
|
|
for f in cxx_flags(target) {
|
|
|
|
let _ = c.flag(f);
|
|
|
|
}
|
|
|
|
let _ = c.cpp(true);
|
|
|
|
if use_libcxx(target) {
|
|
|
|
let _ = c.cpp_set_stdlib(Some("c++"));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"S" => {},
|
|
|
|
e => panic!("Unsupported file extension: {:?}", e),
|
|
|
|
};
|
|
|
|
for f in cpp_flags(target) {
|
|
|
|
let _ = c.flag(&f);
|
|
|
|
}
|
|
|
|
if target.os() != "none" &&
|
|
|
|
target.os() != "redox" &&
|
2017-04-01 23:14:37 +08:00
|
|
|
target.os() != "windows" {
|
2017-02-19 23:22:21 -10:00
|
|
|
let _ = c.flag("-fstack-protector");
|
|
|
|
}
|
2017-03-18 16:58:14 -10:00
|
|
|
|
2017-02-19 23:22:21 -10:00
|
|
|
match (target.os(), target.env()) {
|
|
|
|
// ``-gfull`` is required for Darwin's |-dead_strip|.
|
|
|
|
("macos", _) => { let _ = c.flag("-gfull"); },
|
|
|
|
(_, "msvc") => {},
|
|
|
|
_ => { let _ = c.flag("-g3"); },
|
|
|
|
};
|
2017-03-16 12:43:18 -10:00
|
|
|
if !target.is_debug() {
|
2017-02-19 23:22:21 -10:00
|
|
|
let _ = c.define("NDEBUG", None);
|
2017-03-18 16:58:14 -10:00
|
|
|
}
|
|
|
|
|
|
|
|
if target.env() == "msvc" {
|
|
|
|
if std::env::var("OPT_LEVEL").unwrap() == "0" {
|
|
|
|
let _ = c.flag("/Od"); // Disable optimization for debug builds.
|
2017-02-19 23:22:21 -10:00
|
|
|
// run-time checking: (s)tack frame, (u)ninitialized variables
|
|
|
|
let _ = c.flag("/RTCsu");
|
2017-03-18 16:58:14 -10:00
|
|
|
} else {
|
|
|
|
let _ = c.flag("/Ox"); // Enable full optimization.
|
2017-02-19 23:22:21 -10:00
|
|
|
}
|
|
|
|
}
|
2017-03-18 16:58:14 -10:00
|
|
|
|
2017-03-05 19:49:44 -10:00
|
|
|
if target.env() != "msvc" {
|
2017-02-19 23:22:21 -10:00
|
|
|
let _ = c.define("_XOPEN_SOURCE", Some("700"));
|
|
|
|
}
|
2017-03-05 19:49:48 -10:00
|
|
|
if target.env() == "musl" {
|
|
|
|
// Some platforms enable _FORTIFY_SOURCE by default, but musl
|
|
|
|
// libc doesn't support it yet. See
|
|
|
|
// http://wiki.musl-libc.org/wiki/Future_Ideas#Fortify
|
|
|
|
// http://www.openwall.com/lists/musl/2015/02/04/3
|
|
|
|
// http://www.openwall.com/lists/musl/2015/06/17/1
|
|
|
|
let _ = c.flag("-U_FORTIFY_SOURCE");
|
|
|
|
}
|
2017-03-14 09:36:15 -10:00
|
|
|
if target.os() == "android" {
|
|
|
|
// Define __ANDROID_API__ to the Android API level we want.
|
|
|
|
// Needed for Android NDK Unified Headers, see:
|
|
|
|
// https://android.googlesource.com/platform/ndk/+/master/docs/UnifiedHeaders.md#Supporting-Unified-Headers-in-Your-Build-System
|
|
|
|
let _ = c.define("__ANDROID_API__", Some("18"));
|
2017-03-06 17:33:40 -08:00
|
|
|
}
|
|
|
|
|
2017-02-19 23:22:21 -10:00
|
|
|
let mut c = c.get_compiler().to_command();
|
|
|
|
let _ = c.arg("-c")
|
|
|
|
.arg(format!("{}{}", target.obj_opt,
|
|
|
|
out_dir.to_str().expect("Invalid path")))
|
|
|
|
.arg(file);
|
|
|
|
c
|
|
|
|
}
|
|
|
|
|
2017-03-18 10:16:16 -10:00
|
|
|
fn yasm(file: &Path, arch: &str, out_file: &Path) -> Command {
|
|
|
|
let (oformat, machine) = match arch {
|
|
|
|
"x86_64" => ("--oformat=win64", "--machine=amd64"),
|
|
|
|
"x86" => ("--oformat=win32", "--machine=x86"),
|
|
|
|
_ => panic!("unsupported arch: {}", arch),
|
2017-02-19 23:22:21 -10:00
|
|
|
};
|
|
|
|
let mut c = Command::new("yasm.exe");
|
|
|
|
let _ = c.arg("-X").arg("vc")
|
|
|
|
.arg("--dformat=cv8")
|
|
|
|
.arg(oformat)
|
|
|
|
.arg(machine)
|
|
|
|
.arg("-o").arg(out_file.to_str().expect("Invalid path"))
|
|
|
|
.arg(file);
|
|
|
|
c
|
|
|
|
}
|
|
|
|
|
2017-03-04 12:46:36 -10:00
|
|
|
fn use_libcxx(target: &Target) -> bool {
|
2017-03-18 22:55:24 -10:00
|
|
|
target.os() == "freebsd"
|
2017-03-03 15:25:34 -10:00
|
|
|
}
|
|
|
|
|
2017-01-26 18:07:26 +01:00
|
|
|
fn run_command_with_args<S>(command_name: S, args: &[String])
|
2016-10-26 09:02:30 -10:00
|
|
|
where S: AsRef<std::ffi::OsStr> + Copy
|
|
|
|
{
|
2017-02-19 23:22:21 -10:00
|
|
|
let mut cmd = Command::new(command_name);
|
2017-02-19 20:26:19 -10:00
|
|
|
let _ = cmd.args(args);
|
2017-03-18 10:16:16 -10:00
|
|
|
run_command(cmd)
|
|
|
|
}
|
2017-02-19 20:26:19 -10:00
|
|
|
|
2017-03-18 10:16:16 -10:00
|
|
|
fn run_command(mut cmd: Command) {
|
|
|
|
println!("running {:?}", cmd);
|
2017-02-19 20:26:19 -10:00
|
|
|
let status = cmd.status().unwrap_or_else(|e| {
|
2017-04-11 15:18:02 -10:00
|
|
|
panic!("failed to execute [{:?}]: {}", cmd, e);
|
2017-02-19 20:26:19 -10:00
|
|
|
});
|
2016-10-26 09:02:30 -10:00
|
|
|
if !status.success() {
|
2017-02-19 20:26:19 -10:00
|
|
|
panic!("execution failed");
|
2016-08-14 20:39:12 -10:00
|
|
|
}
|
|
|
|
}
|
2017-02-07 23:19:36 +01:00
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
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)> {
|
2017-03-18 13:26:00 -10:00
|
|
|
let srcs = sources_for_arch(arch);
|
|
|
|
let mut src_dsts = srcs.iter()
|
2017-03-16 12:43:18 -10:00
|
|
|
.filter(|p| is_perlasm(p))
|
|
|
|
.map(|src| (src.clone(), asm_path(out_dir, src, os, perlasm_format)))
|
2017-03-18 13:26:00 -10:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
// Some PerlAsm source files need to be run multiple times with different
|
|
|
|
// output paths.
|
|
|
|
{ // Appease the borrow checker.
|
|
|
|
let mut maybe_synthesize = |concrete, synthesized| {
|
|
|
|
let concrete_path = PathBuf::from(concrete);
|
|
|
|
if srcs.contains(&concrete_path) {
|
|
|
|
let synthesized_path = PathBuf::from(synthesized);
|
|
|
|
src_dsts.push((concrete_path,
|
|
|
|
asm_path(out_dir, &synthesized_path, os,
|
|
|
|
perlasm_format)))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
maybe_synthesize(SHA512_X86_64, SHA256_X86_64);
|
|
|
|
maybe_synthesize(SHA512_ARMV8, SHA256_ARMV8);
|
|
|
|
}
|
|
|
|
|
|
|
|
src_dsts
|
2017-03-16 12:43:18 -10:00
|
|
|
}
|
|
|
|
|
2017-03-18 10:16:16 -10:00
|
|
|
fn asm_srcs(perlasm_src_dsts: Vec<(PathBuf, PathBuf)>) -> Vec<PathBuf> {
|
|
|
|
perlasm_src_dsts.into_iter()
|
|
|
|
.map(|(_src, dst)| dst)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
|
2017-03-16 12:43:18 -10:00
|
|
|
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");
|
2017-03-15 21:22:39 -10:00
|
|
|
|
|
|
|
let dst_stem = src_stem.to_str().unwrap();
|
2017-03-16 12:43:18 -10:00
|
|
|
let dst_extension = if os == Some("windows") { "asm" } else { "S" };
|
2017-03-15 21:22:39 -10:00
|
|
|
let dst_filename =
|
|
|
|
format!("{}-{}.{}", dst_stem, perlasm_format, dst_extension);
|
2017-03-18 10:16:46 -10:00
|
|
|
out_dir.join(dst_filename)
|
2017-03-16 12:43:18 -10:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-03-15 21:22:39 -10:00
|
|
|
|
2017-03-17 10:28:50 -10:00
|
|
|
let mut args = Vec::<String>::new();
|
2017-03-16 12:43:18 -10:00
|
|
|
args.push(src.to_string_lossy().into_owned());
|
2017-03-15 20:47:06 -10:00
|
|
|
args.push(perlasm_format.to_owned());
|
|
|
|
if arch == "x86" {
|
2017-03-17 10:28:50 -10:00
|
|
|
args.push("-fPIC".into());
|
|
|
|
args.push("-DOPENSSL_IA32_SSE2".into());
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
2017-03-16 12:43:18 -10:00
|
|
|
// 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);
|
2017-03-17 10:28:50 -10:00
|
|
|
run_command_with_args(&get_command("PERL_EXECUTABLE", "perl"), &args);
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
fn need_run(source: &Path, target: &Path, includes_modified: SystemTime)
|
|
|
|
-> bool {
|
|
|
|
let s_modified = file_modified(source);
|
|
|
|
if let Ok(target_metadata) = std::fs::metadata(target) {
|
|
|
|
let target_modified = target_metadata.modified().unwrap();
|
|
|
|
s_modified >= target_modified || includes_modified >= target_modified
|
2017-02-07 23:19:36 +01:00
|
|
|
} else {
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
// On error fetching metadata for the target file, assume the target
|
|
|
|
// doesn't exist.
|
|
|
|
true
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Improve include file modification checks.
Treat a missing source file as an error, whereas before we were
treating it as indicating that the target needs to be rebuilt. Because
we do dependency checking bottom-up, not top-down, the source file
always exists. If it doesn't, then that's an error. In particular, it
probably means that build.rs lists some source files that have been
removed. (See the previous commit.)
Also, the original purpose of this commit is to memoize the
modification time of the most recently modified include file, instead
of `stat()`ing each include file over and over again for each source
file. So do that too.
Finally, in the name of simplicity, don't bother tracking test vs.
non-test includes separately. It's rare when any include file changes,
and we don't save much by separating things, so K.I.S.S. to reduce the
chance that things get screwed up.
2017-03-15 23:37:40 -10:00
|
|
|
fn file_modified(path: &Path) -> SystemTime {
|
|
|
|
let path = Path::new(path);
|
|
|
|
let path_as_str = format!("{:?}", path);
|
|
|
|
std::fs::metadata(path).expect(&path_as_str).modified().expect("nah")
|
|
|
|
}
|
|
|
|
|
2017-02-07 23:19:36 +01:00
|
|
|
fn get_command(var: &str, default: &str) -> String {
|
2017-03-16 12:43:18 -10:00
|
|
|
std::env::var(var).unwrap_or(default.into())
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn check_all_files_tracked() {
|
2017-02-07 23:32:13 +01:00
|
|
|
let _ = rayon::join(|| walk_dir(&PathBuf::from("crypto"), &is_tracked),
|
|
|
|
|| walk_dir(&PathBuf::from("include"), &is_tracked));
|
2017-02-07 23:19:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_tracked(file: &DirEntry) {
|
|
|
|
let p = file.path();
|
|
|
|
let cmp = |f| p == PathBuf::from(f);
|
|
|
|
let tracked = match p.extension().and_then(|p| p.to_str()) {
|
2017-03-17 11:28:43 -10:00
|
|
|
Some("h") |
|
|
|
|
Some("inl") => {
|
|
|
|
RING_INCLUDES.iter().any(cmp)
|
2017-02-07 23:19:36 +01:00
|
|
|
},
|
2017-03-17 10:28:50 -10:00
|
|
|
Some("c") |
|
|
|
|
Some("cc") |
|
2017-02-19 23:22:21 -10:00
|
|
|
Some("S") |
|
|
|
|
Some("asm") => {
|
2017-03-17 10:28:50 -10:00
|
|
|
RING_SRCS.iter().any(|&(_, ref f)| cmp(f)) ||
|
|
|
|
RING_TEST_SRCS.iter().any(cmp)
|
2017-02-07 23:19:36 +01:00
|
|
|
},
|
|
|
|
Some("pl") => {
|
2017-03-17 10:28:50 -10:00
|
|
|
RING_SRCS.iter().any(|&(_, ref f)| cmp(f)) ||
|
|
|
|
RING_PERL_INCLUDES.iter().any(cmp)
|
2017-02-07 23:19:36 +01:00
|
|
|
},
|
|
|
|
_ => true,
|
|
|
|
};
|
|
|
|
if !tracked {
|
|
|
|
panic!("{:?} is not tracked in build.rs", p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn walk_dir<F>(dir: &Path, cb: &F)
|
|
|
|
where F: Fn(&DirEntry)
|
|
|
|
{
|
|
|
|
if dir.is_dir() {
|
|
|
|
for entry in fs::read_dir(dir).unwrap() {
|
|
|
|
let entry = entry.unwrap();
|
|
|
|
let path = entry.path();
|
|
|
|
if path.is_dir() {
|
|
|
|
walk_dir(&path, cb);
|
|
|
|
} else {
|
|
|
|
cb(&entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|