Skip to content

Commit

Permalink
gen_mod_rs codegen option
Browse files Browse the repository at this point in the history
When this option is specified, codegens generate `mod.rs` which
`pub use` all the generated files.

This way:
* users can include generated files
* users don't have to enumerate generated files
* this opens door to generating mod hierarchy
  • Loading branch information
stepancheg committed Sep 27, 2020
1 parent 0f7df86 commit 4aa4689
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 6 deletions.
26 changes: 25 additions & 1 deletion protobuf-codegen-pure-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern crate protobuf_test_common;
use std::io::Read;
use std::io::Write;

use std::env;
use std::fs;
use std::path::Path;

Expand All @@ -20,7 +21,7 @@ fn copy_test<P1: AsRef<Path>, P2: AsRef<Path>>(src: P1, dst: P2) {
fs::File::open(src.as_ref())
.expect(&format!("open {}", src.as_ref().display()))
.read_to_end(&mut content)
.expect("read_to_end");
.expect(&format!("read_to_end {}", src.as_ref().display()));

let mut write = fs::File::create(dst).expect("create");
writeln!(write, "// @generated").expect("write");
Expand Down Expand Up @@ -120,6 +121,27 @@ fn generate_interop() {
.unwrap();
}

fn generate_include_generated() {
copy_from_protobuf_test("src/include_generated/mod.rs");

let dir = format!("{}/include_generated", env::var("OUT_DIR").unwrap());
if Path::new(&dir).exists() {
fs::remove_dir_all(&dir).unwrap();
}
fs::create_dir(&dir).unwrap();
protobuf_codegen_pure::Codegen::new()
.out_dir(dir)
.input("../protobuf-test/src/include_generated/v2.proto")
.input("../protobuf-test/src/include_generated/v3.proto")
.customize(Customize {
gen_mod_rs: Some(true),
..Default::default()
})
.include("../protobuf-test/src/include_generated")
.run()
.unwrap();
}

fn generate_pb_rs() {
print_rerun_if_changed("../protobuf-test");

Expand All @@ -139,6 +161,8 @@ fn generate_pb_rs() {
gen_in_dir("src/google/protobuf", "src");

generate_interop();

generate_include_generated();
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
2 changes: 2 additions & 0 deletions protobuf-codegen-pure-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ mod v3;
mod common;

mod interop;

mod include_generated;
17 changes: 17 additions & 0 deletions protobuf-codegen/src/customize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ pub struct Customize {
pub serde_derive_cfg: Option<String>,
/// Enable lite runtime
pub lite_runtime: Option<bool>,
/// Generate `mod.rs` in the output directory.
///
/// This option allows inclusion of generated files from cargo output directory.
///
/// This option will likely be on by default in rust-protobuf version 3.
pub gen_mod_rs: Option<bool>,
/// Used internally to generate protos bundled in protobuf crate
/// like `descriptor.proto`
pub inside_protobuf: Option<bool>,
Expand Down Expand Up @@ -75,6 +81,9 @@ impl Customize {
if let Some(v) = that.lite_runtime {
self.lite_runtime = Some(v);
}
if let Some(v) = that.gen_mod_rs {
self.gen_mod_rs = Some(v);
}
if let Some(v) = that.inside_protobuf {
self.inside_protobuf = Some(v);
}
Expand Down Expand Up @@ -122,6 +131,8 @@ impl Customize {
r.serde_derive_cfg = Some(v.to_owned());
} else if n == "lite_runtime" {
r.lite_runtime = Some(parse_bool(v)?);
} else if n == "gen_mod_rs" {
r.gen_mod_rs = Some(parse_bool(v)?);
} else if n == "inside_protobuf" {
r.inside_protobuf = Some(parse_bool(v)?);
} else {
Expand All @@ -144,6 +155,7 @@ pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customiz
let serde_derive = rustproto::exts::serde_derive.get(source);
let serde_derive_cfg = rustproto::exts::serde_derive_cfg.get(source);
let lite_runtime = None;
let gen_mod_rs = None;
let inside_protobuf = None;
Customize {
expose_oneof,
Expand All @@ -155,6 +167,7 @@ pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customiz
serde_derive,
serde_derive_cfg,
lite_runtime,
gen_mod_rs,
inside_protobuf,
_future_options: (),
}
Expand All @@ -171,6 +184,7 @@ pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
let serde_derive = None;
let serde_derive_cfg = None;
let lite_runtime = None;
let gen_mod_rs = None;
let inside_protobuf = None;
Customize {
expose_oneof,
Expand All @@ -182,6 +196,7 @@ pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
serde_derive,
serde_derive_cfg,
lite_runtime,
gen_mod_rs,
inside_protobuf,
_future_options: (),
}
Expand All @@ -197,6 +212,7 @@ pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
let serde_derive = rustproto::exts::serde_derive_all.get(source);
let serde_derive_cfg = rustproto::exts::serde_derive_cfg_all.get(source);
let lite_runtime = rustproto::exts::lite_runtime_all.get(source);
let gen_mod_rs = None;
let inside_protobuf = None;
Customize {
expose_oneof,
Expand All @@ -209,6 +225,7 @@ pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
serde_derive_cfg,
lite_runtime,
inside_protobuf,
gen_mod_rs,
_future_options: (),
}
}
39 changes: 35 additions & 4 deletions protobuf-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub use amend_io_error_util::amend_io_error;
use scope::FileScope;
use scope::RootScope;

use crate::file::proto_path_to_fn_file_descriptor;
use crate::file::{proto_path_to_fn_file_descriptor, proto_path_to_rust_mod};
use inside::protobuf_crate_path;
pub use protobuf_abs_path::ProtobufAbsolutePath;
pub use protobuf_ident::ProtobufIdent;
Expand Down Expand Up @@ -243,13 +243,18 @@ impl FileIndex {
}
}

struct GenFileResult {
compiler_plugin_result: compiler_plugin::GenResult,
mod_name: String,
}

fn gen_file(
file_descriptor: &FileDescriptor,
_files_map: &HashMap<&Path, &FileDescriptor>,
root_scope: &RootScope,
customize: &Customize,
parser: &str,
) -> compiler_plugin::GenResult {
) -> GenFileResult {
// TODO: use it
let mut customize = customize.clone();
// options specified in invocation have precedence over options specified in file
Expand Down Expand Up @@ -355,8 +360,26 @@ fn gen_file(
}
}

GenFileResult {
compiler_plugin_result: compiler_plugin::GenResult {
name: proto_name_to_rs(file_descriptor.proto().get_name()),
content: v,
},
mod_name: proto_path_to_rust_mod(file_descriptor.proto().get_name()).into_string(),
}
}

fn gen_mod_rs(mods: &[String]) -> compiler_plugin::GenResult {
let mut v = Vec::new();
let mut w = CodeWriter::new(&mut v);
w.comment("@generated");
w.write_line("");
for m in mods {
w.write_line(&format!("pub mod {};", m));
}
drop(w);
compiler_plugin::GenResult {
name: proto_name_to_rs(file_descriptor.proto().get_name()),
name: "mod.rs".to_owned(),
content: v,
}
}
Expand All @@ -382,19 +405,27 @@ pub fn gen(
.map(|f| (Path::new(f.proto().get_name()), f))
.collect();

let mut mods = Vec::new();

for file_name in files_to_generate {
let file = files_map.get(file_name.as_path()).expect(&format!(
"file not found in file descriptors: {:?}, files: {:?}",
file_name,
files_map.keys()
));
results.push(gen_file(file, &files_map, &root_scope, customize, parser));
let gen_file_result = gen_file(file, &files_map, &root_scope, customize, parser);
results.push(gen_file_result.compiler_plugin_result);
mods.push(gen_file_result.mod_name);
}

if customize.inside_protobuf.unwrap_or(false) {
results.push(gen_well_known_types_mod(&file_descriptors));
}

if customize.gen_mod_rs.unwrap_or(false) {
results.push(gen_mod_rs(&mods));
}

results
}

Expand Down
2 changes: 1 addition & 1 deletion protobuf-codegen/src/rust_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl RustIdent {
&self.0
}

pub fn _into_string(self) -> String {
pub fn into_string(self) -> String {
self.0
}

Expand Down
22 changes: 22 additions & 0 deletions protobuf-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ extern crate protoc_rust;

extern crate protobuf_test_common;

use std::env;
use std::fs;
use std::io::Write;

use protobuf_test_common::build::*;
use std::path::Path;

fn gen_in_dir(dir: &str, include_dir: &str) {
gen_in_dir_impl(
Expand Down Expand Up @@ -71,10 +73,30 @@ fn generate_interop() {
.unwrap();
}

fn generate_include_generated() {
let dir = format!("{}/include_generated", env::var("OUT_DIR").unwrap());
if Path::new(&dir).exists() {
fs::remove_dir_all(&dir).unwrap();
}
fs::create_dir(&dir).unwrap();
protoc_rust::Codegen::new()
.out_dir(dir)
.input("src/include_generated/v2.proto")
.input("src/include_generated/v3.proto")
.customize(Customize {
gen_mod_rs: Some(true),
..Default::default()
})
.include("src/include_generated")
.run()
.unwrap();
}

fn generate_pb_rs() {
generate_in_common();
generate_in_v2_v3();
generate_interop();
generate_include_generated();
}

fn main() {
Expand Down
11 changes: 11 additions & 0 deletions protobuf-test/src/include_generated/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Include single mod.rs which references two mods: `v2` and `v3`
include!(concat!(env!("OUT_DIR"), "/include_generated/mod.rs"));

use v2::V2Message;
use v3::V3Message;

#[test]
fn test() {
let _ = V2Message::new();
let _ = V3Message::new();
}
3 changes: 3 additions & 0 deletions protobuf-test/src/include_generated/v2.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
syntax = "proto2";

message V2Message {}
8 changes: 8 additions & 0 deletions protobuf-test/src/include_generated/v3.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";

import "v2.proto";

message V3Message {
// Test we can include other protos
V2Message v2 = 1;
}
2 changes: 2 additions & 0 deletions protobuf-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ mod common;
mod google;

mod interop;

mod include_generated;

0 comments on commit 4aa4689

Please sign in to comment.