1use std::{env, io, path, process};
20
21pub fn compile_protos<P>(protos: &[P], includes: &[P]) -> io::Result<()>
49where
50 P: AsRef<path::Path>,
51{
52 let out_dir_path: path::PathBuf = env::var_os("OUT_DIR")
53 .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "OUT_DIR env var is not set"))
54 .map(Into::into)?;
55 let out_dir = out_dir_path.as_os_str();
56
57 let _ = prost_build::compile_protos(protos, includes)?;
59
60 let mut cmd = process::Command::new("protoc");
62 for include in includes {
63 cmd.arg("-I").arg(include.as_ref());
64 }
65 for proto in protos {
66 cmd.arg(proto.as_ref());
67 }
68 cmd.arg("--plugin=protoc-gen=brpc=`which protoc-gen-brpc`");
69 cmd.arg("--brpc_out").arg(&out_dir);
70
71 let output = cmd.output()?;
72 if !output.status.success() {
73 return Err(io::Error::new(
74 io::ErrorKind::Other,
75 format!(
76 "protoc failed in the first pass: {}",
77 String::from_utf8_lossy(&output.stderr)
78 ),
79 ));
80 }
81
82 let mut cmd = process::Command::new("protoc");
84 let current_dir = out_dir_path.to_path_buf();
85 cmd.arg("-I").arg(out_dir_path.to_path_buf());
86 for proto in protos {
87 let f = proto
88 .as_ref()
89 .file_name()
90 .ok_or(io::Error::new(io::ErrorKind::Other, "Invalid file name"))?;
91 cmd.arg(current_dir.join(f));
92 }
93 cmd.arg("--cpp_out").arg(out_dir_path.to_path_buf());
94 let output = cmd.output()?;
95 if !output.status.success() {
96 return Err(io::Error::new(
97 io::ErrorKind::Other,
98 format!(
99 "protoc failed in the second pass: {}",
100 String::from_utf8_lossy(&output.stderr)
101 ),
102 ));
103 }
104
105 let mut builder = cc::Build::new();
107 for proto in protos {
108 let mut cc_to_build = out_dir_path.to_path_buf();
109 let f = proto
110 .as_ref()
111 .file_name()
112 .ok_or(io::Error::new(io::ErrorKind::Other, "Invalid file name"))?;
113 cc_to_build.push(f);
114 cc_to_build.set_extension("brpc.cc");
115 builder.file(&cc_to_build);
116
117 let mut cc_to_build = out_dir_path.to_path_buf();
118 let f = proto
119 .as_ref()
120 .file_name()
121 .ok_or(io::Error::new(io::ErrorKind::Other, "Invalid file name"))?;
122 cc_to_build.push(f);
123 cc_to_build.set_extension("pb.cc");
124 builder.file(&cc_to_build);
125 }
126
127 builder.cpp(true).flag("-std=c++11").warnings(false);
128 builder.compile("brpc_service");
129 println!("cargo:rustc-link-lib=static=brpc_service");
130
131 println!("cargo:rustc-link-lib=brpc");
132 println!("cargo:rustc-link-lib=protobuf");
133 println!("cargo:rustc-link-lib=gflags");
134 println!("cargo:rustc-link-lib=leveldb");
135 println!("cargo:rustc-link-lib=ssl");
136 println!("cargo:rustc-link-lib=crypto");
137
138 Ok(())
139}