Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ walkdir = "2.5.0"
fxhash = "0.2.1"
depfile = "0.1.1"
regex = "1.12.2"
cargo_metadata = "0.23.1"

[build-dependencies.cu]
workspace = true
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/cmds/cmd_build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ async fn run_build(args: CmdBuild) -> cu::Result<()> {
if lib_enabled && let Some(rust_ctx) = rust_ctx {
let rust_ctx =
rust_ctx.context("Rust is enabled, but cargo context could not be initialized")?;
rust_ctx.check_cxx_version()?;

if !args.configure {
need_link |= rust_ctx
Expand Down
62 changes: 60 additions & 2 deletions packages/cli/src/cmds/cmd_build/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
sync::Arc,
};

use cargo_metadata::{MetadataCommand, semver::Version};
use cu::pre::*;

use crate::env::environment;
Expand All @@ -19,6 +20,8 @@ pub struct RustCtx {
header_suffix: String,
}

static BLESSED_CXX_VERSION: &str = "1.0.194";

impl RustCtx {
/// Gets the crate based on the cargo config. Returns `None` if rust is
/// disabled or can't be automatically enabled. Returns Some(Err()) if
Expand Down Expand Up @@ -53,6 +56,8 @@ impl RustCtx {

let crate_root = manifest.parent().unwrap();

cu::debug!("checking cxx version");

let source_paths = sources
.iter()
.map(|rel_path| crate_root.join(rel_path))
Expand All @@ -69,6 +74,34 @@ impl RustCtx {
})
}

pub fn check_cxx_version(&self) -> cu::Result<()> {
let metadata = MetadataCommand::new()
.manifest_path(&self.manifest)
.exec()?;
let cxx = cu::check!(
metadata.packages.iter().find(|pack| pack.name == "cxx"),
"failed to find cxx package\ntry adding this line to your cargo dependencies: `cxx = \"={}\"`",
BLESSED_CXX_VERSION
)?;
let blessed_version = Version::parse(BLESSED_CXX_VERSION).unwrap();
if cxx.version < blessed_version {
cu::bail!(
"cxx version is older than the supported version; supported: {}, found: {} ",
blessed_version,
cxx.version
);
}
if cxx.version > blessed_version {
cu::warn!(
"cxx version is newer than the supported version; supported: {}, found: {}",
blessed_version,
cxx.version
);
}

Ok(())
}

pub fn has_build_script(&self) -> bool {
let script = self.manifest.parent().unwrap().join("build.rs");
script.exists()
Expand Down Expand Up @@ -261,6 +294,7 @@ async fn cxxbridge_process(
// Run the cxxbridge cmd and update the corresponding file if changed
// returns Ok(true) iff new code was generated and written
async fn cxxbridge_cmd(file: Option<&Path>, header: bool, output: &Path) -> cu::Result<bool> {
let env = environment();
let mut args = vec![];
if let Some(file) = file {
args.push(cu::check!(file.to_str(), "Not utf-8: {}", file.display())?);
Expand All @@ -269,8 +303,14 @@ async fn cxxbridge_cmd(file: Option<&Path>, header: bool, output: &Path) -> cu::
args.push("--header");
}

let exe = cu::which("cxxbridge")
.context("cxxbridge executable not found; `cargo install cxxbridge-cmd`")?;
let exe = env.cxxbridge();
if !exe.exists() {
cu::debug!("cxxbridge-cmd not installed, installing to MEGATON_HOME/bin");
install_cxxbridge(env.home())
.await
.context("Failed to install cxxbridge Make sure you are connected to the internet")?;
}

let command = exe
.command()
.stdout(cu::pio::buffer())
Expand Down Expand Up @@ -298,6 +338,24 @@ async fn cxxbridge_cmd(file: Option<&Path>, header: bool, output: &Path) -> cu::
}
}

async fn install_cxxbridge(dir: &Path) -> cu::Result<()> {
cu::fs::make_dir(dir)?;
let dir = dir.as_utf8()?;
let command = cu::which("cargo")?
.command()
.add(cu::args![
"install",
"--root",
dir,
"--no-track",
"-q", // suppress warning about adding ./bin to path
format!("cxxbridge-cmd@{BLESSED_CXX_VERSION}"),
])
.preset(cu::pio::cargo("Installing cxxbridge-cmd"));

command.co_spawn().await?.0.co_wait_nz().await
}

fn write_if_changed(path: &Path, bytes: &[u8]) -> cu::Result<bool> {
let changed = match cu::fs::read(path) {
Ok(existing) => existing != bytes,
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/src/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub struct Environment {
devkitpro: PathBuf,
dkp_version: String,
dkp_includes: Vec<String>,

cxxbridge: PathBuf,
}

impl Environment {
Expand All @@ -51,6 +53,8 @@ impl Environment {
.expect("Failed to init environment: check that DKP is installed correctly");
let dkp_includes = get_dkp_includes(&devkitpro, &dkp_version);

let cxxbridge = megaton_home.join("bin").join("cxxbridge");

Self {
megaton_home,
cc,
Expand All @@ -66,6 +70,7 @@ impl Environment {
devkitpro,
dkp_version,
dkp_includes,
cxxbridge,
}
}

Expand Down Expand Up @@ -112,6 +117,9 @@ impl Environment {
pub fn asm_version(&self) -> &str {
&self.asm_version
}
pub fn cxxbridge(&self) -> &Path {
&self.cxxbridge
}
}

fn get_dkp_version(dkp: &Path, cc: &Path) -> cu::Result<String> {
Expand Down
Loading