Create and install Fuchsia packages when running
For all run modes except normal, create and install a Fuchsia
package rather than using scp.
Also expose this as fargo make-package, as that might be useful.
Also fix adapt to the recent zircon build changes.
Change-Id: I3490fd356afdd08453ebd93ce3fbeaea9c4b6271
diff --git a/Cargo.lock b/Cargo.lock
index 47cc2ea..143f8e1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -114,8 +114,9 @@
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"uname 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -186,6 +187,11 @@
]
[[package]]
+name = "itoa"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -285,8 +291,13 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "ryu"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "serde"
-version = "1.0.11"
+version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -309,6 +320,16 @@
]
[[package]]
+name = "serde_json"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "slab"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -380,7 +401,7 @@
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -480,6 +501,7 @@
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
"checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c"
"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
+"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb7b49972ee23d8aa1026c365a5b440ba08e35075f18c459980c7395c221ec48"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
@@ -491,9 +513,11 @@
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum redox_syscall 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ddab7acd8e7bf3e49dfdf78ac1209b992329eb2f66e0bf672ab49c70a76d1d68"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
-"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
+"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
+"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
+"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
diff --git a/Cargo.toml b/Cargo.toml
index f64047f..6c5f426 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@
notify = "4.0.0"
serde = "1.0"
serde_derive = "1.0"
+serde_json = "1.0"
toml = "0.4"
[[bin]]
diff --git a/README.md b/README.md
index ca5cef8..4b2f658 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@
-v, --verbose Print verbose output while performing commands
OPTIONS:
+ --cmx-path <cmx-path> Path to sandbox file to use when running
-N, --device-name <device-name>
Name of device to target, needed if there are multiple devices visible on the network
@@ -21,7 +22,7 @@
SUBCOMMANDS:
autotest Auto build and test in Fuchsia device or emulator
build Build binary targeting Fuchsia device or emulator
- build-tests Build tests for Fuchsia device or emulator
+ build-rustc Build rustc targeting Fuchsia
cargo Run a cargo command for Fuchsia. Use -- to indicate that all following
arguments should be passed to cargo.
check Check binary targeting Fuchsia device or emulator
@@ -31,6 +32,7 @@
help Prints this message or the help of the given subcommand(s)
list-devices List visible Fuchsia devices
load-driver Build driver and load it on Fuchsia device or emulator.
+ make-package Make a Fuchsia package from an unstripped binary
pkg-config Run pkg-config for the cross compilation environment
restart Stop all Fuchsia emulators and start a new one
run Run binary on Fuchsia device or emulator
@@ -68,7 +70,7 @@
cd fargo
cargo install --force --path .
-Fargo uses the $FUCHSIA\_DIR/.config file written by ./scripts/fx set to know what
+Fargo uses the values set by `./scripts/fx set` to know what
build directory to use.
Fargo uses ssh to communicate between your host computer and either Qemu or a
@@ -102,9 +104,10 @@
### Running view-producing Rust binaries
-fargo run has an option, `--run-with-tiles`, that will use `tiles_ctl add` to launch the Rust
-binary. Use this option when running if your binaries wants to provide a
-[view provider service](https://fuchsia.googlesource.com/garnet/+/master/public/fidl/fuchsia.ui.views_v1/view_provider.fidl)
+fargo run has the options, `--run-with-tiles` and `--run-with-sessionctl`, that will use
+`tiles_ctl add` to launch the Rust binary. Use this option when running if your binaries
+wants to provide a
+[view provider service](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/sdk/fidl/fuchsia.ui.app/view_provider.fidl)
## Creating a .cargo/config
diff --git a/src/device.rs b/src/device.rs
index 302fed6..98ca071 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-use crate::sdk::{fuchsia_dir, fx_path, target_out_dir, FuchsiaConfig, TargetOptions};
+use crate::sdk::{
+ fuchsia_dir, fx_path, target_out_dir, zircon_build_path, FuchsiaConfig, TargetOptions,
+};
use crate::utils::is_mac;
use failure::{bail, err_msg, Error, ResultExt};
use std::env;
@@ -11,8 +13,8 @@
use std::{str, thread, time};
pub fn netaddr(verbose: bool, target_options: &TargetOptions<'_, '_>) -> Result<String, Error> {
- let fuchsia_dir = fuchsia_dir()?;
- let netaddr_binary = fuchsia_dir.join("out/build-zircon/tools/netaddr");
+ let zircon_build_dir = zircon_build_path(&target_options.config)?;
+ let netaddr_binary = zircon_build_dir.join("tools/netaddr");
let mut args = vec!["--fuchsia", "--timeout=500", "--nowait"];
if let Some(device_name) = target_options.device_name {
args.push(device_name);
@@ -29,9 +31,9 @@
Ok(result)
}
-pub fn netls(verbose: bool) -> Result<(), Error> {
- let fuchsia_dir = fuchsia_dir()?;
- let netls_binary = fuchsia_dir.join("out/build-zircon/tools/netls");
+pub fn netls(verbose: bool, target_options: &TargetOptions<'_, '_>) -> Result<(), Error> {
+ let zircon_build_dir = zircon_build_path(&target_options.config)?;
+ let netls_binary = zircon_build_dir.join("tools/netls");
let mut netls_command = Command::new(netls_binary);
netls_command.arg("--nowait").arg("--timeout=500");
if verbose {
@@ -100,7 +102,7 @@
target_options: &TargetOptions<'_, '_>,
command: &str,
) -> Result<(), Error> {
- let netaddr = netaddr(verbose, target_options)?;
+ let netaddr = netaddr(verbose, target_options).context("netaddr failed")?;
let ssh_config = target_out_dir(config)?.join("ssh-keys/ssh_config");
if !ssh_config.exists() {
bail!("ssh config not found at {:?}", ssh_config);
diff --git a/src/lib.rs b/src/lib.rs
index 3a94f26..d7b3601 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,6 +11,7 @@
mod build_rustc;
mod cross;
mod device;
+mod package;
mod sdk;
mod utils;
@@ -22,12 +23,15 @@
enable_networking, netaddr, netls, scp_to_device, ssh, start_emulator, stop_emulator,
StartEmulatorOptions,
};
-use crate::sdk::{
- cargo_out_dir, cargo_path, clang_archiver_path, clang_c_compiler_path, clang_cpp_compiler_path,
- clang_ranlib_path, clang_resource_dir, rustc_path, rustdoc_path, shared_libraries_path,
- sysroot_path, zircon_build_path,
+use crate::package::make_package;
+use crate::{
+ sdk::{
+ cargo_out_dir, cargo_path, clang_archiver_path, clang_c_compiler_path,
+ clang_cpp_compiler_path, clang_ranlib_path, clang_resource_dir, rustc_path, rustdoc_path,
+ shared_libraries_path, sysroot_path, zircon_build_path,
+ },
+ utils::strip_binary,
};
-use crate::utils::strip_binary;
use clap::{App, AppSettings, Arg, SubCommand};
use failure::{bail, err_msg, format_err, Error, ResultExt};
@@ -67,14 +71,26 @@
config: &FuchsiaConfig,
target_options: &TargetOptions<'_, '_>,
run_mode: RunMode,
+ cmx_path: &Option<PathBuf>,
story_name: &str,
mod_name: &str,
params: &[&str],
test_args: Option<&str>,
) -> Result<(), Error> {
let source_path = PathBuf::from(&filename);
- let stripped_source_path = strip_binary(&source_path)?;
- let destination_path = copy_to_target(&stripped_source_path, verbose, config, target_options)?;
+ let target_string = match run_mode {
+ RunMode::Normal => {
+ let stripped_source_path = strip_binary(&source_path)?;
+ copy_to_target(&stripped_source_path, verbose, config, target_options)?
+ }
+ _ => {
+ if cmx_path.is_none() {
+ bail!("Run modes other than normal require a path to a cmx file");
+ }
+ make_package(target_options, &source_path, cmx_path.as_ref().unwrap())?
+ }
+ };
+
let mut command_string = match run_mode {
RunMode::Tiles => "tiles_ctl add ".to_string(),
RunMode::Ermine => {
@@ -83,7 +99,7 @@
RunMode::Run => "run ".to_string(),
RunMode::Normal => "".to_string(),
};
- command_string.push_str(&destination_path);
+ command_string.push_str(&target_string);
match run_mode {
RunMode::Ermine => {
@@ -111,7 +127,7 @@
println!("running {}", command_string);
}
- ssh(verbose, config, target_options, &command_string)?;
+ ssh(verbose, config, target_options, &command_string).context("ssh failed")?;
Ok(())
}
@@ -293,6 +309,7 @@
pub disable_cross: bool,
pub nocapture: bool,
pub manifest_path: Option<PathBuf>,
+ pub cmx_path: Option<PathBuf>,
}
impl RunCargoOptions {
@@ -306,6 +323,7 @@
mod_name: None,
disable_cross: false,
manifest_path: None,
+ cmx_path: None,
}
}
@@ -319,6 +337,7 @@
mod_name: self.mod_name.clone(),
disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -332,6 +351,7 @@
mod_name: self.mod_name.clone(),
disable_cross: self.disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -345,6 +365,7 @@
mod_name: self.mod_name.clone(),
disable_cross: self.disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -358,6 +379,7 @@
mod_name: self.mod_name.clone(),
disable_cross: self.disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -371,6 +393,7 @@
mod_name: self.mod_name.clone(),
disable_cross: self.disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -384,6 +407,7 @@
mod_name: mod_name.map(|name| name.to_string()),
disable_cross: self.disable_cross,
manifest_path: self.manifest_path.clone(),
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -397,6 +421,7 @@
mod_name: self.mod_name.clone(),
disable_cross: self.disable_cross,
manifest_path: manifest_path,
+ cmx_path: self.cmx_path.clone(),
}
}
@@ -417,11 +442,11 @@
}
}
-fn get_triple_cpu(target_options: &TargetOptions<'_, '_>) -> String {
+pub fn get_triple_cpu(target_options: &TargetOptions<'_, '_>) -> String {
if (target_options.config.fuchsia_arch) == X64 { "x86_64" } else { "aarch64" }.to_string()
}
-fn get_target_triple(target_options: &TargetOptions<'_, '_>) -> String {
+pub fn get_target_triple(target_options: &TargetOptions<'_, '_>) -> String {
let triple_cpu = get_triple_cpu(target_options);
format!("{}-fuchsia", triple_cpu)
@@ -432,6 +457,7 @@
sysroot_as_path: &PathBuf,
) -> Result<String, Error> {
let target_triple = get_target_triple(target_options);
+ let zircon_build_dir = zircon_build_path(&target_options.config)?;
let sysroot_lib_pathbuf = sysroot_as_path.join("lib");
let sysroot_lib = sysroot_lib_pathbuf.to_string_lossy();
let clang_resource_lib = clang_resource_dir(&target_triple)?.join(&target_triple).join("lib");
@@ -442,6 +468,16 @@
"-Clink-arg=--pack-dyn-relocs=relr".to_string(),
"-Clink-arg=--threads".to_string(),
format!("-Clink-arg=-L{}", sysroot_lib),
+ format!(
+ "-Clink-arg=-L{}/user-{}-gcc.shlib/obj/system/ulib/fdio",
+ zircon_build_dir.to_string_lossy(),
+ target_options.config.fuchsia_arch
+ ),
+ format!(
+ "-Clink-arg=-L{}/user-{}-gcc.shlib/obj/system/ulib/syslog",
+ zircon_build_dir.to_string_lossy(),
+ target_options.config.fuchsia_arch
+ ),
format!("-Clink-arg=-L{}", clang_resource_lib.to_string_lossy()),
format!("-Clink-arg=--sysroot={}", sysroot_as_path.to_string_lossy()),
format!("-Lnative={}", shared_libraries_path(target_options)?.to_string_lossy()),
@@ -461,6 +497,7 @@
target_options: &TargetOptions<'_, '_>,
additional_target_args: Option<&str>,
) -> Result<String, Error> {
+ let mut cmx_path;
let tiles_arg = format!("--{}", RUN_WITH_TILES);
let ermine_arg = format!(
"--{} --story-name={} --mod-name={}",
@@ -468,6 +505,7 @@
options.get_story_name(),
options.get_mod_name()
);
+ let cmx_arg = format!("--{}", CMX_PATH);
let run_arg = format!("--{}", RUN_WITH_RUN);
let nocapture_arg = format!("--{}", NOCAPTURE);
@@ -477,9 +515,9 @@
fs::canonicalize(std::env::current_exe()?)?
};
- let mut runner_args = vec![
- fargo_path.to_str().ok_or_else(|| err_msg("unable to convert path to utf8 encoding"))?,
- ];
+ let mut runner_args = vec![fargo_path
+ .to_str()
+ .ok_or_else(|| err_msg("unable to convert path to utf8 encoding"))?];
if options.verbose {
runner_args.push("-v");
@@ -490,6 +528,19 @@
runner_args.push(device_name);
}
+ if let Some(ref passed_path) = options.cmx_path {
+ cmx_path = passed_path.to_string_lossy().to_string();
+ runner_args.push(&cmx_arg);
+ runner_args.push(&cmx_path);
+ } else {
+ match options.run_mode {
+ RunMode::Normal => (),
+ _ => {
+ bail!("Run modes other than normal require a path to a cmx file");
+ }
+ }
+ }
+
runner_args.push(RUN_ON_TARGET);
if nocapture {
@@ -540,6 +591,7 @@
/// mod_name: None,
/// disable_cross: false,
/// manifest_path: None,
+/// cmx_path: None,
/// },
/// "help",
/// &[],
@@ -613,7 +665,7 @@
.env("RUSTDOC", rustdoc_path()?.to_string_lossy().as_ref())
.env("RUSTDOCFLAGS", "--cap-lints allow -Z unstable-options")
.env("FUCHSIA_SHARED_ROOT", shared_libraries_path(target_options)?)
- .env("ZIRCON_BUILD_ROOT", zircon_build_path(target_options)?)
+ .env("ZIRCON_BUILD_ROOT", zircon_build_path(&target_options.config)?)
.arg(subcommand)
.args(target_args)
.args(args);
@@ -718,6 +770,7 @@
static NO_NET: &str = "no-net";
static FX_RUN_PARAMS: &str = "fx-run-params";
static MANIFEST_PATH: &str = "manifest-path";
+static CMX_PATH: &str = "cmx-path";
static RELEASE_HELP: &str = "Build artifacts in release mode, with optimizations";
@@ -733,6 +786,9 @@
static RUN_ON_TARGET: &str = "run-on-target";
+static MAKE_PACKAGE: &str = "make-package";
+static BINARY_PATH: &str = "binary-path";
+
#[doc(hidden)]
pub fn run() -> Result<(), Error> {
let matches = App::new("fargo")
@@ -768,6 +824,12 @@
.global(true)
.help("Path to Cargo.toml"),
)
+ .arg(
+ Arg::with_name(CMX_PATH)
+ .long(CMX_PATH)
+ .value_name(CMX_PATH)
+ .help("Path to sandbox file to use when running"),
+ )
.subcommand(
SubCommand::with_name("autotest")
.about("Auto build and test in Fuchsia device or emulator")
@@ -1078,6 +1140,17 @@
)
.about("Build rustc targeting Fuchsia"),
)
+ .subcommand(
+ SubCommand::with_name(MAKE_PACKAGE)
+ .arg(
+ Arg::with_name(BINARY_PATH)
+ .long(BINARY_PATH)
+ .value_name(BINARY_PATH)
+ .required(true)
+ .help("Path to the binary to package"),
+ )
+ .about("Make a Fuchsia package from an unstripped binary"),
+ )
.get_matches();
let verbose = matches.is_present("verbose");
@@ -1099,6 +1172,7 @@
mod_name: None,
disable_cross,
manifest_path: None,
+ cmx_path: matches.value_of(CMX_PATH).map(|s| PathBuf::from(s)),
};
if verbose {
@@ -1274,7 +1348,7 @@
}
if matches.subcommand_matches("list-devices").is_some() {
- return netls(verbose);
+ return netls(verbose, &target_options);
}
if let Some(start_matches) = matches.subcommand_matches(START) {
@@ -1336,6 +1410,7 @@
mod_name: None,
disable_cross: disable_cross,
manifest_path: None,
+ cmx_path: None,
},
subcommand,
&cargo_params,
@@ -1365,6 +1440,7 @@
&fuchsia_config,
&target_options,
run_mode,
+ &run_cargo_options.cmx_path,
run_on_target_matches.value_of(STORY_NAME).unwrap_or(&random_story_name()),
run_on_target_matches.value_of(MOD_NAME).unwrap_or(DEFAULT_MOD_NAME),
args,
@@ -1409,5 +1485,20 @@
return build_rustc(&rust_root, &target_options);
}
+ if let Some(make_package_matches) = matches.subcommand_matches(MAKE_PACKAGE) {
+ let binary_path = PathBuf::from(
+ make_package_matches
+ .value_of(BINARY_PATH)
+ .expect(&format!("{} is a required parameter of {}", BINARY_PATH, MAKE_PACKAGE)),
+ );
+ let cmx_path = PathBuf::from(
+ make_package_matches
+ .value_of(CMX_PATH)
+ .expect(&format!("{} is a required parameter of {}", CMX_PATH, MAKE_PACKAGE)),
+ );
+ println!("make package {}", make_package(&target_options, &binary_path, &cmx_path)?);
+ return Ok(());
+ }
+
Ok(())
}
diff --git a/src/package.rs b/src/package.rs
new file mode 100644
index 0000000..810ca4c
--- /dev/null
+++ b/src/package.rs
@@ -0,0 +1,232 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use crate::{
+ get_target_triple,
+ sdk::{
+ amber_path, clang_resource_dir, cmc_path, fuchsia_dir, package_manager_path,
+ zircon_build_path, FuchsiaConfig, TargetOptions,
+ },
+ utils::strip_binary,
+};
+use failure::{bail, format_err, Error, ResultExt};
+use serde_json::json;
+use std::{
+ fs::{create_dir_all, File},
+ io::Write,
+ path::{Path, PathBuf},
+ process::Command,
+};
+
+fn validate_cmx_file(fuchsia_config: &FuchsiaConfig, cmx_path: &Path) -> Result<(), Error> {
+ let cmc = cmc_path(fuchsia_config)?;
+
+ let output = Command::new(cmc)
+ .arg("validate")
+ .arg(cmx_path)
+ .output()
+ .context("Running `cmc` to validate cmx file")?;
+
+ if !output.status.success() {
+ bail!("cmc returned error: {}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ Ok(())
+}
+
+fn format_cmx_file(fuchsia_config: &FuchsiaConfig, cmx_path: &Path) -> Result<PathBuf, Error> {
+ let destination_path = format!(
+ "/tmp/{}",
+ cmx_path
+ .file_name()
+ .ok_or(format_err!("file_name failed on {:#?}", cmx_path))?
+ .to_string_lossy()
+ );
+
+ let cmc = cmc_path(fuchsia_config)?;
+
+ let output = Command::new(cmc)
+ .arg("format")
+ .arg(cmx_path)
+ .arg("-o")
+ .arg(&destination_path)
+ .output()
+ .context("Running `cmc` to format cmx file")?;
+
+ if !output.status.success() {
+ bail!("cmc returned error: {}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ Ok(PathBuf::from(destination_path))
+}
+
+fn write_manifest_file(
+ target_options: &TargetOptions<'_, '_>,
+ target: &Path,
+ binary_path: &Path,
+ package_path: &Path,
+ cmx_path: &Path,
+ package_name: &str,
+) -> Result<(), Error> {
+ let mut manifest = File::create(&target)?;
+ let zircon_build = zircon_build_path(&target_options.config)?;
+ let libc_path = format!(
+ "{}/user-{}-gcc.shlib/obj/system/ulib/c/libc.so",
+ zircon_build.to_string_lossy(),
+ target_options.config.fuchsia_arch
+ );
+ let fdio_path = format!(
+ "{}/user-{}-gcc.shlib/obj/system/ulib/fdio/libfdio.so",
+ zircon_build.to_string_lossy(),
+ target_options.config.fuchsia_arch
+ );
+ let target_triple = get_target_triple(target_options);
+ let clang_resource_lib = clang_resource_dir(&target_triple)?.join(&target_triple).join("lib");
+ let libsyslog_path = format!(
+ "{}/user-{}-gcc.shlib/obj/system/ulib/syslog/libsyslog.so",
+ zircon_build.to_string_lossy(),
+ target_options.config.fuchsia_arch
+ );
+ writeln!(
+ manifest,
+ r#"bin/app={}
+lib/ld.so.1={}
+lib/libfdio.so={}
+lib/libunwind.so.1={}/libunwind.so.1
+lib/libsyslog.so={}
+meta/package={}
+meta/{}.cmx={}
+"#,
+ binary_path.to_string_lossy(),
+ libc_path,
+ fdio_path,
+ clang_resource_lib.to_string_lossy(),
+ libsyslog_path,
+ package_path.to_string_lossy(),
+ package_name,
+ cmx_path.to_string_lossy(),
+ )?;
+ Ok(())
+}
+
+fn write_package_file(target: &Path, package_name: &str) -> Result<(), Error> {
+ let mut package = File::create(&target)?;
+ let package_contents = json!({
+ "name": package_name,
+ "version": "0"
+ });
+ writeln!(package, "{}", package_contents.to_string())?;
+ Ok(())
+}
+
+fn pm_build(
+ target_options: &TargetOptions<'_, '_>,
+ manifest_path: &Path,
+ output_path: &Path,
+) -> Result<(), Error> {
+ let pm = package_manager_path(target_options.config)?;
+
+ let fuchsia_dir = fuchsia_dir()?;
+ let dev_key_path = fuchsia_dir.join("build/development.key");
+ let output = Command::new(pm)
+ .arg("-k")
+ .arg(dev_key_path)
+ .arg("-o")
+ .arg(&output_path)
+ .arg("-m")
+ .arg(&manifest_path)
+ .arg("build")
+ .arg("-depfile")
+ .arg("-blobsfile")
+ .arg("-blobs-manifest")
+ .output()
+ .context("Running `cmc` to format cmx file")?;
+
+ if !output.status.success() {
+ bail!("pm returned error: {}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ Ok(())
+}
+
+fn pm_archive(
+ target_options: &TargetOptions<'_, '_>,
+ output_path: &Path,
+ manifest_path: &Path,
+) -> Result<(), Error> {
+ let pm = package_manager_path(target_options.config)?;
+
+ let output = Command::new(pm)
+ .arg("-o")
+ .arg(&output_path)
+ .arg("-m")
+ .arg(&manifest_path)
+ .arg("archive")
+ .output()
+ .context("Running `cmc` to format cmx file")?;
+
+ if !output.status.success() {
+ bail!("pm returned error: {}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ Ok(())
+}
+
+fn pm_publish(target_options: &TargetOptions<'_, '_>, output_path: &Path) -> Result<(), Error> {
+ let pm = package_manager_path(target_options.config)?;
+ let tuf_root = amber_path(target_options.config)?;
+ let output = Command::new(pm)
+ .arg("publish")
+ .arg("-a")
+ .arg("-f")
+ .arg(output_path)
+ .arg("-r")
+ .arg(tuf_root)
+ .arg("-vt")
+ .arg("-v")
+ .output()
+ .context("Running `cmc` to format cmx file")?;
+
+ if !output.status.success() {
+ bail!("pm returned error: {}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ Ok(())
+}
+
+pub fn make_package(
+ target_options: &TargetOptions<'_, '_>,
+ binary_path: &Path,
+ cmx_path: &Path,
+) -> Result<String, Error> {
+ let binary_parent =
+ binary_path.parent().expect(&format!("Can't get parent of {:#?}", binary_path));
+ let mut package_name = binary_path
+ .file_name()
+ .expect("file_name failed on binary_path")
+ .to_string_lossy()
+ .to_string();
+ package_name.push_str("_fargo");
+ let output_path = binary_parent.join(&package_name);
+ create_dir_all(&output_path).context("create_dir_all failed")?;
+ let stripped_binary_path = strip_binary(binary_path)?;
+ validate_cmx_file(&target_options.config, cmx_path)?;
+ let formatted_path = format_cmx_file(&target_options.config, cmx_path)?;
+ let package_path = PathBuf::from("/tmp/package");
+ write_package_file(&package_path, &package_name)?;
+ let manifest_path = PathBuf::from("/tmp/manifest");
+ write_manifest_file(
+ &target_options,
+ &manifest_path,
+ &stripped_binary_path,
+ &package_path,
+ &formatted_path,
+ &package_name,
+ )?;
+ pm_build(&target_options, &manifest_path, &output_path).context("pm_build failed")?;
+ pm_archive(&target_options, &output_path, &manifest_path).context("pm_archive failed")?;
+ pm_publish(&target_options, &output_path.join(format!("{}-0.far", package_name)))
+ .context("pm_publish failed")?;
+ Ok(format!("fuchsia-pkg://fuchsia.com/{}#meta/{}.cmx", package_name, package_name))
+}
diff --git a/src/sdk.rs b/src/sdk.rs
index c5b1c31..9dfcbaa 100644
--- a/src/sdk.rs
+++ b/src/sdk.rs
@@ -104,6 +104,22 @@
Ok(fuchsia_dir.join("garnet").join("target").join(target_triple).join("debug"))
}
+pub fn host_out_dir(config: &FuchsiaConfig) -> Result<PathBuf, Error> {
+ Ok(target_out_dir(config)?.join("host_x64"))
+}
+
+pub fn package_manager_path(config: &FuchsiaConfig) -> Result<PathBuf, Error> {
+ Ok(host_out_dir(config)?.join("pm"))
+}
+
+pub fn cmc_path(config: &FuchsiaConfig) -> Result<PathBuf, Error> {
+ Ok(host_out_dir(config)?.join("cmc"))
+}
+
+pub fn amber_path(config: &FuchsiaConfig) -> Result<PathBuf, Error> {
+ Ok(target_out_dir(config)?.join("amber-files"))
+}
+
pub fn strip_tool_path() -> Result<PathBuf, Error> {
Ok(clang_base_path()?.join("bin/llvm-objcopy"))
}
@@ -118,11 +134,8 @@
.join("sysroot"))
}
-pub fn zircon_build_path(options: &TargetOptions<'_, '_>) -> Result<PathBuf, Error> {
- let fuchsia_dir = fuchsia_dir()?;
- let build_name = if options.config.fuchsia_arch == X64 { "build-x64" } else { "build-arm64" };
- let zircon_build = fuchsia_dir.join("out").join("build-zircon").join(build_name);
- Ok(zircon_build)
+pub fn zircon_build_path(config: &FuchsiaConfig) -> Result<PathBuf, Error> {
+ Ok(PathBuf::from(&config.zircon_build_dir))
}
pub fn shared_libraries_path(options: &TargetOptions<'_, '_>) -> Result<PathBuf, Error> {
@@ -207,6 +220,7 @@
#[derive(Debug, Default)]
pub struct FuchsiaConfig {
pub fuchsia_build_dir: String,
+ pub zircon_build_dir: String,
pub fuchsia_arch: String,
}
@@ -221,8 +235,11 @@
let fx_exec_result =
Command::new(fx_script).args(args).current_dir(&fuchsia_dir).output()?;
let result = str::from_utf8(&fx_exec_result.stdout)?.trim().to_string();
- let mut config =
- FuchsiaConfig { fuchsia_build_dir: String::from(""), fuchsia_arch: String::from("") };
+ let mut config = FuchsiaConfig {
+ fuchsia_build_dir: String::from(""),
+ zircon_build_dir: String::from(""),
+ fuchsia_arch: String::from(""),
+ };
for one_line in result.lines() {
let parts: Vec<&str> = one_line.split("=").collect();
const QUOTE: char = '\'';
@@ -230,6 +247,9 @@
"FUCHSIA_BUILD_DIR" => {
config.fuchsia_build_dir = String::from(parts[1].trim_matches(QUOTE))
}
+ "ZIRCON_BUILDROOT" => {
+ config.zircon_build_dir = String::from(parts[1].trim_matches(QUOTE))
+ }
"FUCHSIA_ARCH" => config.fuchsia_arch = String::from(parts[1].trim_matches(QUOTE)),
_ => (),
}
diff --git a/src/utils.rs b/src/utils.rs
index bf942d9..bd7c0c1 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -4,7 +4,7 @@
use crate::sdk::strip_tool_path;
use failure::{bail, format_err, Error, ResultExt};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::Duration;
use uname::uname;
@@ -19,7 +19,7 @@
uname().expect("uname failed").sysname == "Darwin"
}
-pub fn strip_binary(binary: &PathBuf) -> Result<PathBuf, Error> {
+pub fn strip_binary(binary: &Path) -> Result<PathBuf, Error> {
let file_name = binary.file_name().ok_or(format_err!("file_name failed on {:#?}", binary))?;
let new_file_name = file_name.to_string_lossy().into_owned() + "_stripped";
let target_path = binary