• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Additional parameters for Android build of BoringSSL.
2 //
3 // Requires Android NDK >= 19.
4 const CMAKE_PARAMS_ANDROID_NDK: &[(&str, &[(&str, &str)])] = &[
5     ("aarch64", &[("ANDROID_ABI", "arm64-v8a")]),
6     ("arm", &[("ANDROID_ABI", "armeabi-v7a")]),
7     ("x86", &[("ANDROID_ABI", "x86")]),
8     ("x86_64", &[("ANDROID_ABI", "x86_64")]),
9 ];
10 
11 // iOS.
12 const CMAKE_PARAMS_IOS: &[(&str, &[(&str, &str)])] = &[
13     ("aarch64", &[
14         ("CMAKE_OSX_ARCHITECTURES", "arm64"),
15         ("CMAKE_OSX_SYSROOT", "iphoneos"),
16     ]),
17     ("x86_64", &[
18         ("CMAKE_OSX_ARCHITECTURES", "x86_64"),
19         ("CMAKE_OSX_SYSROOT", "iphonesimulator"),
20     ]),
21 ];
22 
23 // ARM Linux.
24 const CMAKE_PARAMS_ARM_LINUX: &[(&str, &[(&str, &str)])] = &[
25     ("aarch64", &[("CMAKE_SYSTEM_PROCESSOR", "aarch64")]),
26     ("arm", &[("CMAKE_SYSTEM_PROCESSOR", "arm")]),
27 ];
28 
29 /// Returns the platform-specific output path for lib.
30 ///
31 /// MSVC generator on Windows place static libs in a target sub-folder,
32 /// so adjust library location based on platform and build target.
33 /// See issue: https://github.com/alexcrichton/cmake-rs/issues/18
get_boringssl_platform_output_path() -> String34 fn get_boringssl_platform_output_path() -> String {
35     if cfg!(target_env = "msvc") {
36         // Code under this branch should match the logic in cmake-rs
37         let debug_env_var =
38             std::env::var("DEBUG").expect("DEBUG variable not defined in env");
39 
40         let deb_info = match &debug_env_var[..] {
41             "false" => false,
42             "true" => true,
43             unknown => panic!("Unknown DEBUG={} env var.", unknown),
44         };
45 
46         let opt_env_var = std::env::var("OPT_LEVEL")
47             .expect("OPT_LEVEL variable not defined in env");
48 
49         let subdir = match &opt_env_var[..] {
50             "0" => "Debug",
51             "1" | "2" | "3" =>
52                 if deb_info {
53                     "RelWithDebInfo"
54                 } else {
55                     "Release"
56                 },
57             "s" | "z" => "MinSizeRel",
58             unknown => panic!("Unknown OPT_LEVEL={} env var.", unknown),
59         };
60 
61         subdir.to_string()
62     } else {
63         "".to_string()
64     }
65 }
66 
67 /// Returns a new cmake::Config for building BoringSSL.
68 ///
69 /// It will add platform-specific parameters if needed.
get_boringssl_cmake_config() -> cmake::Config70 fn get_boringssl_cmake_config() -> cmake::Config {
71     let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
72     let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
73     let pwd = std::env::current_dir().unwrap();
74 
75     let mut boringssl_cmake = cmake::Config::new("deps/boringssl");
76 
77     // Add platform-specific parameters.
78     match os.as_ref() {
79         "android" => {
80             // We need ANDROID_NDK_HOME to be set properly.
81             let android_ndk_home = std::env::var("ANDROID_NDK_HOME")
82                 .expect("Please set ANDROID_NDK_HOME for Android build");
83             let android_ndk_home = std::path::Path::new(&android_ndk_home);
84             for (android_arch, params) in CMAKE_PARAMS_ANDROID_NDK {
85                 if *android_arch == arch {
86                     for (name, value) in *params {
87                         boringssl_cmake.define(name, value);
88                     }
89                 }
90             }
91             let toolchain_file =
92                 android_ndk_home.join("build/cmake/android.toolchain.cmake");
93             let toolchain_file = toolchain_file.to_str().unwrap();
94             boringssl_cmake.define("CMAKE_TOOLCHAIN_FILE", toolchain_file);
95 
96             // 21 is the minimum level tested. You can give higher value.
97             boringssl_cmake.define("ANDROID_NATIVE_API_LEVEL", "21");
98             boringssl_cmake.define("ANDROID_STL", "c++_shared");
99 
100             boringssl_cmake
101         },
102 
103         "ios" => {
104             for (ios_arch, params) in CMAKE_PARAMS_IOS {
105                 if *ios_arch == arch {
106                     for (name, value) in *params {
107                         boringssl_cmake.define(name, value);
108                     }
109                 }
110             }
111 
112             // Bitcode is always on.
113             let bitcode_cflag = "-fembed-bitcode";
114 
115             // Hack for Xcode 10.1.
116             let target_cflag = if arch == "x86_64" {
117                 "-target x86_64-apple-ios-simulator"
118             } else {
119                 ""
120             };
121 
122             let cflag = format!("{bitcode_cflag} {target_cflag}");
123 
124             boringssl_cmake.define("CMAKE_ASM_FLAGS", &cflag);
125             boringssl_cmake.cflag(&cflag);
126 
127             boringssl_cmake
128         },
129 
130         "linux" => match arch.as_ref() {
131             "aarch64" | "arm" => {
132                 for (arm_arch, params) in CMAKE_PARAMS_ARM_LINUX {
133                     if *arm_arch == arch {
134                         for (name, value) in *params {
135                             boringssl_cmake.define(name, value);
136                         }
137                     }
138                 }
139                 boringssl_cmake.define("CMAKE_SYSTEM_NAME", "Linux");
140                 boringssl_cmake.define("CMAKE_SYSTEM_VERSION", "1");
141 
142                 boringssl_cmake
143             },
144 
145             "x86" => {
146                 boringssl_cmake.define(
147                     "CMAKE_TOOLCHAIN_FILE",
148                     pwd.join("deps/boringssl/src/util/32-bit-toolchain.cmake")
149                         .as_os_str(),
150                 );
151 
152                 boringssl_cmake
153             },
154 
155             _ => boringssl_cmake,
156         },
157 
158         _ => {
159             // Configure BoringSSL for building on 32-bit non-windows platforms.
160             if arch == "x86" && os != "windows" {
161                 boringssl_cmake.define(
162                     "CMAKE_TOOLCHAIN_FILE",
163                     pwd.join("deps/boringssl/src/util/32-bit-toolchain.cmake")
164                         .as_os_str(),
165                 );
166             }
167 
168             boringssl_cmake
169         },
170     }
171 }
172 
write_pkg_config()173 fn write_pkg_config() {
174     use std::io::prelude::*;
175 
176     let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
177     let target_dir = target_dir_path();
178 
179     let out_path = target_dir.as_path().join("quiche.pc");
180     let mut out_file = std::fs::File::create(out_path).unwrap();
181 
182     let include_dir = format!("{manifest_dir}/include");
183 
184     let version = std::env::var("CARGO_PKG_VERSION").unwrap();
185 
186     let output = format!(
187         "# quiche
188 
189 includedir={include_dir}
190 libdir={}
191 
192 Name: quiche
193 Description: quiche library
194 URL: https://github.com/cloudflare/quiche
195 Version: {version}
196 Libs: -Wl,-rpath,${{libdir}} -L${{libdir}} -lquiche
197 Cflags: -I${{includedir}}
198 ",
199         target_dir.to_str().unwrap(),
200     );
201 
202     out_file.write_all(output.as_bytes()).unwrap();
203 }
204 
target_dir_path() -> std::path::PathBuf205 fn target_dir_path() -> std::path::PathBuf {
206     let out_dir = std::env::var("OUT_DIR").unwrap();
207     let out_dir = std::path::Path::new(&out_dir);
208 
209     for p in out_dir.ancestors() {
210         if p.ends_with("build") {
211             return p.parent().unwrap().to_path_buf();
212         }
213     }
214 
215     unreachable!();
216 }
217 
main()218 fn main() {
219     if cfg!(feature = "boringssl-vendored") &&
220         !cfg!(feature = "boringssl-boring-crate")
221     {
222         let bssl_dir = std::env::var("QUICHE_BSSL_PATH").unwrap_or_else(|_| {
223             let mut cfg = get_boringssl_cmake_config();
224 
225             if cfg!(feature = "fuzzing") {
226                 cfg.cxxflag("-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE")
227                     .cxxflag("-DBORINGSSL_UNSAFE_FUZZER_MODE");
228             }
229 
230             cfg.build_target("ssl").build();
231             cfg.build_target("crypto").build().display().to_string()
232         });
233 
234         let build_path = get_boringssl_platform_output_path();
235         let mut build_dir = format!("{bssl_dir}/build/{build_path}");
236 
237         // If build directory doesn't exist, use the specified path as is.
238         if !std::path::Path::new(&build_dir).is_dir() {
239             build_dir = bssl_dir;
240         }
241 
242         println!("cargo:rustc-link-search=native={build_dir}");
243 
244         let bssl_link_kind = std::env::var("QUICHE_BSSL_LINK_KIND")
245             .unwrap_or("static".to_string());
246         println!("cargo:rustc-link-lib={bssl_link_kind}=ssl");
247         println!("cargo:rustc-link-lib={bssl_link_kind}=crypto");
248     }
249 
250     if cfg!(feature = "boringssl-boring-crate") {
251         println!("cargo:rustc-link-lib=static=ssl");
252         println!("cargo:rustc-link-lib=static=crypto");
253     }
254 
255     // MacOS: Allow cdylib to link with undefined symbols
256     let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
257     if target_os == "macos" {
258         println!("cargo:rustc-cdylib-link-arg=-Wl,-undefined,dynamic_lookup");
259     }
260 
261     if cfg!(feature = "pkg-config-meta") {
262         write_pkg_config();
263     }
264 }
265