1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use anyhow::anyhow;
16 use cmd_runner::{run_cmd_shell, run_cmd_shell_with_color, YellowStderr};
17 use semver::{Version, VersionReq};
18 use std::{env, fs, path::Path};
19
20 use crate::CargoOptions;
21
build_boringssl(root: &Path) -> anyhow::Result<()>22 pub fn build_boringssl(root: &Path) -> anyhow::Result<()> {
23 let bindgen_version_req = VersionReq::parse(">=0.69.4")?;
24 let bindgen_version = get_bindgen_version()?;
25
26 if !bindgen_version_req.matches(&bindgen_version) {
27 return Err(anyhow!("Bindgen does not match expected version: {bindgen_version_req}"));
28 }
29
30 let vendor_dir = root
31 .parent()
32 .ok_or_else(|| anyhow!("project root dir no parent dir"))?
33 .join("boringssl-build");
34 fs::create_dir_all(&vendor_dir)?;
35
36 let build_dir = root
37 .parent()
38 .ok_or_else(|| anyhow!("project root dir no parent dir"))?
39 .join("third_party/boringssl/build");
40 fs::create_dir_all(&build_dir)?;
41
42 let target = run_cmd_shell_with_color::<YellowStderr>(&vendor_dir, "rustc -vV")?
43 .stdout()
44 .lines()
45 .find(|l| l.starts_with("host: "))
46 .and_then(|l| l.split_once(' '))
47 .ok_or_else(|| anyhow!("Couldn't get rustc target"))?
48 .1
49 .to_string();
50 let target = shell_escape::escape(target.into());
51 run_cmd_shell_with_color::<YellowStderr>(
52 &build_dir,
53 format!(
54 "cmake -G Ninja .. -DRUST_BINDINGS={} -DCMAKE_POSITION_INDEPENDENT_CODE=true",
55 target
56 ),
57 )?;
58 run_cmd_shell(&build_dir, "ninja")?;
59
60 Ok(())
61 }
62
check_boringssl(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()>63 pub fn check_boringssl(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
64 log::info!("Checking boringssl");
65
66 build_boringssl(root)?;
67
68 let bssl_dir = root.join("crypto/crypto_provider_boringssl");
69
70 let locked_arg = if cargo_options.locked { "--locked" } else { "" };
71
72 run_cmd_shell(&bssl_dir, format!("cargo check {locked_arg}"))?;
73 run_cmd_shell(&bssl_dir, "cargo fmt --check")?;
74 run_cmd_shell(&bssl_dir, "cargo clippy --all-targets")?;
75 run_cmd_shell(&bssl_dir, cargo_options.test("check_boringssl", ""))?;
76 run_cmd_shell(&bssl_dir, "cargo doc --no-deps")?;
77 run_cmd_shell(
78 root,
79 cargo_options.test(
80 "check_boringssl_ukey2",
81 "-p ukey2_connections -p ukey2_rs --no-default-features --features test_boringssl",
82 ),
83 )?;
84 Ok(())
85 }
86
87 /// Checks out latest boringssl commit and runs our crypto provider tests against it
check_boringssl_at_head(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()>88 pub fn check_boringssl_at_head(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
89 // TODO: find a better way, a kokoro implemented auto-roller?
90 build_boringssl_at_latest(root)?;
91
92 let bssl_dir = root.join("crypto/crypto_provider_boringssl");
93 run_cmd_shell(&bssl_dir, "cargo check")?;
94 run_cmd_shell(&bssl_dir, cargo_options.test("check_boringssl_latest", ""))?;
95 Ok(())
96 }
97
build_boringssl_at_latest(root: &Path) -> anyhow::Result<()>98 fn build_boringssl_at_latest(root: &Path) -> anyhow::Result<()> {
99 // Now check boringssl against HEAD. Kokoro does not allow us to directly update the git submodule
100 // so we must use manual hackery instead :/
101 run_cmd_shell(root.parent().unwrap(), "rm -Rf third_party/boringssl")?;
102 run_cmd_shell(
103 &root.parent().unwrap().join("third_party"),
104 "git clone https://boringssl.googlesource.com/boringssl",
105 )?;
106 run_cmd_shell(
107 &root.parent().unwrap().join("third_party/boringssl"),
108 "git checkout origin/master",
109 )?;
110 build_boringssl(root)?;
111 Ok(())
112 }
113
get_bindgen_version() -> anyhow::Result<Version>114 fn get_bindgen_version() -> anyhow::Result<Version> {
115 let bindgen_version_output = run_cmd_shell(&env::current_dir().unwrap(), "bindgen --version")?;
116
117 let version = bindgen_version_output
118 .stdout()
119 .lines()
120 .next()
121 .ok_or(anyhow!("bindgen version output stream is empty"))?
122 .strip_prefix("bindgen ")
123 .ok_or(anyhow!("bindgen version output missing expected prefix of \"bindgen \""))?
124 .parse::<Version>()?;
125
126 Ok(version)
127 }
128