Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9ef16f5

Browse files
committed
build: support pkg-config
Support querying pkg-config for mbedtls directories. When building against mbedtls, use the following search criteria to locate the mbedtls dependency: 1. Env Variables 2. pkg-config 3. vendor directory This will allow binary packages from distributions to work without modification and not require a vendored mbedtls package. The problem with vendored packages is upsates, and since mbedtls is a critical cryptographic suite, it's important that the distributions can quickly update a single mbedtls package that everyone links to. Related to: - Mbed-TLS/mbedtls#8691 Signed-off-by: Bill Roberts <[email protected]>
1 parent d268c4a commit 9ef16f5

File tree

3 files changed

+150
-92
lines changed

3 files changed

+150
-92
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

psa-crypto-sys/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cc = "1.0.59"
1717
cmake = "0.1.44"
1818
regex = "1.9.1"
1919
walkdir = "2.3.1"
20+
pkg-config = "0.3.29"
2021

2122
[features]
2223
default = ["operations"]

psa-crypto-sys/build.rs

Lines changed: 142 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,72 @@ mod common {
6666
use std::io::{Error, ErrorKind, Result};
6767
use std::path::{Path, PathBuf};
6868

69+
pub fn get_external_mbedtls() -> Option<Result<(String, String)>> {
70+
if env::var("MBEDTLS_LIB_DIR").is_err() ^ env::var("MBEDTLS_INCLUDE_DIR").is_err() {
71+
return Some(Err(Error::new(
72+
ErrorKind::Other,
73+
"both environment variables MBEDTLS_LIB_DIR and MBEDTLS_INCLUDE_DIR need to be set for operations feature",
74+
)));
75+
}
76+
77+
if let (Ok(lib_dir), Ok(include_dir)) =
78+
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
79+
{
80+
println!("Found environment varibales, using external MbedTLS");
81+
return Some(Ok((include_dir, lib_dir)));
82+
}
83+
84+
if let Ok(mbedtls_result) = pkg_config::Config::new()
85+
.range_version("3.5".."4.0")
86+
.probe("mbedtls")
87+
{
88+
let include_dirs: Vec<String> = mbedtls_result
89+
.include_paths
90+
.into_iter()
91+
.map(|x: PathBuf| -> String { x.into_os_string().into_string().unwrap() })
92+
.collect();
93+
let include_dir = include_dirs.join(" ");
94+
// The current build framework doesn't support multiple lib paths for -L unfortuantely, so
95+
// we just take the first element, which is enough for now :-(
96+
let lib_dir = <PathBuf as Clone>::clone(&mbedtls_result.link_paths[0])
97+
.into_os_string()
98+
.into_string()
99+
.unwrap();
100+
println!("Found pkg-config mbedtls, using external MbedTLS");
101+
return Some(Ok((include_dir, lib_dir)));
102+
}
103+
104+
// No env vars set and no discovered package through pkg-config
105+
None
106+
}
107+
108+
#[cfg(all(feature = "interface", not(feature = "operations")))]
109+
pub fn get_external_mbedtls_include_only() -> Result<String> {
110+
if let Ok(include_dir) = env::var("MBEDTLS_INCLUDE_DIR") {
111+
println!("Found environment varibale, using external MbedTLS");
112+
return Ok(include_dir);
113+
}
114+
115+
if let Ok(mbedtls_result) = pkg_config::Config::new()
116+
.range_version("3.5".."4.0")
117+
.probe("mbedtls")
118+
{
119+
let include_dirs: Vec<String> = mbedtls_result
120+
.include_paths
121+
.into_iter()
122+
.map(|x: PathBuf| -> String { x.into_os_string().into_string().unwrap() })
123+
.collect();
124+
let include_dir = include_dirs.join(" ");
125+
126+
return Ok(include_dir);
127+
}
128+
129+
Err(Error::new(
130+
ErrorKind::Other,
131+
"interface feature necessitates MBEDTLS_INCLUDE_DIR environment variable",
132+
))
133+
}
134+
69135
pub fn configure_mbed_crypto() -> Result<()> {
70136
let mbedtls_dir = String::from("./vendor");
71137
let mbedtls_config = mbedtls_dir + "/scripts/config.py";
@@ -209,22 +275,17 @@ mod common {
209275
#[cfg(all(feature = "interface", not(feature = "operations")))]
210276
mod interface {
211277
use super::common;
212-
use std::env;
213-
use std::io::{Error, ErrorKind, Result};
278+
use std::io::Result;
214279

215280
// Build script when the interface feature is on and not the operations one
216281
pub fn script_interface() -> Result<()> {
217-
if let Ok(include_dir) = env::var("MBEDTLS_INCLUDE_DIR") {
218-
common::configure_mbed_crypto()?;
219-
common::generate_mbed_crypto_bindings(include_dir.clone(), false)?;
220-
let _ = common::compile_shim_library(include_dir, true, false)?;
221-
Ok(())
222-
} else {
223-
Err(Error::new(
224-
ErrorKind::Other,
225-
"interface feature necessitates MBEDTLS_INCLUDE_DIR environment variable",
226-
))
227-
}
282+
let include_dir = common::get_external_mbedtls_include_only().unwrap();
283+
284+
// TODO: Does interface need the vendored mbedtls?
285+
common::configure_mbed_crypto()?;
286+
common::generate_mbed_crypto_bindings(include_dir.clone(), false)?;
287+
let _ = common::compile_shim_library(include_dir, true, false)?;
288+
Ok(())
228289
}
229290
}
230291

@@ -235,9 +296,9 @@ mod operations {
235296
use super::common::prefix;
236297
use cmake::Config;
237298
use std::env;
299+
use std::io::Result;
238300
#[cfg(feature = "prefix")]
239301
use std::io::Write;
240-
use std::io::{Error, ErrorKind, Result};
241302
use std::path::PathBuf;
242303
use walkdir::WalkDir;
243304

@@ -288,36 +349,31 @@ mod operations {
288349
let include;
289350
let external_mbedtls;
290351

291-
if env::var("MBEDTLS_LIB_DIR").is_err() ^ env::var("MBEDTLS_INCLUDE_DIR").is_err() {
292-
return Err(Error::new(
293-
ErrorKind::Other,
294-
"both environment variables MBEDTLS_LIB_DIR and MBEDTLS_INCLUDE_DIR need to be set for operations feature",
295-
));
296-
}
297-
if let (Ok(lib_dir), Ok(include_dir)) =
298-
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
299-
{
300-
println!("Found environment varibales, using external MbedTLS");
301-
lib = lib_dir;
302-
include = include_dir;
303-
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
304-
external_mbedtls = true;
305-
} else {
306-
println!("Did not find environment variables, building MbedTLS!");
307-
common::configure_mbed_crypto()?;
308-
let mut mbed_lib_dir = compile_mbed_crypto()?;
309-
let mut mbed_include_dir = mbed_lib_dir.clone();
310-
mbed_lib_dir.push("lib");
311-
if !mbed_lib_dir.as_path().exists() {
312-
_ = mbed_lib_dir.pop();
313-
mbed_lib_dir.push("lib64");
352+
match common::get_external_mbedtls() {
353+
Some(result) => {
354+
let (include_dir, lib_dir) = result.unwrap();
355+
lib = lib_dir;
356+
include = include_dir;
357+
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
358+
external_mbedtls = true;
314359
}
315-
mbed_include_dir.push("include");
360+
None => {
361+
println!("Did not find external MBEDTLS, building MbedTLS!");
362+
common::configure_mbed_crypto()?;
363+
let mut mbed_lib_dir = compile_mbed_crypto()?;
364+
let mut mbed_include_dir = mbed_lib_dir.clone();
365+
mbed_lib_dir.push("lib");
366+
if !mbed_lib_dir.as_path().exists() {
367+
_ = mbed_lib_dir.pop();
368+
mbed_lib_dir.push("lib64");
369+
}
370+
mbed_include_dir.push("include");
316371

317-
lib = mbed_lib_dir.to_str().unwrap().to_owned();
318-
include = mbed_include_dir.to_str().unwrap().to_owned();
319-
statically = true;
320-
external_mbedtls = false;
372+
lib = mbed_lib_dir.to_str().unwrap().to_owned();
373+
include = mbed_include_dir.to_str().unwrap().to_owned();
374+
statically = true;
375+
external_mbedtls = false;
376+
}
321377
}
322378

323379
// Linking to PSA Crypto library is only needed for the operations.
@@ -332,58 +388,52 @@ mod operations {
332388
#[cfg(feature = "prefix")]
333389
// Build script when the operations feature is on
334390
pub fn script_operations() -> Result<()> {
335-
if env::var("MBEDTLS_LIB_DIR").is_err() ^ env::var("MBEDTLS_INCLUDE_DIR").is_err() {
336-
return Err(Error::new(
337-
ErrorKind::Other,
338-
"both environment variables MBEDTLS_LIB_DIR and MBEDTLS_INCLUDE_DIR need to be set for operations feature",
339-
));
340-
}
341-
342-
if let (Ok(lib_dir), Ok(include_dir)) =
343-
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
344-
{
345-
println!("Building with external MBEDTLS");
346-
347-
// Request rustc to link the Mbed Crypto library
348-
let link_type = if cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok() {
349-
"static"
350-
} else {
351-
"dylib"
352-
};
353-
println!("cargo:rustc-link-search=native={}", lib_dir);
354-
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);
355-
356-
common::generate_mbed_crypto_bindings(include_dir.clone(), true)?;
357-
let _ = common::compile_shim_library(include_dir, true, true)?;
358-
} else {
359-
println!("Did not find environment variables, building MbedTLS!");
360-
common::configure_mbed_crypto()?;
361-
let mut mbed_lib_dir = compile_mbed_crypto()?;
362-
let mut mbed_include_dir = mbed_lib_dir.clone();
363-
mbed_lib_dir.push("lib");
364-
if !mbed_lib_dir.as_path().exists() {
365-
_ = mbed_lib_dir.pop();
366-
mbed_lib_dir.push("lib64");
391+
match common::get_external_mbedtls() {
392+
Some(result) => {
393+
let (include_dir, lib_dir) = result.unwrap();
394+
// Request rustc to link the Mbed Crypto library
395+
let link_type = if cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok()
396+
{
397+
"static"
398+
} else {
399+
"dylib"
400+
};
401+
println!("cargo:rustc-link-search=native={}", lib_dir);
402+
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);
403+
404+
common::generate_mbed_crypto_bindings(include_dir.clone(), true)?;
405+
let _ = common::compile_shim_library(include_dir, true, true)?;
367406
}
407+
None => {
408+
println!("Did not find environment variables, building MbedTLS!");
409+
common::configure_mbed_crypto()?;
410+
let mut mbed_lib_dir = compile_mbed_crypto()?;
411+
let mut mbed_include_dir = mbed_lib_dir.clone();
412+
mbed_lib_dir.push("lib");
413+
if !mbed_lib_dir.as_path().exists() {
414+
_ = mbed_lib_dir.pop();
415+
mbed_lib_dir.push("lib64");
416+
}
368417

369-
mbed_include_dir.push("include");
370-
let main_lib = mbed_lib_dir.join("libmbedcrypto.a");
371-
372-
let include = mbed_include_dir.to_str().unwrap().to_owned();
373-
common::generate_mbed_crypto_bindings(include.clone(), false)?;
374-
let shim_lib = common::compile_shim_library(include, false, false)?;
375-
376-
// Modify and copy the libraries into a new directory.
377-
let llib_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("llib");
378-
let main_lib_name = prefix() + "mbedcrypto";
379-
let shim_lib_name = prefix() + "shim";
380-
objcopy(vec![
381-
(main_lib, llib_path.join(format!("lib{}.a", main_lib_name))),
382-
(shim_lib, llib_path.join(format!("lib{}.a", shim_lib_name))),
383-
])?;
384-
println!("cargo:rustc-link-search=native={}", llib_path.display());
385-
println!("cargo:rustc-link-lib=static={}", main_lib_name);
386-
println!("cargo:rustc-link-lib=static={}", shim_lib_name);
418+
mbed_include_dir.push("include");
419+
let main_lib = mbed_lib_dir.join("libmbedcrypto.a");
420+
421+
let include = mbed_include_dir.to_str().unwrap().to_owned();
422+
common::generate_mbed_crypto_bindings(include.clone(), false)?;
423+
let shim_lib = common::compile_shim_library(include, false, false)?;
424+
425+
// Modify and copy the libraries into a new directory.
426+
let llib_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("llib");
427+
let main_lib_name = prefix() + "mbedcrypto";
428+
let shim_lib_name = prefix() + "shim";
429+
objcopy(vec![
430+
(main_lib, llib_path.join(format!("lib{}.a", main_lib_name))),
431+
(shim_lib, llib_path.join(format!("lib{}.a", shim_lib_name))),
432+
])?;
433+
println!("cargo:rustc-link-search=native={}", llib_path.display());
434+
println!("cargo:rustc-link-lib=static={}", main_lib_name);
435+
println!("cargo:rustc-link-lib=static={}", shim_lib_name);
436+
}
387437
}
388438

389439
Ok(())

0 commit comments

Comments
 (0)