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>>24fn 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()47fn 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