其实 OS X 从很早之前就不带 OpenSSL 一起玩了,推荐使用 Common Crypto 来做相关操作,但是有些时候还是需要 OpenSSL 来给咱自己玩的,之前是使用 Homebrew 安装的,但是 Homebrew 最近的一个 PR#597brew link --force openssl 也直接拒绝了:

$ brew link --force openssl
Warning: Refusing to link: openssl
Linking keg-only openssl means you may end up linking against the insecure,
deprecated system OpenSSL while using the headers from Homebrew's openssl.
Instead, pass the full include/library paths to your compiler e.g.:
  -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib

所以在某些依赖 OpenSSL 的地方会出现奇怪的问题,比如对于 rust 用户而言,在依赖 OpenSSL 的地方跑 cargo test 就有可能出现以下问题:

error: linking with `cc` failed: exit code: 1
note: "cc" "-m64" "-L" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib" "/Users/realityone/Documents/Softs/rust-openssl/openssl-sys/target/debug/openssl_sys-e8e481b77fe0209d.0.o" "-o" "/Users/realityone/Documents/Softs/rust-openssl/openssl-sys/target/debug/openssl_sys-e8e481b77fe0209d" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/realityone/Documents/Softs/rust-openssl/openssl-sys/target/debug" "-L" "/Users/realityone/Documents/Softs/rust-openssl/openssl-sys/target/debug/deps" "-L" "/usr/lib" "-L" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib" "-l" "ssl" "-l" "crypto" "-l" "z" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libtest-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libterm-39b92f95.rlib" "/Users/realityone/Documents/Softs/rust-openssl/openssl-sys/target/debug/deps/liblibc-1417726cb94dbc83.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libstd-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libunwind-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/librand-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libcollections-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/librustc_unicode-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/liballoc-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/liballoc_jemalloc-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/liblibc-39b92f95.rlib" "/usr/local/Cellar/rust/1.11.0/lib/rustlib/x86_64-apple-darwin/lib/libcore-39b92f95.rlib" "-l" "System" "-l" "pthread" "-l" "c" "-l" "m" "-l" "compiler-rt"
note: ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error
error: Could not compile `openssl-sys`.

因为 Homebrew 现在也不会把 OpenSSL ln 到默认的几个 lib 搜索目录下了。

于是咱又观察了下 openssl-sys 的编译方式,是使用了 cargo 的 build script,发现可以传递两个环境变量 OPENSSL_LIB_DIROPENSSL_INCLUDE_DIR,然后就可以测试成功了!

$ cargo clean
$ export OPENSSL_LIB_DIR=$(brew --prefix openssl)/lib
$ export OPENSSL_INCLUDE_DIR=$(brew --prefix openssl)/include
$ cargo build
$ cargo test

那以后使用还需不需要再加上这两个环境变量呢?其实是不需要了,但是如果 cargo clean 之后的话重新编译还是需要的,因为 openssl-sys 会把当时的值传递给 downstream,那样之后的程序也能找到正确的依赖了。

参考: