]> git.proxmox.com Git - rustc.git/blob - src/liblibc/libc-test/build.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / liblibc / libc-test / build.rs
1 #![deny(warnings)]
2
3 extern crate ctest;
4
5 use std::env;
6
7 fn main() {
8 let target = env::var("TARGET").unwrap();
9 let windows = target.contains("windows");
10 let mingw = target.contains("windows-gnu");
11 let linux = target.contains("unknown-linux");
12 let android = target.contains("android");
13 let apple = target.contains("apple");
14 let musl = target.contains("musl");
15 let freebsd = target.contains("freebsd");
16 let bsdlike = freebsd || apple;
17 let mut cfg = ctest::TestGenerator::new();
18
19 // Pull in extra goodies on linux/mingw
20 if target.contains("unknown-linux") {
21 cfg.define("_GNU_SOURCE", None);
22 } else if windows {
23 cfg.define("_WIN32_WINNT", Some("0x8000"));
24 }
25
26 // Android doesn't actually have in_port_t but it's much easier if we
27 // provide one for us to test against
28 if android {
29 cfg.define("in_port_t", Some("uint16_t"));
30 }
31
32 cfg.header("errno.h")
33 .header("fcntl.h")
34 .header("limits.h")
35 .header("stddef.h")
36 .header("stdint.h")
37 .header("stdio.h")
38 .header("stdlib.h")
39 .header("sys/stat.h")
40 .header("sys/types.h")
41 .header("time.h")
42 .header("wchar.h");
43
44 if windows {
45 cfg.header("winsock2.h"); // must be before windows.h
46
47 cfg.header("direct.h");
48 cfg.header("io.h");
49 cfg.header("sys/utime.h");
50 cfg.header("windows.h");
51 cfg.header("process.h");
52 cfg.header("ws2ipdef.h");
53
54 if target.contains("gnu") {
55 cfg.header("ws2tcpip.h");
56 }
57 } else {
58 cfg.header("ctype.h");
59 cfg.header("dirent.h");
60 cfg.header("net/if.h");
61 cfg.header("netdb.h");
62 cfg.header("netinet/in.h");
63 cfg.header("netinet/ip.h");
64 cfg.header("netinet/tcp.h");
65 cfg.header("pthread.h");
66 cfg.header("dlfcn.h");
67 cfg.header("signal.h");
68 cfg.header("string.h");
69 cfg.header("sys/file.h");
70 cfg.header("sys/ioctl.h");
71 cfg.header("sys/mman.h");
72 cfg.header("sys/resource.h");
73 cfg.header("sys/socket.h");
74 cfg.header("sys/time.h");
75 cfg.header("sys/un.h");
76 cfg.header("sys/wait.h");
77 cfg.header("unistd.h");
78 cfg.header("utime.h");
79 cfg.header("pwd.h");
80 cfg.header("grp.h");
81 }
82
83 if android {
84 cfg.header("arpa/inet.h");
85 cfg.header("time64.h");
86 } else if !windows {
87 cfg.header("glob.h");
88 cfg.header("ifaddrs.h");
89 cfg.header("sys/statvfs.h");
90
91 if !musl {
92 cfg.header("execinfo.h");
93 cfg.header("sys/sysctl.h");
94 }
95 }
96
97 if apple {
98 cfg.header("mach-o/dyld.h");
99 cfg.header("mach/mach_time.h");
100 cfg.header("malloc/malloc.h");
101 if target.starts_with("x86") {
102 cfg.header("crt_externs.h");
103 }
104 }
105
106 if linux || android {
107 cfg.header("netpacket/packet.h");
108 cfg.header("net/ethernet.h");
109 cfg.header("malloc.h");
110 cfg.header("sys/prctl.h");
111 /* linux kernel header */
112 if !musl {
113 cfg.header("linux/netlink.h");
114 }
115 }
116
117 if freebsd {
118 cfg.header("pthread_np.h");
119 }
120
121 cfg.type_name(move |ty, is_struct| {
122 match ty {
123 // Just pass all these through, no need for a "struct" prefix
124 "FILE" |
125 "fd_set" |
126 "Dl_info" |
127 "DIR" => ty.to_string(),
128
129 // Fixup a few types on windows that don't actually exist.
130 "time64_t" if windows => "__time64_t".to_string(),
131 "ssize_t" if windows => "SSIZE_T".to_string(),
132
133 // OSX calls this something else
134 "sighandler_t" if bsdlike => "sig_t".to_string(),
135
136 t if t.ends_with("_t") => t.to_string(),
137
138 // Windows uppercase structs don't have `struct` in front, there's a
139 // few special cases for windows, and then otherwise put `struct` in
140 // front of everything.
141 t if is_struct => {
142 if windows && ty.chars().next().unwrap().is_uppercase() {
143 t.to_string()
144 } else if windows && t == "stat" {
145 "struct __stat64".to_string()
146 } else if windows && t == "utimbuf" {
147 "struct __utimbuf64".to_string()
148 } else {
149 format!("struct {}", t)
150 }
151 }
152
153 t => t.to_string(),
154 }
155 });
156
157 let target2 = target.clone();
158 cfg.field_name(move |struct_, field| {
159 match field {
160 // Our stat *_nsec fields normally don't actually exist but are part
161 // of a timeval struct
162 s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
163 if target2.contains("apple") {
164 s.replace("_nsec", "spec.tv_nsec")
165 } else if target2.contains("android") {
166 s.to_string()
167 } else {
168 s.replace("e_nsec", ".tv_nsec")
169 }
170 }
171 s => s.to_string(),
172 }
173 });
174
175 cfg.skip_type(move |ty| {
176 match ty {
177 // sighandler_t is crazy across platforms
178 "sighandler_t" => true,
179
180 _ => false
181 }
182 });
183
184 cfg.skip_struct(move |ty| {
185 match ty {
186 "sockaddr_nl" => musl,
187 _ => false
188 }
189 });
190
191 cfg.skip_signededness(|c| {
192 match c {
193 "LARGE_INTEGER" |
194 "mach_timebase_info_data_t" |
195 "float" |
196 "double" => true,
197 n if n.starts_with("pthread") => true,
198
199 // windows-isms
200 n if n.starts_with("P") => true,
201 n if n.starts_with("H") => true,
202 n if n.starts_with("LP") => true,
203 _ => false,
204 }
205 });
206
207 cfg.skip_const(move |name| {
208 match name {
209 // Apparently these don't exist in mingw headers?
210 "MEM_RESET_UNDO" |
211 "FILE_ATTRIBUTE_NO_SCRUB_DATA" |
212 "FILE_ATTRIBUTE_INTEGRITY_STREAM" |
213 "ERROR_NOTHING_TO_TERMINATE" if mingw => true,
214
215 "SIG_IGN" => true, // sighandler_t weirdness
216
217 // types on musl are defined a little differently
218 n if musl && n.contains("__SIZEOF_PTHREAD") => true,
219
220 // Skip constants not defined in MUSL but just passed down to the
221 // kernel regardless
222 "RLIMIT_NLIMITS" |
223 "TCP_COOKIE_TRANSACTIONS" |
224 "RLIMIT_RTTIME" if musl => true,
225
226 _ => false,
227 }
228 });
229
230 cfg.skip_fn(move |name| {
231 // skip those that are manually verifiedmanually verified
232 match name {
233 "execv" | // crazy stuff with const/mut
234 "execve" |
235 "execvp" |
236 "execvpe" => true,
237
238 "getrlimit" | "getrlimit64" | // non-int in 1st arg
239 "setrlimit" | "setrlimit64" | // non-int in 1st arg
240 "strerror_r" if linux => true, // actually xpg-something-or-other
241
242 // typed 2nd arg on linux and android
243 "gettimeofday" if linux || android || freebsd => true,
244
245 "dlerror" if android => true, // const-ness is added
246 "dladdr" if musl => true, // const-ness only added recently
247
248 // OSX has 'struct tm *const' which we can't actually represent in
249 // Rust, but is close enough to *mut
250 "timegm" if apple => true,
251
252 _ => false,
253 }
254 });
255
256 // Windows dllimport oddness?
257 cfg.skip_fn_ptrcheck(move |_| windows);
258
259 cfg.skip_field_type(move |struct_, field| {
260 // This is a weird union, don't check the type.
261 (struct_ == "ifaddrs" && field == "ifa_ifu") ||
262 // sighandler_t type is super weird
263 (struct_ == "sigaction" && field == "sa_sigaction")
264 });
265
266 cfg.skip_field(move |struct_, field| {
267 // this is actually a union on linux, so we can't represent it well and
268 // just insert some padding.
269 (struct_ == "siginfo_t" && field == "_pad") ||
270 // musl names this __dummy1 but it's still there
271 (musl && struct_ == "glob_t" && field == "gl_flags")
272 });
273
274 cfg.generate("../src/lib.rs", "all.rs");
275 }