@@ -30,6 +30,88 @@ Cflags: -I${{includedir}}
3030 out_file. write_all ( output. as_bytes ( ) ) . unwrap ( ) ;
3131}
3232
33+ /// Returns true if cargo resolved `boring` to a 4.x version.
34+ ///
35+ /// Walks up from `OUT_DIR` looking for a `Cargo.lock`, then scans it
36+ /// for the `boring` package. We use `Cargo.lock` rather than shelling
37+ /// out to `cargo metadata` because (a) the lockfile is guaranteed to
38+ /// exist at this point in the build, (b) parsing it is cheap and has
39+ /// no extra dependencies, and (c) it avoids re-entering cargo from a
40+ /// build script.
41+ ///
42+ /// 4.x is the *legacy* branch; `cfg(boring_v4)` is meant to be a
43+ /// transitional flag that we can drop once internal users have all
44+ /// moved to 5.x. New code should live in the `not(boring_v4)` arm so
45+ /// removing the cfg later is just deleting the legacy arm.
46+ fn detect_boring_v4 ( ) -> bool {
47+ let Some ( lockfile) = find_cargo_lock ( ) else {
48+ // No lockfile (shouldn't happen in normal cargo builds, but
49+ // be conservative). Assume 5.x — the default and forward-
50+ // looking version. Downstream can fix this by generating a
51+ // lockfile (`cargo generate-lockfile`).
52+ println ! (
53+ "cargo:warning=quiche: Cargo.lock not found; assuming boring 5.x"
54+ ) ;
55+ return false ;
56+ } ;
57+
58+ println ! ( "cargo:rerun-if-changed={}" , lockfile. display( ) ) ;
59+
60+ let contents = match std:: fs:: read_to_string ( & lockfile) {
61+ Ok ( s) => s,
62+ Err ( e) => {
63+ println ! (
64+ "cargo:warning=quiche: failed to read {}: {e}; assuming boring 5.x" ,
65+ lockfile. display( ) ,
66+ ) ;
67+ return false ;
68+ } ,
69+ } ;
70+
71+ // The lockfile is TOML but a regex-light scan is enough: find a
72+ // `[[package]]` whose `name = "boring"` (not "boring-sys") and
73+ // read its `version`.
74+ let mut in_boring = false ;
75+ for line in contents. lines ( ) {
76+ let line = line. trim ( ) ;
77+ if line == "[[package]]" {
78+ in_boring = false ;
79+ continue ;
80+ }
81+ if line == "name = \" boring\" " {
82+ in_boring = true ;
83+ continue ;
84+ }
85+ if in_boring {
86+ if let Some ( rest) = line. strip_prefix ( "version = \" " ) {
87+ let version = rest. trim_end_matches ( '"' ) ;
88+ let major = version. split ( '.' ) . next ( ) . unwrap_or ( "" ) ;
89+ return major == "4" ;
90+ }
91+ }
92+ }
93+
94+ // `boring` not present in the lockfile (e.g.
95+ // `boringssl-boring-crate` is off). Doesn't matter what we return
96+ // since the `cfg` won't be observed.
97+ false
98+ }
99+
100+ fn find_cargo_lock ( ) -> Option < std:: path:: PathBuf > {
101+ // Start from `CARGO_MANIFEST_DIR` and walk up. Cargo guarantees
102+ // the lockfile lives at the workspace root, which is an ancestor
103+ // of the manifest dir.
104+ let manifest_dir =
105+ std:: path:: PathBuf :: from ( std:: env:: var_os ( "CARGO_MANIFEST_DIR" ) ?) ;
106+ for dir in manifest_dir. ancestors ( ) {
107+ let candidate = dir. join ( "Cargo.lock" ) ;
108+ if candidate. is_file ( ) {
109+ return Some ( candidate) ;
110+ }
111+ }
112+ None
113+ }
114+
33115fn target_dir_path ( ) -> std:: path:: PathBuf {
34116 let out_dir = std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ;
35117 let out_dir = std:: path:: Path :: new ( & out_dir) ;
@@ -44,7 +126,21 @@ fn target_dir_path() -> std::path::PathBuf {
44126}
45127
46128fn main ( ) {
129+ // The `boring` workspace dep has a wide version range
130+ // (`>=4.21, <6`) so the resolver can pick either 4.x or 5.x based
131+ // on downstream constraints. The two majors differ in their
132+ // default TLS curve list (5.x advertises post-quantum key shares)
133+ // and in their Rust API for raw public keys, so we need to switch
134+ // on the resolved version at compile time. Detect it here and
135+ // emit `cfg(boring_v4)` for the legacy 4.x case.
136+ //
137+ // The cfg is always registered (even when the backend feature is
138+ // off) so rustc doesn't warn about unknown cfg names.
139+ println ! ( "cargo::rustc-check-cfg=cfg(boring_v4)" ) ;
47140 if cfg ! ( feature = "boringssl-boring-crate" ) {
141+ if detect_boring_v4 ( ) {
142+ println ! ( "cargo:rustc-cfg=boring_v4" ) ;
143+ }
48144 println ! ( "cargo:rustc-link-lib=static=ssl" ) ;
49145 println ! ( "cargo:rustc-link-lib=static=crypto" ) ;
50146 }
0 commit comments