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