blob: fa9e4073e2e936a9ea5049062acbeab9efb7e885 [file] [log] [blame]
David Tolnayb4dba232020-05-11 00:55:29 -07001// Functionality that is shared between the cxx_build::bridge entry point and
2// the cxxbridge CLI command.
David Tolnay7db73692019-10-20 14:51:12 -04003
4mod error;
David Tolnayfcd8f462020-08-29 12:13:09 -07005mod file;
David Tolnay7db73692019-10-20 14:51:12 -04006pub(super) mod include;
7pub(super) mod out;
8mod write;
9
David Tolnay0d47a532020-07-30 19:39:04 -070010#[cfg(test)]
11mod tests;
12
David Tolnay52509842020-04-25 19:38:59 -070013use self::error::{format_err, Error, Result};
David Tolnayfcd8f462020-08-29 12:13:09 -070014use self::file::File;
David Tolnay0dd85ff2020-05-03 23:43:33 -070015use crate::syntax::report::Errors;
David Tolnayb6cf3142020-04-19 20:56:09 -070016use crate::syntax::{self, check, Types};
David Tolnay7db73692019-10-20 14:51:12 -040017use std::fs;
David Tolnay7db73692019-10-20 14:51:12 -040018use std::path::Path;
David Tolnay7db73692019-10-20 14:51:12 -040019
David Tolnay33d30292020-03-18 18:02:02 -070020#[derive(Default)]
21pub(super) struct Opt {
22 /// Any additional headers to #include
23 pub include: Vec<String>,
Adrian Taylor21f0ff02020-07-21 16:21:48 -070024 /// Whether to set __attribute__((visibility("default")))
25 /// or similar annotations on function implementations.
26 pub cxx_impl_annotations: Option<String>,
David Tolnay33d30292020-03-18 18:02:02 -070027}
28
David Tolnay7ece56f2020-03-29 21:21:38 -070029pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
David Tolnay7db73692019-10-20 14:51:12 -040030 let header = false;
Adrian Taylor8205e622020-07-21 21:53:59 -070031 generate_from_path(path, opt, header)
David Tolnay7db73692019-10-20 14:51:12 -040032}
33
David Tolnay7ece56f2020-03-29 21:21:38 -070034pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
David Tolnay7db73692019-10-20 14:51:12 -040035 let header = true;
Adrian Taylor8205e622020-07-21 21:53:59 -070036 generate_from_path(path, opt, header)
David Tolnay7db73692019-10-20 14:51:12 -040037}
38
Adrian Taylor8205e622020-07-21 21:53:59 -070039fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
David Tolnay7db73692019-10-20 14:51:12 -040040 let source = match fs::read_to_string(path) {
41 Ok(source) => source,
42 Err(err) => format_err(path, "", Error::Io(err)),
43 };
David Tolnay17c32302020-08-29 12:21:16 -070044 let mut source = source.as_str();
45 if source.starts_with("#!") && !source.starts_with("#![") {
46 let shebang_end = source.find('\n').unwrap_or(source.len());
47 source = &source[shebang_end..];
48 }
49 match generate(source, opt, header) {
Adrian Taylor8205e622020-07-21 21:53:59 -070050 Ok(out) => out,
David Tolnay17c32302020-08-29 12:21:16 -070051 Err(err) => format_err(path, source, err),
David Tolnay7db73692019-10-20 14:51:12 -040052 }
53}
Adrian Taylor8205e622020-07-21 21:53:59 -070054
55fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
56 proc_macro2::fallback::force();
57 let ref mut errors = Errors::new();
David Tolnayfcd8f462020-08-29 12:13:09 -070058 let syntax: File = syn::parse_str(source)?;
David Tolnay3c64a4e2020-08-29 14:07:38 -070059 let bridge = syntax
60 .modules
61 .into_iter()
62 .next()
63 .ok_or(Error::NoBridgeMod)?;
Adrian Taylor8205e622020-07-21 21:53:59 -070064 let ref namespace = bridge.namespace;
David Tolnay3c64a4e2020-08-29 14:07:38 -070065 let ref apis = syntax::parse_items(errors, bridge.content);
Adrian Taylor8205e622020-07-21 21:53:59 -070066 let ref types = Types::collect(errors, apis);
67 errors.propagate()?;
68 check::typecheck(errors, namespace, apis, types);
69 errors.propagate()?;
70 let out = write::gen(namespace, apis, types, opt, header);
71 Ok(out.content())
72}