xref: /aosp_15_r20/external/bazelbuild-rules_rust/proto/protobuf/optional_output_wrapper.rs (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1 // Copyright 2020 The Bazel Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::env::args;
16 use std::error;
17 use std::fs::File;
18 use std::path::Path;
19 use std::process::Command;
20 
21 // A simple wrapper around a binary to ensure we always create some outputs
22 // Optional outputs are not available in Skylark :(
23 // Syntax: $0 output1 output2 ... -- program  [arg1...argn]
ensure() -> Result<i32, Box<dyn error::Error>>24 fn ensure() -> Result<i32, Box<dyn error::Error>> {
25     let index = args().position(|a| a == "--").ok_or("no --")?;
26     let optional_outputs = args().take(index).collect::<Vec<String>>();
27     let exe = args().nth(index + 1).ok_or("no exe")?;
28     let exe_args = args().skip(index + 2).collect::<Vec<String>>();
29     if exe_args.is_empty() {
30         return Err("no exe args".into());
31     }
32     match Command::new(exe).args(exe_args).status()?.code() {
33         Some(code) => {
34             if code == 0 {
35                 for out in optional_outputs {
36                     if !Path::new(&out).exists() {
37                         let _ = File::create(out)?;
38                     }
39                 }
40             }
41             Ok(code)
42         }
43         None => Err("process killed".into()),
44     }
45 }
46 
main()47 fn main() {
48     std::process::exit(match ensure() {
49         Ok(exit_code) => exit_code,
50         Err(e) => {
51             println!("Usage: [optional_output1...optional_outputN] -- program [arg1...argn]");
52             println!("{:?}", args());
53             println!("{e:?}");
54             -1
55         }
56     });
57 }
58