33
44use std:: {
55 collections:: HashMap ,
6+ fs:: File ,
7+ io:: Write ,
68 path:: { Path , PathBuf } ,
79 process:: { Command , Stdio } ,
810 str:: FromStr ,
911} ;
1012
1113fn main ( ) {
14+ let out_dir = PathBuf :: from ( std:: env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
1215 let profile: Profile = std:: env:: var ( "PROFILE" ) . unwrap ( ) . parse ( ) . unwrap ( ) ;
1316 let package_locations = package_locations ( ) ;
1417
@@ -28,10 +31,16 @@ fn main() {
2831 || std:: env:: var ( "DOCS_RS" ) . is_ok ( )
2932 || std:: env:: var ( "JUSTCHECK" ) . is_ok ( ) ;
3033
34+ let mut gen_file = File :: create ( out_dir. join ( "gen.rs" ) ) . unwrap ( ) ;
35+
3136 for feature in FEATURES {
3237 println ! ( "processing {}" , feature. name) ;
33- feature. build_or_stub ( stub, profile, & package_locations) ;
38+ feature. build_or_stub ( stub, profile, & package_locations, & out_dir , & mut gen_file ) ;
3439 }
40+
41+ gen_file. flush ( ) . unwrap ( ) ;
42+
43+ println ! ( "cargo::rerun-if-changed=build.rs" ) ;
3544}
3645
3746/// Get locations for all packages in the dependency tree.
@@ -151,6 +160,27 @@ impl std::fmt::Display for Profile {
151160 }
152161}
153162
163+ /// Artifact type.
164+ enum ArtifactType {
165+ /// Library.
166+ Lib ,
167+
168+ /// Example.
169+ Example ( & ' static str ) ,
170+ }
171+
172+ /// Just(file) command.
173+ struct JustCmd {
174+ /// Artifact type.
175+ artifact_type : ArtifactType ,
176+
177+ /// Name of the resulting constant.
178+ const_name : & ' static str ,
179+
180+ /// Documentation for the created constant.
181+ doc : & ' static str ,
182+ }
183+
154184/// Feature description.
155185struct Feature {
156186 /// Lowercase feature name.
@@ -159,15 +189,8 @@ struct Feature {
159189 /// Package that contains the feature code.
160190 package : & ' static str ,
161191
162- /// `just` command prefix that compiles the feature.
163- ///
164- /// This will call `just prefix{profile}` within the package directory.
165- just_cmd_prefix : & ' static str ,
166-
167- /// Path components to file in target directory.
168- ///
169- /// So `["foo", "bar.bin"]` will resolve to `CARGO_TARGET_DIR/wasm32-wasip2/foo/bar.bin`.
170- just_out_file : & ' static [ & ' static str ] ,
192+ /// Just commands.
193+ just_cmds : & ' static [ JustCmd ] ,
171194}
172195
173196impl Feature {
@@ -177,12 +200,13 @@ impl Feature {
177200 stub : bool ,
178201 profile : Profile ,
179202 package_locations : & HashMap < String , PathBuf > ,
203+ out_dir : & Path ,
204+ gen_file : & mut File ,
180205 ) {
181206 let Self {
182207 name,
183208 package,
184- just_cmd_prefix,
185- just_out_file,
209+ just_cmds,
186210 } = self ;
187211
188212 let name_upper = name. to_uppercase ( ) ;
@@ -191,32 +215,61 @@ impl Feature {
191215 return ;
192216 }
193217
194- let out_dir = PathBuf :: from ( std:: env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
195-
196- let out_file = if stub {
197- let out_file = out_dir. join ( format ! ( "{name}.wasm" ) ) ;
198- // write empty stub file
199- std:: fs:: write ( & out_file, b"" ) . unwrap ( ) ;
200- out_file
201- } else {
202- let target_dir = out_dir. join ( name) ;
218+ let cwd = package_locations. get ( * package) . unwrap ( ) ;
219+ let target_dir = out_dir. join ( name) ;
220+
221+ for just_cmd in * just_cmds {
222+ let JustCmd {
223+ artifact_type,
224+ const_name,
225+ doc,
226+ } = just_cmd;
227+ let out_file = if stub {
228+ let out_file = out_dir. join ( format ! ( "{name}.wasm" ) ) ;
229+ // write empty stub file
230+ std:: fs:: write ( & out_file, b"" ) . unwrap ( ) ;
231+ out_file
232+ } else {
233+ let mut just_cmd = "build-" . to_owned ( ) ;
234+ match artifact_type {
235+ ArtifactType :: Lib => { }
236+ ArtifactType :: Example ( example) => {
237+ just_cmd. push_str ( example) ;
238+ just_cmd. push ( '-' ) ;
239+ }
240+ }
241+ just_cmd. push_str ( profile. as_str ( ) ) ;
242+
243+ just_build ( cwd, & just_cmd, & target_dir) ;
244+
245+ let out = target_dir. join ( "wasm32-wasip2" ) . join ( profile. as_str ( ) ) ;
246+ match artifact_type {
247+ ArtifactType :: Lib => out. join ( format ! ( "{}.wasm" , package. replace( "-" , "_" ) ) ) ,
248+ ArtifactType :: Example ( example) => out
249+ . join ( "examples" )
250+ . join ( format ! ( "{}.wasm" , example. replace( "-" , "_" ) ) ) ,
251+ }
252+ } ;
203253
204- just_build (
205- package_locations. get ( * package) . unwrap ( ) ,
206- & format ! ( "{just_cmd_prefix}{profile}" ) ,
207- & target_dir,
254+ println ! (
255+ "cargo::rustc-env=BIN_PATH_{const_name}={}" ,
256+ out_file. display( ) ,
208257 ) ;
209258
210- just_out_file. iter ( ) . fold (
211- target_dir. join ( "wasm32-wasip2" ) . join ( profile. as_str ( ) ) ,
212- |path, part| path. join ( part) ,
213- )
214- } ;
215-
216- println ! (
217- "cargo::rustc-env=BIN_PATH_{name_upper}={}" ,
218- out_file. display( ) ,
219- ) ;
259+ writeln ! ( gen_file, "/// {doc}" ) . unwrap ( ) ;
260+ writeln ! ( gen_file, r#"#[cfg(feature = "{name}")]"# ) . unwrap ( ) ;
261+ writeln ! ( gen_file, r#"pub static BIN_{const_name}: &[u8] = include_bytes!(env!("BIN_PATH_{const_name}"));"# ) . unwrap ( ) ;
262+
263+ // we cannot really depend directly on examples, so we need to tell Cargo about it
264+ if let ArtifactType :: Example ( example) = artifact_type {
265+ println ! (
266+ "cargo::rerun-if-changed={}" ,
267+ cwd. join( "examples" )
268+ . join( format!( "{}.rs" , example. replace( "-" , "_" ) ) )
269+ . display( ) ,
270+ ) ;
271+ }
272+ }
220273 }
221274}
222275
@@ -232,18 +285,24 @@ fn just_build(cwd: &Path, just_cmd: &str, cargo_target_dir: &Path) {
232285
233286/// All supported features.
234287///
235- /// This must be in-sync with the feature list in `Cargo.toml` and the imports in `src/lib.rs` .
288+ /// This must be in-sync with the feature list in `Cargo.toml`.
236289const FEATURES : & [ Feature ] = & [
237290 Feature {
238291 name : "example" ,
239292 package : "datafusion-udf-wasm-guest" ,
240- just_cmd_prefix : "build-add-one-" ,
241- just_out_file : & [ "examples" , "add_one.wasm" ] ,
293+ just_cmds : & [ JustCmd {
294+ artifact_type : ArtifactType :: Example ( "add-one" ) ,
295+ const_name : "EXAMPLE" ,
296+ doc : r#""add-one" example."# ,
297+ } ] ,
242298 } ,
243299 Feature {
244300 name : "python" ,
245301 package : "datafusion-udf-wasm-python" ,
246- just_cmd_prefix : "" ,
247- just_out_file : & [ "datafusion_udf_wasm_python.wasm" ] ,
302+ just_cmds : & [ JustCmd {
303+ artifact_type : ArtifactType :: Lib ,
304+ const_name : "PYTHON" ,
305+ doc : "Python UDF." ,
306+ } ] ,
248307 } ,
249308] ;
0 commit comments