File: build.rs

package info (click to toggle)
rust-curve25519-dalek 4.2.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,848 kB
  • sloc: sh: 63; makefile: 29
file content (148 lines) | stat: -rw-r--r-- 5,805 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! This selects the curve25519_dalek_bits either by default from target_pointer_width or explicitly set

#![deny(clippy::unwrap_used, dead_code)]

#[allow(non_camel_case_types)]
#[derive(PartialEq, Debug)]
enum DalekBits {
    Dalek32,
    Dalek64,
}

use std::fmt::Formatter;

impl std::fmt::Display for DalekBits {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
        let w_bits = match self {
            DalekBits::Dalek32 => "32",
            DalekBits::Dalek64 => "64",
        };
        write!(f, "{}", w_bits)
    }
}

fn main() {
    let target_arch = match std::env::var("CARGO_CFG_TARGET_ARCH") {
        Ok(arch) => arch,
        _ => "".to_string(),
    };

    let curve25519_dalek_bits = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref() {
        Ok("32") => DalekBits::Dalek32,
        Ok("64") => DalekBits::Dalek64,
        _ => deterministic::determine_curve25519_dalek_bits(&target_arch),
    };

    println!("cargo:rustc-cfg=curve25519_dalek_bits=\"{curve25519_dalek_bits}\"");

    let nightly = if rustc_version::version_meta()
        .expect("failed to detect rustc version")
        .channel
        == rustc_version::Channel::Nightly
    {
        println!("cargo:rustc-cfg=nightly");
        true
    } else {
        false
    };

    let rustc_version = rustc_version::version().expect("failed to detect rustc version");
    if rustc_version.major == 1 && rustc_version.minor <= 64 {
        // Old versions of Rust complain when you have an `unsafe fn` and you use `unsafe {}` inside,
        // so for those we want to apply the `#[allow(unused_unsafe)]` attribute to get rid of that warning.
        println!("cargo:rustc-cfg=allow_unused_unsafe");
    }

    // Backend overrides / defaults
    let curve25519_dalek_backend = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BACKEND")
        .as_deref()
    {
        Ok("fiat") => "fiat",
        Ok("serial") => "serial",
        Ok("simd") => {
            // simd can only be enabled on x86_64 & 64bit target_pointer_width
            match is_capable_simd(&target_arch, curve25519_dalek_bits) {
                true => "simd",
                // If override is not possible this must result to compile error
                // See: issues/532
                false => panic!("Could not override curve25519_dalek_backend to simd"),
            }
        }
        Ok("unstable_avx512") if nightly => {
            // simd can only be enabled on x86_64 & 64bit target_pointer_width
            match is_capable_simd(&target_arch, curve25519_dalek_bits) {
                true => {
                    // In addition enable Avx2 fallback through simd stable backend
                    // NOTE: Compiler permits duplicate / multi value on the same key
                    println!("cargo:rustc-cfg=curve25519_dalek_backend=\"simd\"");

                    "unstable_avx512"
                }
                // If override is not possible this must result to compile error
                // See: issues/532
                false => panic!("Could not override curve25519_dalek_backend to unstable_avx512"),
            }
        }
        Ok("unstable_avx512") if !nightly => {
            panic!("Could not override curve25519_dalek_backend to unstable_avx512, as this is nightly only");
        }
        // default between serial / simd (if potentially capable)
        _ => match is_capable_simd(&target_arch, curve25519_dalek_bits) {
            true => "simd",
            false => "serial",
        },
    };
    println!("cargo:rustc-cfg=curve25519_dalek_backend=\"{curve25519_dalek_backend}\"");
}

// Is the target arch & curve25519_dalek_bits potentially simd capable ?
fn is_capable_simd(arch: &str, bits: DalekBits) -> bool {
    arch == "x86_64" && bits == DalekBits::Dalek64
}

// Deterministic cfg(curve25519_dalek_bits) when this is not explicitly set.
mod deterministic {

    use super::*;

    // Custom Rust non-cargo build tooling needs to set CARGO_CFG_TARGET_POINTER_WIDTH
    static ERR_MSG_NO_POINTER_WIDTH: &str =
        "Standard Cargo TARGET_POINTER_WIDTH environment variable is not set.";

    // When either non-32 or 64 TARGET_POINTER_WIDTH detected
    static ERR_MSG_UNKNOWN_POINTER_WIDTH: &str = "Unknown TARGET_POINTER_WIDTH detected.";

    // Warning when the curve25519_dalek_bits cannot be determined
    fn determine_curve25519_dalek_bits_warning(cause: &str) {
        println!("cargo:warning=\"Defaulting to curve25519_dalek_bits=32: {cause}\"");
    }

    // Determine the curve25519_dalek_bits based on Rust standard TARGET triplet
    pub(super) fn determine_curve25519_dalek_bits(target_arch: &String) -> DalekBits {
        let target_pointer_width = match std::env::var("CARGO_CFG_TARGET_POINTER_WIDTH") {
            Ok(pw) => pw,
            Err(_) => {
                determine_curve25519_dalek_bits_warning(ERR_MSG_NO_POINTER_WIDTH);
                return DalekBits::Dalek32;
            }
        };

        #[allow(clippy::match_single_binding)]
        match &target_arch {
            //Issues: 449 and 456
            //TODO: When adding arch defaults use proper types not String match
            //TODO(Arm): Needs tests + benchmarks to back this up
            //TODO(Wasm32): Needs tests + benchmarks to back this up
            _ => match target_pointer_width.as_ref() {
                "64" => DalekBits::Dalek64,
                "32" => DalekBits::Dalek32,
                // Intended default solely for non-32/64 target pointer widths
                // Otherwise known target platforms only.
                _ => {
                    determine_curve25519_dalek_bits_warning(ERR_MSG_UNKNOWN_POINTER_WIDTH);
                    DalekBits::Dalek32
                }
            },
        }
    }
}