blob: 7bfa8720a6dabd499bcfadf1aef2b85113cff0fd [file] [log] [blame]
Alex Crichton8e5f0cd2015-09-09 22:46:19 -07001#![allow(unused_must_use)]
2
3extern crate gcc;
4extern crate syntex_syntax as syntax;
5
6use std::env;
7use std::fs::File;
8use std::io::BufWriter;
9use std::io::prelude::*;
10use std::path::{Path, PathBuf};
11
12use syntax::ast;
13use syntax::parse::token::InternedString;
14use syntax::attr;
15use syntax::parse::{self, ParseSess};
16use syntax::visit::{self, Visitor};
17
18struct TestGenerator {
19 rust: Box<Write>,
20 c: Box<Write>,
21}
22
23fn main() {
Alex Crichton16083062015-09-09 22:59:24 -070024 let target = env::var("TARGET").unwrap();
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070025
Alex Crichton16083062015-09-09 22:59:24 -070026 let sess = ParseSess::new();
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070027 let src = Path::new("../src/lib.rs");
28 let cfg = Vec::new();
29 let mut krate = parse::parse_crate_from_file(src, cfg, &sess);
Alex Crichton16083062015-09-09 22:59:24 -070030 build_cfg(&mut krate.config, &target);
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070031
32 let mut gated_cfgs = Vec::new();
33 let krate = syntax::config::strip_unconfigured_items(&sess.span_diagnostic,
34 krate,
35 &mut gated_cfgs);
36
37 let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
38 let rust_out = BufWriter::new(File::create(out.join("all.rs")).unwrap());
39 let mut c_out = BufWriter::new(File::create(out.join("all.c")).unwrap());
40
41 writeln!(c_out, "
42#include <netinet/in.h>
43#include <netinet/ip.h>
44#include <signal.h>
Alex Crichton16083062015-09-09 22:59:24 -070045#include <stdalign.h>
46#include <stddef.h>
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070047#include <stdint.h>
Alex Crichton16083062015-09-09 22:59:24 -070048#include <sys/resource.h>
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070049#include <sys/types.h>
50#include <time.h>
Alex Crichton16083062015-09-09 22:59:24 -070051#include <wchar.h>
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070052");
53
Alex Crichton16083062015-09-09 22:59:24 -070054 if target.contains("apple-darwin") {
55 writeln!(c_out, "
56#include <mach/mach_time.h>
57");
58 }
59
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070060 visit::walk_crate(&mut TestGenerator {
61 rust: Box::new(rust_out),
62 c: Box::new(c_out),
63 }, &krate);
64
65 gcc::Config::new()
66 .file(out.join("all.c"))
67 .compile("liball.a");
68}
69
Alex Crichton16083062015-09-09 22:59:24 -070070fn build_cfg(cfg: &mut ast::CrateConfig, target: &str) {
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070071 let (arch, target_pointer_width) = if target.starts_with("x86_64") {
72 ("x86_64", "64")
73 } else if target.starts_with("i686") {
74 ("x86", "32")
75 } else {
76 panic!("unknown arch/pointer width: {}", target)
77 };
78 let (os, family, env) = if target.contains("unknown-linux") {
79 ("linux", "unix", "gnu")
Alex Crichton16083062015-09-09 22:59:24 -070080 } else if target.contains("apple-darwin") {
81 ("macos", "unix", "")
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070082 } else {
83 panic!("unknown os/family width: {}", target)
84 };
85
86 let mk = attr::mk_name_value_item_str;
87 let s = InternedString::new;
88 cfg.push(attr::mk_word_item(s(family)));
89 cfg.push(mk(s("target_os"), s(os)));
90 cfg.push(mk(s("target_family"), s(family)));
91 cfg.push(mk(s("target_arch"), s(arch)));
92 // skip endianness
93 cfg.push(mk(s("target_pointer_width"), s(target_pointer_width)));
94 cfg.push(mk(s("target_env"), s(env)));
95}
96
97impl TestGenerator {
98 fn typedef(&mut self, ty: &str) {
99 let cty = if ty.starts_with("c_") {
100 let rest = ty[2..].replace("long", " long");
101 if rest.starts_with("u") {
102 format!("unsigned {}", &rest[1..])
Alex Crichton16083062015-09-09 22:59:24 -0700103 } else if rest.starts_with("s") && rest != "short" {
104 format!("signed {}", &rest[1..])
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700105 } else {
106 rest
107 }
108 } else {
109 (match ty {
Alex Crichton16083062015-09-09 22:59:24 -0700110 "sighandler_t" => return,
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700111 ty => ty,
112 }).to_string()
113 };
Alex Crichton16083062015-09-09 22:59:24 -0700114
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700115 writeln!(self.c, r#"
Alex Crichton16083062015-09-09 22:59:24 -0700116 uint64_t ty_{ty}_size() {{ return sizeof({cty}); }}
117 uint64_t ty_{ty}_align() {{ return alignof({cty}); }}
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700118 "#, ty = ty, cty = cty);
119 writeln!(self.rust, r#"
120 #[test]
Alex Crichton16083062015-09-09 22:59:24 -0700121 fn sanity_{ty}() {{
122 extern {{
123 fn ty_{ty}_size() -> u64;
124 fn ty_{ty}_align() -> u64;
125 }}
126 unsafe {{
127 assert_eq!(mem::size_of::<libc::{ty}>() as u64,
128 ty_{ty}_size());
129 assert_eq!(mem::align_of::<libc::{ty}>() as u64,
130 ty_{ty}_align());
131 }}
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700132 }}
133 "#, ty = ty);
134 }
135}
136
137impl<'v> Visitor<'v> for TestGenerator {
138 fn visit_item(&mut self, i: &'v ast::Item) {
139 match i.node {
140 ast::ItemTy(_, ref generics) => {
141 assert!(generics.lifetimes.len() == 0);
142 assert!(generics.ty_params.len() == 0);
143 assert!(generics.where_clause.predicates.len() == 0);
144 self.typedef(&i.ident.to_string());
145 }
146
147 _ => {}
148 }
149 visit::walk_item(self, i)
150 }
151}