Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 1 | #![allow(unused_must_use)] |
| 2 | |
| 3 | extern crate gcc; |
| 4 | extern crate syntex_syntax as syntax; |
| 5 | |
| 6 | use std::env; |
| 7 | use std::fs::File; |
| 8 | use std::io::BufWriter; |
| 9 | use std::io::prelude::*; |
| 10 | use std::path::{Path, PathBuf}; |
| 11 | |
| 12 | use syntax::ast; |
| 13 | use syntax::parse::token::InternedString; |
| 14 | use syntax::attr; |
| 15 | use syntax::parse::{self, ParseSess}; |
| 16 | use syntax::visit::{self, Visitor}; |
| 17 | |
| 18 | struct TestGenerator { |
| 19 | rust: Box<Write>, |
| 20 | c: Box<Write>, |
| 21 | } |
| 22 | |
| 23 | fn main() { |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 24 | let target = env::var("TARGET").unwrap(); |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 25 | |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 26 | let sess = ParseSess::new(); |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 27 | 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 Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 30 | build_cfg(&mut krate.config, &target); |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 31 | |
| 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 Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 45 | #include <stdalign.h> |
| 46 | #include <stddef.h> |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 47 | #include <stdint.h> |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 48 | #include <sys/resource.h> |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 49 | #include <sys/types.h> |
| 50 | #include <time.h> |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 51 | #include <wchar.h> |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 52 | "); |
| 53 | |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 54 | if target.contains("apple-darwin") { |
| 55 | writeln!(c_out, " |
| 56 | #include <mach/mach_time.h> |
| 57 | "); |
| 58 | } |
| 59 | |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 60 | 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 Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 70 | fn build_cfg(cfg: &mut ast::CrateConfig, target: &str) { |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 71 | 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 Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 80 | } else if target.contains("apple-darwin") { |
| 81 | ("macos", "unix", "") |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 82 | } 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 | |
| 97 | impl 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 Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 103 | } else if rest.starts_with("s") && rest != "short" { |
| 104 | format!("signed {}", &rest[1..]) |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 105 | } else { |
| 106 | rest |
| 107 | } |
| 108 | } else { |
| 109 | (match ty { |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 110 | "sighandler_t" => return, |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 111 | ty => ty, |
| 112 | }).to_string() |
| 113 | }; |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 114 | |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 115 | writeln!(self.c, r#" |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 116 | uint64_t ty_{ty}_size() {{ return sizeof({cty}); }} |
| 117 | uint64_t ty_{ty}_align() {{ return alignof({cty}); }} |
Alex Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 118 | "#, ty = ty, cty = cty); |
| 119 | writeln!(self.rust, r#" |
| 120 | #[test] |
Alex Crichton | 1608306 | 2015-09-09 22:59:24 -0700 | [diff] [blame^] | 121 | 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 Crichton | 8e5f0cd | 2015-09-09 22:46:19 -0700 | [diff] [blame] | 132 | }} |
| 133 | "#, ty = ty); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | impl<'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 | } |