From ef20ddbc57c7e6593ecc48ab016b43792204c0cf Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 26 Apr 2017 22:39:52 -0400 Subject: [PATCH 1/8] Add binding for res_init. Some notes about the particularities of the changes: res_init has been deprecated in favor of res_ninit, and many (but not all) targets have therefore renamed the link name to __res_init. For example, this happened in glibc in version 2.2: https://bugzilla.redhat.com/show_bug.cgi?id=43822#c6 In these systems, res_init is #defined to __res_init in resolv.h, which lets existing C programs continue to be compiled. Unfortunately, this define doesn't automatically apply to our Rust code. We therefore need to manually map the link name of res_init as appropriate for each target: macOS and iOS use res_9_init: https://github.com/practicalswift/osx/blob/3908694d6328baa293f0d7fc337348c01d13ed8f/src/libresolv/resolv.h#L316 Solaris uses res_init: https://java.net/projects/solaris/sources/on-src/content/usr/src/head/resolv.h OpenBSD uses __res_init: https://github.com/openbsd/src/blob/f3b3b7c7ca9a921db3a5650eed40f2b2e4d731d8/include/resolv.h#L268 FreeBSD uses __res_init: https://github.com/freebsd/freebsd/blob/6911f4a88c9832e5985b788f5e84010424f9e020/include/resolv.h#L290 NetBSD uses __res_init: http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/include/resolv.h glibc uses __res_init: https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/resolv/resolv.h#L259 eglibc uses __res_init: https://github.com/Xilinx/eglibc/blob/7f0bcce417c47aefad06ddfec7cd4ced3a4e10ff/resolv/resolv.h#L259 musl uses res_init: https://github.com/runtimejs/musl-libc/blob/0a11d7cb13e243782da36e2e5747b8b151933cca/include/resolv.h#L128 Android uses res_init: https://github.com/android/platform_bionic/blob/306ea559528255e19a5bcd68cc2a9b1afc2cfb27/libc/include/resolv.h#L57 One caveat here is that NetBSD doesn't seem to use the symbol name __res_init yet, despite the redefine being present in resolv.h. At least Travis fails for the netbsd target if __res_init is used. This may change in the future. iOS and macOS both unfortunately require linking with libresolv, despite the symbols technically being available without libresolv: resolv: http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html Android and OpenBSD fall in the same category. --- libc-test/build.rs | 1 + src/unix/mod.rs | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 28ac5a51b97b4..cfee015be033b 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -77,6 +77,7 @@ fn main() { cfg.header("netinet/in.h"); cfg.header("netinet/ip.h"); cfg.header("netinet/tcp.h"); + cfg.header("resolv.h"); cfg.header("pthread.h"); cfg.header("dlfcn.h"); cfg.header("signal.h"); diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 7ebf0d9e0bac5..f83d8f2ca5d89 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -206,9 +206,22 @@ pub const PRIO_MAX: ::c_int = 20; cfg_if! { if #[cfg(dox)] { // on dox builds don't pull in anything - } else if #[cfg(all(not(stdbuild), feature = "use_std"))] { + } else if #[cfg(all(not(stdbuild), + feature = "use_std", + not(any(target_os = "macos", + target_os = "ios", + target_os = "android", + target_os = "openbsd", + target_os = "bitrig") + )))] { // cargo build, don't pull in anything extra as the libstd dep // already pulls in all libs. + } else if #[cfg(all(not(stdbuild), feature = "use_std"))] { + // except on macOS and iOS, where we must link with lib resolv + // for res_init, despite libsystem_info including it: + // http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html + #[link(name = "resolv")] + extern {} } else if #[cfg(any(all(target_env = "musl", not(target_arch = "mips"))))] { #[link(name = "c", kind = "static", cfg(target_feature = "crt-static"))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] @@ -229,6 +242,7 @@ cfg_if! { target_os = "bitrig"))] { #[link(name = "c")] #[link(name = "m")] + #[link(name = "resolv")] extern {} } else if #[cfg(target_os = "haiku")] { #[link(name = "root")] @@ -694,6 +708,17 @@ extern { res: *mut *mut addrinfo) -> ::c_int; pub fn freeaddrinfo(res: *mut addrinfo); pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char; + #[cfg_attr(all(unix, + not(target_os = "macos"), + not(target_os = "ios"), + not(target_os = "netbsd"), + not(target_os = "solaris"), + not(target_env = "musl") + ), + link_name = "__res_init")] + #[cfg_attr(any(target_os = "macos", target_os = "ios"), + link_name = "res_9_init")] + pub fn res_init() -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; From f93cf62d9a931a55879e7edf3793285cb5eaa3b2 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 28 Apr 2017 17:14:09 -0400 Subject: [PATCH 2/8] OpenBSD can't -lresolv, Android shouldn't need it --- src/unix/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index f83d8f2ca5d89..611171a2c10e1 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -210,8 +210,6 @@ cfg_if! { feature = "use_std", not(any(target_os = "macos", target_os = "ios", - target_os = "android", - target_os = "openbsd", target_os = "bitrig") )))] { // cargo build, don't pull in anything extra as the libstd dep @@ -237,13 +235,16 @@ cfg_if! { extern {} } else if #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "android", - target_os = "openbsd", target_os = "bitrig"))] { #[link(name = "c")] #[link(name = "m")] #[link(name = "resolv")] extern {} + } else if #[cfg(any(target_os = "android", + target_os = "openbsd"))] { + #[link(name = "c")] + #[link(name = "m")] + extern {} } else if #[cfg(target_os = "haiku")] { #[link(name = "root")] #[link(name = "network")] From afebd981318c61b45f35ad7792c7ea32e741ebcc Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 28 Apr 2017 22:23:33 -0400 Subject: [PATCH 3/8] Android doesn't expose res_init in header file --- libc-test/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index cfee015be033b..57767f55ea5a3 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -469,6 +469,10 @@ fn main() { // it's in a header file? "endpwent" if android => true, + // Apparently it exists, but isn't defined in a header: + // https://mail.gnome.org/archives/commits-list/2013-May/msg01329.html + "res_init" if android => true, + _ => false, } }); From b8f58386757a67442c580124990127dd4b1c376d Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 28 Apr 2017 22:23:58 -0400 Subject: [PATCH 4/8] OpenBSD also uses res_init like NetBSD? --- src/unix/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 611171a2c10e1..54b27150ecff8 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -713,6 +713,7 @@ extern { not(target_os = "macos"), not(target_os = "ios"), not(target_os = "netbsd"), + not(target_os = "openbsd"), not(target_os = "solaris"), not(target_env = "musl") ), From 6eb8d1c77cff490a1ec46394f7998d41450a0acc Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 28 Apr 2017 23:58:48 -0400 Subject: [PATCH 5/8] Treat bitrig and openbsd the same (@semarie) --- src/unix/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 54b27150ecff8..95fa075629662 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -209,8 +209,7 @@ cfg_if! { } else if #[cfg(all(not(stdbuild), feature = "use_std", not(any(target_os = "macos", - target_os = "ios", - target_os = "bitrig") + target_os = "ios") )))] { // cargo build, don't pull in anything extra as the libstd dep // already pulls in all libs. @@ -234,14 +233,14 @@ cfg_if! { #[link(name = "m")] extern {} } else if #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "bitrig"))] { + target_os = "ios"))] { #[link(name = "c")] #[link(name = "m")] #[link(name = "resolv")] extern {} } else if #[cfg(any(target_os = "android", - target_os = "openbsd"))] { + target_os = "openbsd", + target_os = "bitrig"))] { #[link(name = "c")] #[link(name = "m")] extern {} @@ -714,6 +713,7 @@ extern { not(target_os = "ios"), not(target_os = "netbsd"), not(target_os = "openbsd"), + not(target_os = "bitrig"), not(target_os = "solaris"), not(target_env = "musl") ), From b3700e4364181c58dd7f56f1d90fdb91b181f007 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 3 May 2017 13:41:00 -0400 Subject: [PATCH 6/8] Blacklist > whitelist --- src/unix/mod.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 95fa075629662..2ef85f1cd5ca7 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -708,15 +708,10 @@ extern { res: *mut *mut addrinfo) -> ::c_int; pub fn freeaddrinfo(res: *mut addrinfo); pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char; - #[cfg_attr(all(unix, - not(target_os = "macos"), - not(target_os = "ios"), - not(target_os = "netbsd"), - not(target_os = "openbsd"), - not(target_os = "bitrig"), - not(target_os = "solaris"), - not(target_env = "musl") - ), + #[cfg_attr(any( + all(target_os = "linux", not(target_env = "musl")), + target_os = "freebsd", + target_os = "dragonfly"), link_name = "__res_init")] #[cfg_attr(any(target_os = "macos", target_os = "ios"), link_name = "res_9_init")] From fcf5fc0257bb01e84aabfa0efd0d09638145d105 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 3 May 2017 15:17:24 -0400 Subject: [PATCH 7/8] Avoid special-casing linking with resolv --- src/unix/mod.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 2ef85f1cd5ca7..a235d6a422017 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -206,19 +206,9 @@ pub const PRIO_MAX: ::c_int = 20; cfg_if! { if #[cfg(dox)] { // on dox builds don't pull in anything - } else if #[cfg(all(not(stdbuild), - feature = "use_std", - not(any(target_os = "macos", - target_os = "ios") - )))] { + } else if #[cfg(all(not(stdbuild), feature = "use_std"))] { // cargo build, don't pull in anything extra as the libstd dep // already pulls in all libs. - } else if #[cfg(all(not(stdbuild), feature = "use_std"))] { - // except on macOS and iOS, where we must link with lib resolv - // for res_init, despite libsystem_info including it: - // http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html - #[link(name = "resolv")] - extern {} } else if #[cfg(any(all(target_env = "musl", not(target_arch = "mips"))))] { #[link(name = "c", kind = "static", cfg(target_feature = "crt-static"))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] @@ -233,12 +223,8 @@ cfg_if! { #[link(name = "m")] extern {} } else if #[cfg(any(target_os = "macos", - target_os = "ios"))] { - #[link(name = "c")] - #[link(name = "m")] - #[link(name = "resolv")] - extern {} - } else if #[cfg(any(target_os = "android", + target_os = "ios", + target_os = "android", target_os = "openbsd", target_os = "bitrig"))] { #[link(name = "c")] From be7e45f6f5f4fb372ebe8dfab7533500cf3e254c Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 3 May 2017 15:57:29 -0400 Subject: [PATCH 8/8] Skip res_init test on macOS/iOS --- libc-test/build.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 57767f55ea5a3..2f59a442af184 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -469,10 +469,16 @@ fn main() { // it's in a header file? "endpwent" if android => true, - // Apparently it exists, but isn't defined in a header: + // Apparently res_init exists on Android, but isn't defined in a header: // https://mail.gnome.org/archives/commits-list/2013-May/msg01329.html "res_init" if android => true, + // On macOS and iOS, res_init is available, but requires linking with libresolv: + // http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html + // See discussion for skipping here: + // https://github.com/rust-lang/libc/pull/585#discussion_r114561460 + "res_init" if apple => true, + _ => false, } });