Skip to content

Commit 8f28aa9

Browse files
committed
Added support for building boringssl with bindgen
This allows building it without the bssl-sys crate. This is an alternative approach to fixing sfackler#1768 (in contrast to sfackler#1806). This maintains support for using the bssl-sys crate.
1 parent 3251678 commit 8f28aa9

File tree

10 files changed

+179
-33
lines changed

10 files changed

+179
-33
lines changed

.github/workflows/ci.yml

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ jobs:
153153
- false
154154
library:
155155
- name: boringssl
156-
version: 5697a9202615925696f8dc7f4e286d44d474769e
156+
version: 93e8d4463d59d671e9c5c6171226341f04b07907
157157
- name: openssl
158158
version: vendored
159159
- name: openssl
@@ -215,10 +215,6 @@ jobs:
215215
library:
216216
name: libressl
217217
version: 3.7.0
218-
exclude:
219-
- library:
220-
name: boringssl
221-
bindgen: true
222218
name: ${{ matrix.target }}-${{ matrix.library.name }}-${{ matrix.library.version }}-${{ matrix.bindgen }}
223219
runs-on: ubuntu-latest
224220
env:
@@ -311,24 +307,34 @@ jobs:
311307
make install_sw
312308
;;
313309
"boringssl")
314-
sed -i rust/CMakeLists.txt -e '1s%^%include_directories(../include)\n%'
315-
cpu=`echo ${{ matrix.target }} | cut -d - -f 1`
310+
mkdir build
311+
cd build
312+
316313
echo "set(CMAKE_SYSTEM_NAME Linux)" > toolchain.cmake
317314
echo "set(CMAKE_SYSTEM_PROCESSOR $cpu)" >> toolchain.cmake
318315
echo "set(triple ${{ matrix.target }})" >> toolchain.cmake
319316
echo 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} '$OS_FLAGS '" CACHE STRING "c++ flags")' >> toolchain.cmake
320317
echo 'set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} '$OS_FLAGS '" CACHE STRING "c flags")' >> toolchain.cmake
321318
echo 'set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} '$OS_FLAGS '" CACHE STRING "asm flags")' >> toolchain.cmake
322-
cmake -DRUST_BINDINGS="${{ matrix.target }}" -B $OPENSSL_DIR -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
323-
make -C $OPENSSL_DIR
319+
320+
cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DRUST_BINDINGS="${{ matrix.target }}" -DCMAKE_INSTALL_PREFIX="${OPENSSL_DIR}" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
321+
make -j "$(nproc)"
322+
make install
323+
324+
# Copy stuff around so it's all as the build system expects.
325+
cp -r rust/ "$OPENSSL_DIR/rust"
326+
mkdir -p "$OPENSSL_DIR/crypto/"
327+
mkdir -p "$OPENSSL_DIR/ssl/"
328+
cp "$OPENSSL_DIR/lib/libcrypto.a" "$OPENSSL_DIR/crypto/"
329+
cp "$OPENSSL_DIR/lib/libssl.a" "$OPENSSL_DIR/ssl/"
324330
esac
325331
326332
if: matrix.library.version != 'vendored' && !steps.openssl-cache.outputs.cache-hit
327333
- run: |
328334
mkdir -p .cargo
329335
echo '[patch.crates-io]' > .cargo/config.toml
330336
echo 'bssl-sys = { path = "'$OPENSSL_DIR'/rust" }' >> .cargo/config.toml
331-
if: matrix.library.name == 'boringssl'
337+
if: matrix.library.name == 'boringssl' && !matrix.bindgen
332338
- uses: actions/cache@v3
333339
with:
334340
path: ~/.cargo/registry/index
@@ -350,14 +356,14 @@ jobs:
350356
if [[ "${{ matrix.library.version }}" == "vendored" ]]; then
351357
features="--features vendored"
352358
fi
353-
if [[ "${{ matrix.bindgen }}" == "true" ]]; then
359+
if [[ "${{ matrix.bindgen }}" == "true" && "${{ matrix.library.name }}" != "boringssl" ]]; then
354360
features="$features --features bindgen"
355361
fi
356362
cargo run --manifest-path=systest/Cargo.toml --target ${{ matrix.target }} $features
357363
if: matrix.library.name != 'boringssl'
358364
- name: Test openssl
359365
run: |
360-
if [[ "${{ matrix.library.name }}" == "boringssl" ]]; then
366+
if [[ "${{ matrix.library.name }}" == "boringssl" && "${{ matrix.bindgen }}" != "true" ]]; then
361367
features="--features unstable_boringssl"
362368
fi
363369
if [[ "${{ matrix.library.version }}" == "vendored" ]]; then

openssl-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ libc = "0.2"
2323
bssl-sys = { version = "0.1.0", optional = true }
2424

2525
[build-dependencies]
26-
bindgen = { version = "0.60.1", optional = true }
26+
bindgen = { version = "0.64.0", optional = true, features = ["experimental"] }
2727
cc = "1.0"
2828
openssl-src = { version = "111", optional = true }
2929
pkg-config = "0.3.9"

openssl-sys/build/main.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ mod cfgs;
2323
mod find_normal;
2424
#[cfg(feature = "vendored")]
2525
mod find_vendored;
26-
#[cfg(feature = "bindgen")]
2726
mod run_bindgen;
2827

2928
#[derive(PartialEq)]
@@ -32,6 +31,7 @@ enum Version {
3231
Openssl11x,
3332
Openssl10x,
3433
Libressl,
34+
Boringssl,
3535
}
3636

3737
fn env_inner(name: &str) -> Option<OsString> {
@@ -67,10 +67,9 @@ fn find_openssl(target: &str) -> (Vec<PathBuf>, PathBuf) {
6767
fn check_ssl_kind() {
6868
if cfg!(feature = "unstable_boringssl") {
6969
println!("cargo:rustc-cfg=boringssl");
70+
println!("cargo:boringssl=true");
7071
// BoringSSL does not have any build logic, exit early
7172
std::process::exit(0);
72-
} else {
73-
println!("cargo:rustc-cfg=openssl");
7473
}
7574
}
7675

@@ -146,8 +145,12 @@ fn check_rustc_versions() {
146145
#[allow(clippy::let_and_return)]
147146
fn postprocess(include_dirs: &[PathBuf]) -> Version {
148147
let version = validate_headers(include_dirs);
149-
#[cfg(feature = "bindgen")]
150-
run_bindgen::run(&include_dirs);
148+
149+
// Never run bindgen for BoringSSL, if it was needed we already ran it.
150+
if version != Version::Boringssl {
151+
#[cfg(feature = "bindgen")]
152+
run_bindgen::run(&include_dirs);
153+
}
151154

152155
version
153156
}
@@ -235,9 +238,15 @@ See rust-openssl documentation for more information:
235238
}
236239

237240
if is_boringssl {
238-
panic!("BoringSSL detected, but `unstable_boringssl` feature wasn't specified.")
241+
println!("cargo:rustc-cfg=boringssl");
242+
println!("cargo:boringssl=true");
243+
run_bindgen::run_boringssl(include_dirs);
244+
return Version::Boringssl;
239245
}
240246

247+
// We set this for any non-BoringSSL lib.
248+
println!("cargo:rustc-cfg=openssl");
249+
241250
for enabled in &enabled {
242251
println!("cargo:rustc-cfg=osslconf=\"{}\"", enabled);
243252
}

openssl-sys/build/run_bindgen.rs

Lines changed: 112 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
#[cfg(feature = "bindgen")]
12
use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks};
2-
use bindgen::RustTarget;
3-
use std::env;
3+
#[cfg(feature = "bindgen")]
4+
use bindgen::{MacroTypeVariation, RustTarget};
5+
use std::io::Write;
46
use std::path::PathBuf;
7+
use std::{env, fs};
8+
#[cfg(not(feature = "bindgen"))]
9+
use std::process;
510

611
const INCLUDES: &str = "
712
#include <openssl/aes.h>
813
#include <openssl/asn1.h>
914
#include <openssl/bio.h>
10-
#include <openssl/comp.h>
1115
#include <openssl/conf.h>
1216
#include <openssl/crypto.h>
1317
#include <openssl/dh.h>
@@ -17,7 +21,6 @@ const INCLUDES: &str = "
1721
#include <openssl/evp.h>
1822
#include <openssl/hmac.h>
1923
#include <openssl/objects.h>
20-
#include <openssl/ocsp.h>
2124
#include <openssl/opensslv.h>
2225
#include <openssl/pem.h>
2326
#include <openssl/pkcs12.h>
@@ -35,10 +38,15 @@ const INCLUDES: &str = "
3538
// this must be included after ssl.h for libressl!
3639
#include <openssl/srtp.h>
3740
38-
#if !defined(LIBRESSL_VERSION_NUMBER)
41+
#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
3942
#include <openssl/cms.h>
4043
#endif
4144
45+
#if !defined(OPENSSL_IS_BORINGSSL)
46+
#include <openssl/comp.h>
47+
#include <openssl/ocsp.h>
48+
#endif
49+
4250
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
4351
#include <openssl/kdf.h>
4452
#endif
@@ -48,6 +56,7 @@ const INCLUDES: &str = "
4856
#endif
4957
";
5058

59+
#[cfg(feature = "bindgen")]
5160
pub fn run(include_dirs: &[PathBuf]) {
5261
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
5362

@@ -94,9 +103,107 @@ pub fn run(include_dirs: &[PathBuf]) {
94103
.unwrap();
95104
}
96105

106+
#[cfg(feature = "bindgen")]
107+
pub fn run_boringssl(include_dirs: &[PathBuf]) {
108+
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
109+
let mut builder = bindgen::builder()
110+
.rust_target(RustTarget::Stable_1_47)
111+
.ctypes_prefix("::libc")
112+
.derive_default(false)
113+
.enable_function_attribute_detection()
114+
.size_t_is_usize(true)
115+
.default_macro_constant_type(MacroTypeVariation::Signed)
116+
.rustified_enum("point_conversion_form_t")
117+
.allowlist_file(".*/openssl/[^/]+\\.h")
118+
.wrap_static_fns(true)
119+
.wrap_static_fns_path(out_dir.join("boring_static_wrapper").display().to_string())
120+
.layout_tests(false)
121+
.header_contents("includes.h", INCLUDES);
122+
123+
for include_dir in include_dirs {
124+
builder = builder
125+
.clang_arg("-I")
126+
.clang_arg(include_dir.display().to_string());
127+
}
128+
129+
builder
130+
.generate()
131+
.unwrap()
132+
.write_to_file(out_dir.join("bindgen.rs"))
133+
.unwrap();
134+
135+
fs::File::create(out_dir.join("boring_static_wrapper.h"))
136+
.expect("Failed to create boring_static_wrapper.h")
137+
.write_all(INCLUDES.as_bytes())
138+
.expect("Failed to write contents to boring_static_wrapper.h");
139+
140+
cc::Build::new()
141+
.file(out_dir.join("boring_static_wrapper.c"))
142+
.includes(include_dirs)
143+
.flag("-include")
144+
.flag(
145+
&out_dir
146+
.join("boring_static_wrapper.h")
147+
.display()
148+
.to_string(),
149+
)
150+
.compile("boring_static_wrapper");
151+
}
152+
153+
#[cfg(not(feature = "bindgen"))]
154+
pub fn run_boringssl(include_dirs: &[PathBuf]) {
155+
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
156+
157+
fs::File::create(out_dir.join("boring_static_wrapper.h"))
158+
.expect("Failed to create boring_static_wrapper.h")
159+
.write_all(INCLUDES.as_bytes())
160+
.expect("Failed to write contents to boring_static_wrapper.h");
161+
162+
let mut bindgen_cmd = process::Command::new("bindgen");
163+
bindgen_cmd
164+
.arg("-o")
165+
.arg(out_dir.join("bindgen.rs"))
166+
.arg("--rust-target=1.47")
167+
.arg("--ctypes-prefix=::libc")
168+
.arg("--no-derive-default")
169+
.arg("--enable-function-attribute-detection")
170+
.arg("--size_t-is-usize")
171+
.arg("--default-macro-constant-type=signed")
172+
.arg("--rustified-enum=point_conversion_form_t")
173+
.arg("--allowlist-file=.*/openssl/[^/]+\\.h")
174+
.arg("--experimental")
175+
.arg("--wrap-static-fns")
176+
.arg("--wrap-static-fns-path")
177+
.arg(out_dir.join("boring_static_wrapper").display().to_string())
178+
.arg("--no-layout-tests")
179+
.arg(out_dir.join("boring_static_wrapper.h"))
180+
.arg("--")
181+
.arg(format!("--target={}", env::var("TARGET").unwrap()));
182+
183+
for include_dir in include_dirs {
184+
bindgen_cmd.arg("-I").arg(include_dir.display().to_string());
185+
}
186+
187+
let result = bindgen_cmd.status().expect("bindgen failed to execute");
188+
assert!(result.success());
189+
190+
cc::Build::new()
191+
.file(out_dir.join("boring_static_wrapper.c"))
192+
.includes(include_dirs)
193+
.flag("-include")
194+
.flag(
195+
&out_dir
196+
.join("boring_static_wrapper.h")
197+
.display()
198+
.to_string(),
199+
)
200+
.compile("boring_static_wrapper");
201+
}
202+
97203
#[derive(Debug)]
98204
struct OpensslCallbacks;
99205

206+
#[cfg(feature = "bindgen")]
100207
impl ParseCallbacks for OpensslCallbacks {
101208
// for now we'll continue hand-writing constants
102209
fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior {

openssl-sys/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,25 @@
1616
extern crate libc;
1717
pub use libc::*;
1818

19-
#[cfg(boringssl)]
19+
#[cfg(feature = "unstable_boringssl")]
2020
extern crate bssl_sys;
21-
#[cfg(boringssl)]
21+
#[cfg(feature = "unstable_boringssl")]
2222
pub use bssl_sys::*;
2323

24+
#[cfg(all(boringssl, not(feature = "unstable_boringssl")))]
25+
#[path = "."]
26+
mod boringssl {
27+
include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
28+
29+
pub fn init() {
30+
unsafe {
31+
CRYPTO_library_init();
32+
}
33+
}
34+
}
35+
#[cfg(all(boringssl, not(feature = "unstable_boringssl")))]
36+
pub use boringssl::*;
37+
2438
#[cfg(openssl)]
2539
#[path = "."]
2640
mod openssl {

openssl/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn main() {
1111
println!("cargo:rustc-cfg=libressl");
1212
}
1313

14-
if env::var("CARGO_FEATURE_UNSTABLE_BORINGSSL").is_ok() {
14+
if env::var("DEP_OPENSSL_BORINGSSL").is_ok() {
1515
println!("cargo:rustc-cfg=boringssl");
1616
return;
1717
}

openssl/src/bio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<'a> MemBioSlice<'a> {
2525
let bio = unsafe {
2626
cvt_p(BIO_new_mem_buf(
2727
buf.as_ptr() as *const _,
28-
buf.len() as c_int,
28+
buf.len() as crate::SLenType,
2929
))?
3030
};
3131

@@ -74,7 +74,7 @@ impl MemBio {
7474
}
7575

7676
cfg_if! {
77-
if #[cfg(ossl102)] {
77+
if #[cfg(any(ossl102, boringssl))] {
7878
use ffi::BIO_new_mem_buf;
7979
} else {
8080
#[allow(bad_style)]

openssl/src/dh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ where
239239
}
240240

241241
cfg_if! {
242-
if #[cfg(any(ossl110, libressl270))] {
242+
if #[cfg(any(ossl110, libressl270, boringssl))] {
243243
use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
244244
} else {
245245
#[allow(bad_style)]

openssl/src/error.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,19 +297,24 @@ impl fmt::Debug for Error {
297297
}
298298

299299
impl fmt::Display for Error {
300+
// On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on
301+
// OpenSSL/LibreSSL they're safe.
302+
#[allow(unused_unsafe)]
300303
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
301304
write!(fmt, "error:{:08X}", self.code())?;
302305
match self.library() {
303306
Some(l) => write!(fmt, ":{}", l)?,
304-
None => write!(fmt, ":lib({})", ffi::ERR_GET_LIB(self.code()))?,
307+
None => write!(fmt, ":lib({})", unsafe { ffi::ERR_GET_LIB(self.code()) })?,
305308
}
306309
match self.function() {
307310
Some(f) => write!(fmt, ":{}", f)?,
308-
None => write!(fmt, ":func({})", ffi::ERR_GET_FUNC(self.code()))?,
311+
None => write!(fmt, ":func({})", unsafe { ffi::ERR_GET_FUNC(self.code()) })?,
309312
}
310313
match self.reason() {
311314
Some(r) => write!(fmt, ":{}", r)?,
312-
None => write!(fmt, ":reason({})", ffi::ERR_GET_REASON(self.code()))?,
315+
None => write!(fmt, ":reason({})", unsafe {
316+
ffi::ERR_GET_REASON(self.code())
317+
})?,
313318
}
314319
write!(
315320
fmt,

0 commit comments

Comments
 (0)