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

Skip to content

Commit 404aeb4

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 404aeb4

File tree

3 files changed

+151
-90
lines changed

3 files changed

+151
-90
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: 143 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,74 @@ mod common {
6666
use std::io::{Error, ErrorKind, Result};
6767
use std::path::{Path, PathBuf};
6868

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

215283
// Build script when the interface feature is on and not the operations one
216284
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-
}
285+
let include_dir = common::get_external_mbedtls_include_only().unwrap();
286+
287+
// TODO: Does interface need the vendored mbedtls?
288+
common::configure_mbed_crypto()?;
289+
common::generate_mbed_crypto_bindings(include_dir.clone(), false)?;
290+
let _ = common::compile_shim_library(include_dir, true, false)?;
291+
Ok(())
228292
}
229293
}
230294

@@ -235,9 +299,9 @@ mod operations {
235299
use super::common::prefix;
236300
use cmake::Config;
237301
use std::env;
302+
use std::io::Result;
238303
#[cfg(feature = "prefix")]
239304
use std::io::Write;
240-
use std::io::{Error, ErrorKind, Result};
241305
use std::path::PathBuf;
242306
use walkdir::WalkDir;
243307

@@ -288,36 +352,31 @@ mod operations {
288352
let include;
289353
let external_mbedtls;
290354

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");
355+
match common::get_external_mbedtls() {
356+
Some(result) => {
357+
let (include_dir, lib_dir) = result.unwrap();
358+
lib = lib_dir;
359+
include = include_dir;
360+
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
361+
external_mbedtls = true;
314362
}
315-
mbed_include_dir.push("include");
363+
None => {
364+
println!("Did not find external MBEDTLS, building MbedTLS!");
365+
common::configure_mbed_crypto()?;
366+
let mut mbed_lib_dir = compile_mbed_crypto()?;
367+
let mut mbed_include_dir = mbed_lib_dir.clone();
368+
mbed_lib_dir.push("lib");
369+
if !mbed_lib_dir.as_path().exists() {
370+
_ = mbed_lib_dir.pop();
371+
mbed_lib_dir.push("lib64");
372+
}
373+
mbed_include_dir.push("include");
316374

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;
375+
lib = mbed_lib_dir.to_str().unwrap().to_owned();
376+
include = mbed_include_dir.to_str().unwrap().to_owned();
377+
statically = true;
378+
external_mbedtls = false;
379+
}
321380
}
322381

323382
// Linking to PSA Crypto library is only needed for the operations.
@@ -332,58 +391,52 @@ mod operations {
332391
#[cfg(feature = "prefix")]
333392
// Build script when the operations feature is on
334393
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");
394+
match common::get_external_mbedtls() {
395+
Some(result) => {
396+
let (include_dir, lib_dir) = result.unwrap();
397+
// Request rustc to link the Mbed Crypto library
398+
let link_type = if cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok()
399+
{
400+
"static"
401+
} else {
402+
"dylib"
403+
};
404+
println!("cargo:rustc-link-search=native={}", lib_dir);
405+
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);
406+
407+
common::generate_mbed_crypto_bindings(include_dir.clone(), true)?;
408+
let _ = common::compile_shim_library(include_dir, true, true)?;
367409
}
410+
None => {
411+
println!("Did not find environment variables, building MbedTLS!");
412+
common::configure_mbed_crypto()?;
413+
let mut mbed_lib_dir = compile_mbed_crypto()?;
414+
let mut mbed_include_dir = mbed_lib_dir.clone();
415+
mbed_lib_dir.push("lib");
416+
if !mbed_lib_dir.as_path().exists() {
417+
_ = mbed_lib_dir.pop();
418+
mbed_lib_dir.push("lib64");
419+
}
368420

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);
421+
mbed_include_dir.push("include");
422+
let main_lib = mbed_lib_dir.join("libmbedcrypto.a");
423+
424+
let include = mbed_include_dir.to_str().unwrap().to_owned();
425+
common::generate_mbed_crypto_bindings(include.clone(), false)?;
426+
let shim_lib = common::compile_shim_library(include, false, false)?;
427+
428+
// Modify and copy the libraries into a new directory.
429+
let llib_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("llib");
430+
let main_lib_name = prefix() + "mbedcrypto";
431+
let shim_lib_name = prefix() + "shim";
432+
objcopy(vec![
433+
(main_lib, llib_path.join(format!("lib{}.a", main_lib_name))),
434+
(shim_lib, llib_path.join(format!("lib{}.a", shim_lib_name))),
435+
])?;
436+
println!("cargo:rustc-link-search=native={}", llib_path.display());
437+
println!("cargo:rustc-link-lib=static={}", main_lib_name);
438+
println!("cargo:rustc-link-lib=static={}", shim_lib_name);
439+
}
387440
}
388441

389442
Ok(())

0 commit comments

Comments
 (0)