blob: 32e3f3c8ed8e251182c786d38106be2d9f1e7c75 [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A simple wrapper around a build_script execution to generate file to reuse
// by rust_library/rust_binary.
extern crate cargo_build_script_output_parser;
use cargo_build_script_output_parser::{BuildScriptOutput, CompileAndLinkFlags};
use std::env;
use std::fs::{create_dir_all, write};
use std::path::Path;
use std::process::{exit, Command};
fn main() {
// We use exec_root.join rather than std::fs::canonicalize, to avoid resolving symlinks, as
// some execution strategies and remote execution environments may use symlinks in ways which
// canonicalizing them may break them, e.g. by having input files be symlinks into a /cas
// directory - resolving these may cause tools which inspect $0, or try to resolve files
// relative to themselves, to fail.
let exec_root = env::current_dir().expect("Failed to get current directory");
let mut args = env::args().skip(1);
let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set");
let rustc_env = env::var("RUSTC").expect("RUSTC was not set");
let manifest_dir = exec_root.join(&manifest_dir_env);
let rustc = exec_root.join(&rustc_env);
let cc = env::var_os("CC").map(|env_var| {
let cc_path = Path::new(&env_var);
if cc_path.is_relative() {
exec_root.join(cc_path).into_os_string()
} else {
env_var
}
});
match (args.next(), args.next(), args.next(), args.next(), args.next(), args.next(), args.next()) {
(Some(progname), Some(crate_name), Some(out_dir), Some(envfile), Some(flagfile), Some(linkflags), Some(depenvfile)) => {
let out_dir_abs = exec_root.join(&out_dir);
// For some reason Google's RBE does not create the output directory, force create it.
create_dir_all(&out_dir_abs).expect(&format!("Failed to make output directory: {:?}", out_dir_abs));
let mut command = Command::new(exec_root.join(&progname));
command
.args(args)
.current_dir(manifest_dir.clone())
.env("OUT_DIR", out_dir_abs)
.env("CARGO_MANIFEST_DIR", manifest_dir)
.env("RUSTC", rustc);
if let Some(cc) = cc {
command.env("CC", cc);
}
let output = BuildScriptOutput::from_command(&mut command);
write(&envfile, BuildScriptOutput::to_env(&output).as_bytes())
.expect(&format!("Unable to write file {:?}", envfile));
write(&depenvfile, BuildScriptOutput::to_dep_env(&output, &crate_name).as_bytes())
.expect(&format!("Unable to write file {:?}", depenvfile));
let CompileAndLinkFlags { compile_flags, link_flags } = BuildScriptOutput::to_flags(&output, &exec_root.to_string_lossy());
write(&flagfile, compile_flags.as_bytes())
.expect(&format!("Unable to write file {:?}", flagfile));
write(&linkflags, link_flags.as_bytes())
.expect(&format!("Unable to write file {:?}", linkflags));
}
_ => {
eprintln!("Usage: $0 progname crate_name out_dir envfile flagfile linkflagfile depenvfile [arg1...argn]");
exit(1);
}
}
}