mirror of
https://github.com/topjohnwu/cxx.git
synced 2025-02-24 18:12:14 +00:00
Use Opt to control which outputs get generated
This commit is contained in:
parent
318c3530b4
commit
8238d4a316
@ -103,16 +103,16 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
|
||||
|
||||
fn try_generate_bridge(build: &mut cc::Build, rust_source_file: &Path) -> Result<()> {
|
||||
let opt = Opt::default();
|
||||
let header = gen::do_generate_header(rust_source_file, &opt);
|
||||
let generated = gen::generate_from_path(rust_source_file, &opt);
|
||||
|
||||
let header_path = paths::out_with_extension(rust_source_file, ".h")?;
|
||||
fs::create_dir_all(header_path.parent().unwrap())?;
|
||||
fs::write(&header_path, header)?;
|
||||
fs::write(&header_path, generated.header)?;
|
||||
paths::symlink_header(&header_path, rust_source_file);
|
||||
|
||||
let bridge = gen::do_generate_bridge(rust_source_file, &opt);
|
||||
let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
|
||||
fs::write(&bridge_path, bridge)?;
|
||||
build.file(&bridge_path);
|
||||
let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
|
||||
fs::write(&implementation_path, generated.implementation)?;
|
||||
build.file(&implementation_path);
|
||||
|
||||
let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
|
||||
let _ = fs::create_dir_all(cxx_h.parent().unwrap());
|
||||
|
@ -32,11 +32,13 @@ fn main() {
|
||||
let gen = gen::Opt {
|
||||
include: opt.include,
|
||||
cxx_impl_annotations: opt.cxx_impl_annotations,
|
||||
gen_header: opt.header,
|
||||
gen_implementation: !opt.header,
|
||||
};
|
||||
|
||||
match (opt.input, opt.header) {
|
||||
(Some(input), true) => write(gen::do_generate_header(&input, &gen)),
|
||||
(Some(input), false) => write(gen::do_generate_bridge(&input, &gen)),
|
||||
(Some(input), true) => write(gen::generate_from_path(&input, &gen).header),
|
||||
(Some(input), false) => write(gen::generate_from_path(&input, &gen).implementation),
|
||||
(None, true) => write(include::HEADER),
|
||||
(None, false) => unreachable!(), // enforced by required_unless
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
|
||||
let syntax = syn::parse2(rust_source)
|
||||
.map_err(crate::gen::Error::from)
|
||||
.map_err(Error)?;
|
||||
gen::generate(syntax, opt, true, true).map_err(Error)
|
||||
gen::generate(syntax, opt).map_err(Error)
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
|
@ -44,6 +44,9 @@ pub struct Opt {
|
||||
/// Rust code from one shared object or executable depends on these C++
|
||||
/// functions in another.
|
||||
pub cxx_impl_annotations: Option<String>,
|
||||
|
||||
pub(super) gen_header: bool,
|
||||
pub(super) gen_implementation: bool,
|
||||
}
|
||||
|
||||
/// Results of code generation.
|
||||
@ -59,52 +62,34 @@ impl Default for Opt {
|
||||
Opt {
|
||||
include: Vec::new(),
|
||||
cxx_impl_annotations: None,
|
||||
gen_header: true,
|
||||
gen_implementation: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
|
||||
let header = false;
|
||||
generate_from_path(path, opt, header)
|
||||
}
|
||||
|
||||
pub(super) fn do_generate_header(path: &Path, opt: &Opt) -> Vec<u8> {
|
||||
let header = true;
|
||||
generate_from_path(path, opt, header)
|
||||
}
|
||||
|
||||
fn generate_from_path(path: &Path, opt: &Opt, header: bool) -> Vec<u8> {
|
||||
pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
|
||||
let source = match fs::read_to_string(path) {
|
||||
Ok(source) => source,
|
||||
Err(err) => format_err(path, "", Error::Io(err)),
|
||||
};
|
||||
match generate_from_string(&source, opt, header) {
|
||||
match generate_from_string(&source, opt) {
|
||||
Ok(out) => out,
|
||||
Err(err) => format_err(path, &source, err),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_from_string(source: &str, opt: &Opt, header: bool) -> Result<Vec<u8>> {
|
||||
fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
|
||||
let mut source = source;
|
||||
if source.starts_with("#!") && !source.starts_with("#![") {
|
||||
let shebang_end = source.find('\n').unwrap_or(source.len());
|
||||
source = &source[shebang_end..];
|
||||
}
|
||||
let syntax: File = syn::parse_str(source)?;
|
||||
let generated = generate(syntax, opt, header, !header)?;
|
||||
Ok(if header {
|
||||
generated.header
|
||||
} else {
|
||||
generated.implementation
|
||||
})
|
||||
generate(syntax, opt)
|
||||
}
|
||||
|
||||
pub(super) fn generate(
|
||||
syntax: File,
|
||||
opt: &Opt,
|
||||
gen_header: bool,
|
||||
gen_implementation: bool,
|
||||
) -> Result<GeneratedCode> {
|
||||
pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
|
||||
proc_macro2::fallback::force();
|
||||
let ref mut errors = Errors::new();
|
||||
let bridge = syntax
|
||||
@ -123,12 +108,12 @@ pub(super) fn generate(
|
||||
// from the same token stream to avoid parsing twice. But others
|
||||
// only need to generate one or the other.
|
||||
Ok(GeneratedCode {
|
||||
header: if gen_header {
|
||||
header: if opt.gen_header {
|
||||
write::gen(namespace, apis, types, opt, true).content()
|
||||
} else {
|
||||
Vec::new()
|
||||
},
|
||||
implementation: if gen_implementation {
|
||||
implementation: if opt.gen_implementation {
|
||||
write::gen(namespace, apis, types, opt, false).content()
|
||||
} else {
|
||||
Vec::new()
|
||||
|
@ -14,9 +14,11 @@ fn test_cpp() {
|
||||
let opts = Opt {
|
||||
include: Vec::new(),
|
||||
cxx_impl_annotations: None,
|
||||
gen_header: false,
|
||||
gen_implementation: true,
|
||||
};
|
||||
let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
|
||||
let output = std::str::from_utf8(&output).unwrap();
|
||||
let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
|
||||
let output = std::str::from_utf8(&output.implementation).unwrap();
|
||||
// To avoid continual breakage we won't test every byte.
|
||||
// Let's look for the major features.
|
||||
assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
|
||||
@ -27,8 +29,10 @@ fn test_annotation() {
|
||||
let opts = Opt {
|
||||
include: Vec::new(),
|
||||
cxx_impl_annotations: Some("ANNOTATION".to_string()),
|
||||
gen_header: false,
|
||||
gen_implementation: true,
|
||||
};
|
||||
let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
|
||||
let output = std::str::from_utf8(&output).unwrap();
|
||||
let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
|
||||
let output = std::str::from_utf8(&output.implementation).unwrap();
|
||||
assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user