1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::env;
6 use std::path::Path;
7 use std::path::PathBuf;
8 use std::process::Command;
9
10 use anyhow::bail;
11 use anyhow::Result;
12
13 /// Returns the target triplet prefix for gcc commands. No prefix is required
14 /// for native builds.
get_cross_compile_prefix() -> String15 fn get_cross_compile_prefix() -> String {
16 let target = env::var("TARGET").unwrap();
17
18 if env::var("HOST").unwrap() == target {
19 return String::from("");
20 }
21
22 let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
23 let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
24 let env = if target.ends_with("-gnueabihf") {
25 String::from("gnueabihf")
26 } else {
27 env::var("CARGO_CFG_TARGET_ENV").unwrap()
28 };
29 format!("{}-{}-{}-", arch, os, env)
30 }
31
build_libtpm2(out_dir: &Path) -> Result<()>32 fn build_libtpm2(out_dir: &Path) -> Result<()> {
33 let lib_path = out_dir.join("libtpm2.a");
34 if lib_path.exists() {
35 return Ok(());
36 }
37
38 if !Path::new("libtpm2/.git").exists() {
39 bail!(
40 "tpm2-sys/libtpm2 source does not exist, did you forget to \
41 `git submodule update --init`?"
42 );
43 }
44
45 let make_flags = env::var("CARGO_MAKEFLAGS").unwrap();
46 let prefix = get_cross_compile_prefix();
47 let status = Command::new("make")
48 .env("MAKEFLAGS", make_flags)
49 .arg(format!("AR={}ar", prefix))
50 .arg(format!("CC={}gcc", prefix))
51 .arg(format!("OBJCOPY={}objcopy", prefix))
52 .arg("CFLAGS=-Wno-error")
53 .arg(format!("obj={}", out_dir.display()))
54 .current_dir("libtpm2")
55 .status()?;
56 if !status.success() {
57 bail!("make failed with status: {}", status);
58 }
59 Ok(())
60 }
61
main() -> Result<()>62 fn main() -> Result<()> {
63 // Skip installing dependencies when generating documents.
64 if std::env::var("CARGO_DOC").is_ok() {
65 return Ok(());
66 }
67
68 // libtpm2 is unix only
69 if std::env::var("CARGO_CFG_UNIX").is_err() {
70 return Ok(());
71 }
72
73 // Use tpm2 package from the standard system location if available.
74 if pkg_config::Config::new()
75 .statik(true)
76 .probe("libtpm2")
77 .is_ok()
78 {
79 return Ok(());
80 }
81
82 // Otherwise build from source
83 let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
84 build_libtpm2(&out_dir)?;
85
86 println!("cargo:rustc-link-search={}", out_dir.display());
87 println!("cargo:rustc-link-lib=static=tpm2");
88 println!("cargo:rustc-link-lib=ssl");
89 println!("cargo:rustc-link-lib=crypto");
90 Ok(())
91 }
92