]> git.proxmox.com Git - rustc.git/blame - vendor/openssl-sys/build/find_normal.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / openssl-sys / build / find_normal.rs
CommitLineData
0a29b90c
FG
1use std::ffi::OsString;
2use std::path::{Path, PathBuf};
3use std::process::{self, Command};
4
5use super::env;
6
7pub fn get_openssl(target: &str) -> (Vec<PathBuf>, PathBuf) {
8 let lib_dir = env("OPENSSL_LIB_DIR").map(PathBuf::from);
9 let include_dir = env("OPENSSL_INCLUDE_DIR").map(PathBuf::from);
10
11 match (lib_dir, include_dir) {
12 (Some(lib_dir), Some(include_dir)) => (vec![lib_dir], include_dir),
13 (lib_dir, include_dir) => {
14 let openssl_dir = env("OPENSSL_DIR").unwrap_or_else(|| find_openssl_dir(target));
15 let openssl_dir = Path::new(&openssl_dir);
16 let lib_dir = lib_dir.map(|d| vec![d]).unwrap_or_else(|| {
17 let mut lib_dirs = vec![];
18 // OpenSSL 3.0 now puts it's libraries in lib64/ by default,
19 // check for both it and lib/.
20 if openssl_dir.join("lib64").exists() {
21 lib_dirs.push(openssl_dir.join("lib64"));
22 }
23 if openssl_dir.join("lib").exists() {
24 lib_dirs.push(openssl_dir.join("lib"));
25 }
26 lib_dirs
27 });
28 let include_dir = include_dir.unwrap_or_else(|| openssl_dir.join("include"));
29 (lib_dir, include_dir)
30 }
31 }
32}
33
34fn resolve_with_wellknown_homebrew_location(dir: &str) -> Option<PathBuf> {
35 let versions = ["openssl@3", "openssl@1.1"];
36
37 // Check up default aarch 64 Homebrew installation location first
38 // for quick resolution if possible.
39 // `pkg-config` on brew doesn't necessarily contain settings for openssl apparently.
40 for version in &versions {
41 let homebrew = Path::new(dir).join(format!("opt/{}", version));
42 if homebrew.exists() {
43 return Some(homebrew);
44 }
45 }
46
47 for version in &versions {
48 // Calling `brew --prefix <package>` command usually slow and
49 // takes seconds, and will be used only as a last resort.
50 let output = execute_command_and_get_output("brew", &["--prefix", version]);
51 if let Some(ref output) = output {
52 let homebrew = Path::new(&output);
53 if homebrew.exists() {
54 return Some(homebrew.to_path_buf());
55 }
56 }
57 }
58
59 None
60}
61
62fn resolve_with_wellknown_location(dir: &str) -> Option<PathBuf> {
63 let root_dir = Path::new(dir);
64 let include_openssl = root_dir.join("include/openssl");
65 if include_openssl.exists() {
66 Some(root_dir.to_path_buf())
67 } else {
68 None
69 }
70}
71
72fn find_openssl_dir(target: &str) -> OsString {
73 let host = env::var("HOST").unwrap();
74
75 if host == target && target.ends_with("-apple-darwin") {
76 let homebrew_dir = match target {
77 "aarch64-apple-darwin" => "/opt/homebrew",
78 _ => "/usr/local",
79 };
80
81 if let Some(dir) = resolve_with_wellknown_homebrew_location(homebrew_dir) {
82 return dir.into();
83 } else if let Some(dir) = resolve_with_wellknown_location("/opt/pkg") {
84 // pkgsrc
85 return dir.into();
86 } else if let Some(dir) = resolve_with_wellknown_location("/opt/local") {
87 // MacPorts
88 return dir.into();
89 }
90 }
91
92 try_pkg_config();
93 try_vcpkg();
94
781aab86
FG
95 // FreeBSD and OpenBSD ship with Libre|OpenSSL but don't include a pkg-config file
96 if host == target && (target.contains("freebsd") || target.contains("openbsd")) {
0a29b90c
FG
97 return OsString::from("/usr");
98 }
99
100 // DragonFly has libressl (or openssl) in ports, but this doesn't include a pkg-config file
101 if host == target && target.contains("dragonfly") {
102 return OsString::from("/usr/local");
103 }
104
105 let mut msg = format!(
106 "
107
108Could not find directory of OpenSSL installation, and this `-sys` crate cannot
109proceed without this knowledge. If OpenSSL is installed and this crate had
110trouble finding it, you can set the `OPENSSL_DIR` environment variable for the
111compilation process.
112
113Make sure you also have the development packages of openssl installed.
114For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.
115
116If you're in a situation where you think the directory *should* be found
117automatically, please open a bug at https://github.com/sfackler/rust-openssl
118and include information about your system as well as this message.
119
120$HOST = {}
121$TARGET = {}
122openssl-sys = {}
123
124",
125 host,
126 target,
127 env!("CARGO_PKG_VERSION")
128 );
129
130 if host.contains("apple-darwin") && target.contains("apple-darwin") {
131 let system = Path::new("/usr/lib/libssl.0.9.8.dylib");
132 if system.exists() {
133 msg.push_str(
134 "
135
136openssl-sys crate build failed: no supported version of OpenSSL found.
137
138Ways to fix it:
139- Use the `vendored` feature of openssl-sys crate to build OpenSSL from source.
140- Use Homebrew to install the `openssl` package.
141
142",
143 );
144 }
145 }
146
147 if host.contains("unknown-linux")
148 && target.contains("unknown-linux-gnu")
149 && Command::new("pkg-config").output().is_err()
150 {
151 msg.push_str(
152 "
153It looks like you're compiling on Linux and also targeting Linux. Currently this
154requires the `pkg-config` utility to find OpenSSL but unfortunately `pkg-config`
155could not be found. If you have OpenSSL installed you can likely fix this by
156installing `pkg-config`.
157
158",
159 );
160 }
161
162 if host.contains("windows") && target.contains("windows-gnu") {
163 msg.push_str(
164 "
165It looks like you're compiling for MinGW but you may not have either OpenSSL or
166pkg-config installed. You can install these two dependencies with:
167
168pacman -S openssl-devel pkg-config
169
170and try building this crate again.
171
172",
173 );
174 }
175
176 if host.contains("windows") && target.contains("windows-msvc") {
177 msg.push_str(
178 "
179It looks like you're compiling for MSVC but we couldn't detect an OpenSSL
180installation. If there isn't one installed then you can try the rust-openssl
181README for more information about how to download precompiled binaries of
182OpenSSL:
183
184https://github.com/sfackler/rust-openssl#windows
185
186",
187 );
188 }
189
190 panic!("{}", msg);
191}
192
193/// Attempt to find OpenSSL through pkg-config.
194///
195/// Note that if this succeeds then the function does not return as pkg-config
196/// typically tells us all the information that we need.
197fn try_pkg_config() {
198 let target = env::var("TARGET").unwrap();
199 let host = env::var("HOST").unwrap();
200
781aab86 201 // FIXME we really shouldn't be automatically enabling this
0a29b90c
FG
202 if target.contains("windows-gnu") && host.contains("windows") {
203 env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");
781aab86
FG
204 } else if target.contains("windows-msvc") {
205 // MSVC targets use vcpkg instead.
0a29b90c
FG
206 return;
207 }
208
209 let lib = match pkg_config::Config::new()
210 .print_system_libs(false)
211 .probe("openssl")
212 {
213 Ok(lib) => lib,
214 Err(e) => {
215 println!("run pkg_config fail: {:?}", e);
216 return;
217 }
218 };
219
220 super::postprocess(&lib.include_paths);
221
222 for include in lib.include_paths.iter() {
223 println!("cargo:include={}", include.display());
224 }
225
226 process::exit(0);
227}
228
229/// Attempt to find OpenSSL through vcpkg.
230///
231/// Note that if this succeeds then the function does not return as vcpkg
232/// should emit all of the cargo metadata that we need.
0a29b90c 233fn try_vcpkg() {
781aab86
FG
234 let target = env::var("TARGET").unwrap();
235 if !target.contains("windows") {
236 return;
237 }
238
0a29b90c
FG
239 // vcpkg will not emit any metadata if it can not find libraries
240 // appropriate for the target triple with the desired linkage.
241
242 let lib = match vcpkg::Config::new()
243 .emit_includes(true)
244 .find_package("openssl")
245 {
246 Ok(lib) => lib,
247 Err(e) => {
248 println!("note: vcpkg did not find openssl: {}", e);
249 return;
250 }
251 };
252
253 super::postprocess(&lib.include_paths);
254
255 println!("cargo:rustc-link-lib=user32");
256 println!("cargo:rustc-link-lib=gdi32");
257 println!("cargo:rustc-link-lib=crypt32");
258
259 process::exit(0);
260}
261
0a29b90c
FG
262fn execute_command_and_get_output(cmd: &str, args: &[&str]) -> Option<String> {
263 let out = Command::new(cmd).args(args).output();
264 if let Ok(ref r1) = out {
265 if r1.status.success() {
266 let r2 = String::from_utf8(r1.stdout.clone());
267 if let Ok(r3) = r2 {
268 return Some(r3.trim().to_string());
269 }
270 }
271 }
272
273 None
274}