This commit is contained in:
Sebastian Moser
2026-10-23 15:27:31 +02:00
parent 9141fc5441
commit 37cb94d1d4
11 changed files with 482 additions and 63 deletions

8
Cargo.lock generated
View File

@@ -850,6 +850,14 @@ dependencies = [
"mize",
]
[[package]]
name = "mize-part-mos"
version = "0.1.0"
dependencies = [
"log",
"mize",
]
[[package]]
name = "mize_macros"
version = "0.1.0"

View File

@@ -56,7 +56,7 @@ pub fn opt(name: &str) -> crate::config::ConfigOptId {
let mut opts = mize.config_opts.lock().unwrap();
let id = cur_part.join(name).unwrap();
let opt = ConfigOpt {
name: name.to_owned(),
name: id.dot(),
val: None,
fun: None,
deps: Vec::new(),
@@ -65,13 +65,49 @@ pub fn opt(name: &str) -> crate::config::ConfigOptId {
ConfigOptId { id }
}
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData>>(_name: &str, _fun: F) {
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData>>(name: &str, fun: F) -> ConfigOptId {
let mize = get_global_mize().unwrap();
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
let mut opts = mize.config_opts.lock().unwrap();
let id = cur_part.join(name).unwrap();
let opt = ConfigOpt {
name: id.dot(),
val: Some(ItemData::from_native(fun)?),
fun: None,
deps: Vec::new(),
};
opts.insert(id.clone(), opt);
ConfigOptId { id }
}
pub fn effect<F: Fn(ItemData) -> MizeResult<ItemData>>(_name: &str, _fun: F) {
pub fn effect<F: Fn(ItemData) -> MizeResult<ItemData>>(_name: &str, _fun: F) -> ConfigOptId {
let mize = get_global_mize().unwrap();
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
let mut opts = mize.config_opts.lock().unwrap();
let id = cur_part.join(name).unwrap();
let opt = ConfigOpt {
name: id.dot(),
val: Some(ItemData::from_native(fun)?),
fun: None,
deps: Vec::new(),
};
opts.insert(id.clone(), opt);
ConfigOptId { id }
}
pub fn thread<F: Fn(ItemData) -> MizeResult<ItemData>>(_name: &str, _fun: F) {
pub fn thread<F: Fn(ItemData) -> MizeResult<ItemData>>(_name: &str, _fun: F) -> ConfigOptId {
let mize = get_global_mize().unwrap();
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
let mut opts = mize.config_opts.lock().unwrap();
let id = cur_part.join(name).unwrap();
let opt = ConfigOpt {
name: id.dot(),
val: Some(ItemData::from_native(fun)?),
fun: None,
deps: Vec::new(),
};
opts.insert(id.clone(), opt);
ConfigOptId { id }
}
type CFun = unsafe extern "C" fn (*mut ItemData) -> *mut ItemData;

View File

@@ -32,6 +32,14 @@ pub trait IntoMizeId {
}
impl MizeId {
pub fn dot(&self) -> String {
let path = self.path();
let mut new_path = Vec::new();
for el in path.iter() {
new_path.push(el.to_owned());
}
new_path.join(".")
}
pub fn join(&mut self, to_add: &str) -> MizeResult<MizeId> {
let path = self.path();
let mut new_path = Vec::new();

View File

@@ -235,7 +235,7 @@ impl Mize {
}
pub fn has_part(&mut self, name: &str) -> MizeResult<bool> {
let id = self.id_new_dots(name)?;
Ok(self.parts.lock().unwrap().contains_key(&id))
Ok(self.config_opts.lock().unwrap().contains_key(&id))
}
pub fn add_listener(
&mut self,
@@ -249,9 +249,6 @@ impl Mize {
Ok(())
}
fn part_names(&mut self) -> Vec<&'static str> {
self.part_names.lock().unwrap().clone()
}
pub fn init(&mut self) -> MizeResult<()> {
@@ -834,10 +831,11 @@ impl Mize {
}
pub fn dyn_call(&mut self, part_id: MizeId, method: &str, args: ItemData) -> MizeResult<ItemData> {
let mut parts = self.parts.lock()?;
let _part = parts.get_mut(&part_id).ok_or(mize_err!("part {part_id} is not loaded"))?;
println!("would be dyn_call ing from part, {:?}, {method}, {:?}", part_id, args);
Ok(ItemData::new())
let mut opts = self.config_opts.lock()?;
let part = opts.get_mut(&part_id).ok_or(mize_err!("part {} is not loaded", part_id.dot()))?;
let fun = part.val.ok_or(mize_err!("fun has no val"))?.native::<Fn(ItemData) -> MizeResult<ItemData>>()?;
println!("dyn_call ing from part, {:?}, {method}, {:?}", part_id, args);
fun(args)
}
pub fn get_part_gen<T: MizePart + Send + Sync + 'static>(

View File

@@ -356,8 +356,7 @@ impl ItemData {
/// The native value must have been stored via from_native().
/// Returns a guard that holds the lock on the native_values registry.
pub fn native<T: Any + Send + Sync + 'static>(&self) -> MizeResult<NativeRefGuard<T>> {
let mize_arc = crate::GLOBAL_MIZE.get().ok_or(mize_err!("No global Mize"))?;
let mize = mize_arc.lock().map_err(|_| mize_err!("Failed to lock global Mize"))?;
let mize = get_global_mize()?;
let native_values = mize.native_values.lock().map_err(|_| mize_err!("Failed to lock native_values"))?;
let id_data = self.get_path("_native")
@@ -389,8 +388,7 @@ impl ItemData {
/// The native value must have been stored via from_native().
/// Returns a guard that holds the lock on the native_values registry.
pub fn native_mut<T: Any + Send + Sync + 'static>(&self) -> MizeResult<NativeMutRefGuard<T>> {
let mize_arc = crate::GLOBAL_MIZE.get().ok_or(mize_err!("No global Mize"))?;
let mize = mize_arc.lock().map_err(|_| mize_err!("Failed to lock global Mize"))?;
let mize = get_global_mize()?;
let mut native_values = mize.native_values.lock().map_err(|_| mize_err!("Failed to lock native_values"))?;
let id_data = self.get_path("_native")
@@ -418,11 +416,18 @@ impl ItemData {
})
}
/// Get a clone of the native value stored in this ItemData.
/// The native value must have been stored via from_native().
/// This is useful when you need to pass the value by ownership (e.g., as a function argument).
pub fn native_clone<T: Any + Send + Sync + Clone + 'static>(&self) -> MizeResult<T> {
let guard = self.native::<T>()?;
Ok(guard.clone())
}
/// Take the native value from this ItemData, removing it from the registry.
/// The native value must have been stored via from_native().
pub fn native_take<T: Any + Send + Sync + 'static>(&self) -> MizeResult<T> {
let mize_arc = crate::GLOBAL_MIZE.get().ok_or(mize_err!("No global Mize"))?;
let mize = mize_arc.lock().map_err(|_| mize_err!("Failed to lock global Mize"))?;
let mize = get_global_mize()?;
let mut native_values = mize.native_values.lock().map_err(|_| mize_err!("Failed to lock native_values"))?;
let id_data = self.get_path("_native")

View File

@@ -21,6 +21,57 @@ pub fn write_to_mize_stdout(args: std::fmt::Arguments) -> MizeResult<()> {
Ok(())
}
/// Mize Shell (msh) macro - wraps command execution with nixpkgs executable resolution.
///
/// If the executable is given as a bare name (identifier), it is resolved via
/// [`msh_get_nix_bin`] to a nixpkgs store path. If it is given as a string literal
/// containing `/`, it is treated as a path and used as-is.
///
/// # Examples
/// ```ignore
/// msh!(git status)?; // resolves `git` from nixpkgs
/// msh!(curl https://example.com)?;
/// msh!("/usr/bin/git" status)?; // uses path directly
/// ```
#[macro_export]
macro_rules! msh {
// First token is a string literal — check if it's a path at runtime
($cmd:literal $($rest:tt)*) => {{
let cmd_str: &str = $cmd;
let resolved: String = if cmd_str.contains('/') {
cmd_str.to_string()
} else {
$crate::msh_get_nix_bin(cmd_str)
};
let mut cmd = ::std::process::Command::new(resolved);
$(cmd.arg(::std::stringify!($rest));)*
let status = cmd.status()?;
if status.success() {
::std::result::Result::Ok(())
} else {
::std::result::Result::Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
::std::format!("msh: command exited with {}", status),
))
}
}};
// First token is an identifier — always resolve via nixpkgs
($cmd:ident $($rest:tt)*) => {{
let resolved: String = $crate::msh_get_nix_bin(::std::stringify!($cmd));
let mut cmd = ::std::process::Command::new(resolved);
$(cmd.arg(::std::stringify!($rest));)*
let status = cmd.status()?;
if status.success() {
::std::result::Result::Ok(())
} else {
::std::result::Result::Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
::std::format!("msh: command exited with {}", status),
))
}
}};
}
pub mod prelude {
pub use super::*;
pub use instance::Mize;
@@ -97,6 +148,99 @@ pub extern "C" fn mize_rust_hack_set_global(mize: Arc<Mutex<Mize>>) {
let _ = GLOBAL_MIZE.set(mize);
}
/// Resolve an executable name to its full path in the nixpkgs store.
///
/// Reads `nix.pkgs.ref` (nixpkgs commit hash) and `nix.bin` (path to the `nix`
/// binary) from the Mize config, then runs:
///
/// ```text
/// <nix.bin> eval --raw nixpkgs/<hash>#<pkg>
/// ```
///
/// and returns `<outPath>/bin/<executable>`.
///
/// Certain executable names are mapped to different nixpkgs attribute names
/// via a hardcoded match (e.g. `npm` → `nodejs`).
///
/// # Panics
/// Panics if the global Mize instance is not set, the config values are missing,
/// or `nix eval` fails.
pub fn msh_get_nix_bin(name: &str) -> String {
// Hardcoded mapping of executable names to nixpkgs attribute names
let pkg = match name {
"npm" => "nodejs",
"node" => "nodejs",
"yarn" => "yarn",
"pnpm" => "nodePackages.pnpm",
_ => name,
};
let mut mize = get_global_mize().expect("msh_get_nix_bin: no global Mize instance set");
let nixpkgs_ref = mize
.get_config("nix.pkgs.ref")
.expect("msh_get_nix_bin: failed to get config nix.pkgs.ref")
.value_string()
.expect("msh_get_nix_bin: nix.pkgs.ref is not a string");
let nix_bin = mize
.get_config("nix.bin")
.expect("msh_get_nix_bin: failed to get config nix.bin")
.value_string()
.expect("msh_get_nix_bin: nix.bin is not a string");
// Run: nix eval --raw nixpkgs/<hash>#<pkg>
// --raw outputs just the store path without quotes
let attr = format!("nixpkgs/{}#{}", nixpkgs_ref, pkg);
let output = std::process::Command::new(&nix_bin)
.args(["eval", "--raw", &attr])
.output()
.expect("msh_get_nix_bin: failed to spawn nix eval");
if !output.status.success() {
panic!(
"msh_get_nix_bin: nix eval failed for {}: {}",
attr,
String::from_utf8_lossy(&output.stderr)
);
}
let out_path = String::from_utf8(output.stdout)
.expect("msh_get_nix_bin: nix eval output is not valid UTF-8")
.trim()
.to_string();
format!("{}/bin/{}", out_path, name)
}
/// Run a command with Mize Shell executable resolution.
///
/// This is the function-based equivalent of the [`msh!`] macro, with proper
/// argument handling (no `stringify!` limitations).
///
/// If `cmd` contains `/` it is treated as a path and used as-is.
/// Otherwise it is resolved via [`msh_get_nix_bin`].
///
/// Returns `Ok(())` if the command exits successfully, or an `io::Error` otherwise.
pub fn msh_run(cmd: &str, args: &[&str]) -> std::io::Result<()> {
let resolved = if cmd.contains('/') {
cmd.to_string()
} else {
msh_get_nix_bin(cmd)
};
let mut command = std::process::Command::new(resolved);
command.args(args);
let status = command.status()?;
if status.success() {
Ok(())
} else {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("msh: command exited with {}", status),
))
}
}
// platform specific stuff
pub mod platform {
use crate::{Mize, MizeResult};

View File

@@ -1,6 +1,6 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{self, parse::Parse, parse::ParseStream, Ident, LitStr, Token, TypePath};
use syn::{self, parse::Parse, parse::ParseStream, Ident, LitStr, Token, Type, TypePath};
use syn::punctuated::Punctuated;
use syn::token;
@@ -9,24 +9,76 @@ use syn::token;
//////////////////////////////////// include_native! macro ///////////////////////////////////////
/// A procedural macro to register methods and associated functions of a foreign type with mize.
///
/// Usage 1: Simplified syntax with method names
/// Usage 1: Simplified syntax with no-argument methods
/// ```ignore
/// include_native!("Command", clap::Command, [arg, subcommand]);
/// include_native!("Command", clap::Command, [get_name, is_empty]);
/// ```
///
/// Usage 2: With associated functions
/// Usage 2: With argument specifications
/// ```ignore
/// include_native!("Command", clap::Command, [
/// arg(arg: clap::Arg),
/// subcommand(cmd: clap::Command)
/// ]);
/// ```
///
/// Usage 3: Block syntax separating associated functions and methods
/// ```ignore
/// include_native!("Command", clap::Command, {
/// associated: [new],
/// methods: [arg, subcommand]
/// associated: [new(name: String)],
/// methods: [arg(arg: clap::Arg), subcommand(cmd: clap::Command)]
/// });
/// ```
/// A function specification: name or name(arg1: Type1, arg2: Type2, ...)
#[derive(Debug, Clone)]
struct FuncSpec {
name: Ident,
args: Vec<(Ident, Type)>,
}
impl Parse for FuncSpec {
fn parse(input: ParseStream) -> syn::Result<Self> {
let name: Ident = input.parse()?;
let mut args = Vec::new();
// Check for parentheses with arguments
if input.peek(syn::token::Paren) {
let content;
syn::parenthesized!(content in input);
// Parse comma-separated arg: Type pairs
while !content.is_empty() {
let arg_name: Ident = content.parse()?;
content.parse::<Token![:]>()?;
let arg_type: Type = content.parse()?;
args.push((arg_name, arg_type));
if !content.is_empty() {
content.parse::<Token![,]>()?;
}
}
}
Ok(FuncSpec { name, args })
}
}
/// Helper struct to parse a list of function specifications
struct FuncSpecList(Vec<FuncSpec>);
impl Parse for FuncSpecList {
fn parse(input: ParseStream) -> syn::Result<Self> {
let punctuated = Punctuated::<FuncSpec, Token![,]>::parse_terminated(input)?;
Ok(FuncSpecList(punctuated.into_iter().collect()))
}
}
/// Input for the simplified syntax: include_native!("name", Type, [method1, method2, ...])
struct IncludeNativeSimple {
name: LitStr,
type_path: TypePath,
methods: Punctuated<Ident, Token![,]>,
methods: Vec<FuncSpec>,
}
impl Parse for IncludeNativeSimple {
@@ -38,35 +90,18 @@ impl Parse for IncludeNativeSimple {
let content;
syn::bracketed!(content in input);
let methods = Punctuated::parse_terminated(&content)?;
let methods = content.parse::<FuncSpecList>()?.0;
Ok(IncludeNativeSimple { name, type_path, methods })
}
}
/// Helper struct to parse a list of identifiers
struct IdentList(Vec<Ident>);
impl Parse for IdentList {
fn parse(input: ParseStream) -> syn::Result<Self> {
let punctuated = Punctuated::<Ident, Token![,]>::parse_terminated(input)?;
Ok(IdentList(punctuated.into_iter().collect()))
}
}
/// Helper to parse a token stream as a list of identifiers (expects comma-separated idents)
fn parse_ident_list(stream: proc_macro2::TokenStream) -> Vec<Ident> {
syn::parse2::<IdentList>(stream)
.map(|list| list.0)
.unwrap_or_default()
}
/// Struct for parsing the block syntax with associated and methods
struct IncludeNativeBlock {
name: LitStr,
type_path: TypePath,
associated: Vec<Ident>,
methods: Vec<Ident>,
associated: Vec<FuncSpec>,
methods: Vec<FuncSpec>,
}
impl Parse for IncludeNativeBlock {
@@ -106,7 +141,9 @@ impl Parse for IncludeNativeBlock {
while j < tokens.len() {
if let proc_macro2::TokenTree::Group(g) = &tokens[j] {
if g.delimiter() == proc_macro2::Delimiter::Bracket {
associated = parse_ident_list(g.stream());
associated = syn::parse2::<FuncSpecList>(g.stream())
.map(|l| l.0)
.unwrap_or_default();
break;
}
}
@@ -130,7 +167,9 @@ impl Parse for IncludeNativeBlock {
while j < tokens.len() {
if let proc_macro2::TokenTree::Group(g) = &tokens[j] {
if g.delimiter() == proc_macro2::Delimiter::Bracket {
methods = parse_ident_list(g.stream());
methods = syn::parse2::<FuncSpecList>(g.stream())
.map(|l| l.0)
.unwrap_or_default();
break;
}
}
@@ -165,26 +204,47 @@ pub fn include_native(input: TokenStream) -> TokenStream {
syn::Error::new(
proc_macro2::Span::call_site(),
"Failed to parse include_native! input. Expected:\n \
include_native!(\"name\", Type, [method1, method2, ...])\n or\n \
include_native!(\"name\", Type, { associated: [func1], methods: [method1] })",
include_native!(\"name\", Type, [method1, method2(arg: Type), ...])\n or\n \
include_native!(\"name\", Type, { associated: [func1(arg: Type)], methods: [method1] })",
)
.to_compile_error()
.into()
}
/// Generate the argument extraction code for a function spec
fn generate_arg_extraction(args: &[(Ident, Type)]) -> Vec<proc_macro2::TokenStream> {
args.iter().enumerate().map(|(i, (arg_name, arg_type))| {
quote! {
let #arg_name = args.arr_nth(#i)?.native_clone::<#arg_type>()?;
}
}).collect()
}
/// Generate the argument passing code for a function call
fn generate_arg_passing(args: &[(Ident, Type)]) -> Vec<proc_macro2::TokenStream> {
args.iter().map(|(arg_name, _)| {
quote! { #arg_name }
}).collect()
}
fn expand_simple_include_native(simple: IncludeNativeSimple) -> TokenStream {
let name = simple.name;
let type_path = simple.type_path;
let methods = simple.methods;
let method_calls = methods.iter().map(|method| {
let method_name = method.to_string();
let method_name = method.name.to_string();
let method_ident = &method.name;
let arg_extractions = generate_arg_extraction(&method.args);
let arg_passings = generate_arg_passing(&method.args);
quote! {
.method(#method_name, |args| {
#(#arg_extractions)*
let this = mize::prelude::get_global_mize()?
.get_config(#name)?
.native_mut::<#type_path>()?;
let result = this.#method();
let result = this.#method_ident(#(#arg_passings),*);
Ok(mize::item::ItemData::from_native(result)?)
})
}
@@ -205,23 +265,33 @@ fn expand_block_include_native(block: IncludeNativeBlock) -> TokenStream {
let methods = block.methods;
let method_calls = methods.iter().map(|method| {
let method_name = method.to_string();
let method_name = method.name.to_string();
let method_ident = &method.name;
let arg_extractions = generate_arg_extraction(&method.args);
let arg_passings = generate_arg_passing(&method.args);
quote! {
.method(#method_name, |args| {
#(#arg_extractions)*
let this = mize::prelude::get_global_mize()?
.get_config(#name)?
.native_mut::<#type_path>()?;
let result = this.#method();
let result = this.#method_ident(#(#arg_passings),*);
Ok(mize::item::ItemData::from_native(result)?)
})
}
});
let associated_calls = associated.iter().map(|func| {
let func_name = func.to_string();
let func_name = func.name.to_string();
let func_ident = &func.name;
let arg_extractions = generate_arg_extraction(&func.args);
let arg_passings = generate_arg_passing(&func.args);
quote! {
.method(#func_name, |args| {
let result = <#type_path>::#func();
#(#arg_extractions)*
let result = <#type_path>::#func_ident(#(#arg_passings),*);
Ok(mize::item::ItemData::from_native(result)?)
})
}

View File

@@ -6,14 +6,10 @@ use mize::prelude::*;
#[unsafe(no_mangle)]
pub extern "C" fn part_cli() -> MizeResult<()> {
// Register methods of clap::Command with mize
// Note: associated functions like `new` require arguments, so they're not included here
// Use the block syntax to separate associated functions from methods:
// include_native!("Command", clap::Command, {
// associated: [some_associated_fn], // functions called as Type::fn()
// methods: [arg, subcommand] // methods called as this.fn()
// });
include_native!("Command", clap::Command, []);
include_native!("Command", clap::Command, {
associated: [new(name: String)],
//methods: [arg(arg: clap::Arg), subcommand(cmd: clap::Command)]
});
opt("state")
.fun(Box::new(|| {

21
parts/mos/Cargo.toml Normal file
View File

@@ -0,0 +1,21 @@
cargo-features = ["profile-rustflags"]
[package]
name = "mize-part-mos"
version = "0.1.0"
edition = "2024"
[lib]
name = "mize_part_mos"
crate-type = [ "cdylib", "rlib" ]
[dependencies]
log = "0.4.34"
mize = { workspace = true }
[profile.dev]
rustflags = ["-C", "prefer-dynamic", "-C", "link-args=-Wl,--export-dynamic"]
[profile.release]
rustflags = ["-C", "prefer-dynamic"]

View File

@@ -0,0 +1,70 @@
use mize::prelude::*;
pub struct CliPart {
id: MizeId
}
impl MizePart for CliPart {
fn id(&self) -> MizeId {
self.id.clone()
}
}
impl CliPart {
pub fn get(name: &str) -> MizeResult<CliPart> {
let mut mize = get_global_mize()?;
let part = mize.get_part(name)?;
Ok(CliPart { id: part.id() })
}
pub fn run(&self, cmdline: Vec<String>) -> MizeResult<()> {
let cmdline = cmdline.into_item_data();
let mut args = ItemData::new();
args.set_path("0", cmdline)?;
dyn_call(self.id.clone(), "run", args)?;
Ok(())
}
pub fn set_command(&self, name: &str) -> MizeResult<()> {
let name = name.into_item_data();
let mut args = ItemData::new();
args.set_path("0", name)?;
dyn_call(self.id.clone(), "set_command", args)?;
Ok(())
}
pub fn subcommand<T: Fn(ArgMatches) -> MizeResult<()> + Send + Sync + 'static>(&self, subcmd: Command, action: T) -> MizeResult<()> {
let mut subcmd_arg = ItemData::new();
subcmd_arg.set_path("_native", subcmd.native_id)?;
let mut action_arg = ItemData::from_native(action)?;
let mut args = ItemData::new();
args.set_path("0", subcmd_arg)?;
args.set_path("1", action_arg)?;
dyn_call(self.id.clone(), "subcommand", args)?;
Ok(())
}
}
// the clap::Command native stuff
pub struct Command {
native_id: u32
}
pub struct ArgMatches {
native_id: u32
}
pub struct Action {
native_id: u32
}
impl Command {
pub fn new(name: &str) -> MizeResult<Command> {
let name = name.into_item_data();
let mut args = ItemData::new();
args.set_path("0", name)?;
let mut mize = get_global_mize()?;
let id = mize.id_new_dots("cli.Command")?;
let data = dyn_call(id.clone(), "new", args)?;
let native_id: u32 = data.get_path("_native")?.native_take()?;
Ok(Command { native_id })
}
}

63
parts/mos/src/lib.rs Normal file
View File

@@ -0,0 +1,63 @@
use std::fs::create_dir_all;
use mize::prelude::*;
use cmd_lib::run_cmd as sh;
use mize::tracing::info;
// a static version of what would be generated.
// as we need mize.dev to generate anything.
mod generated;
use generated::*;
// spacetime gen command: sh!(RUST_LOG=error RUST_BACKTRACE=0 spacetime generate --build-options="--lint-dir=" -p $SRC/mize/marts/spacetime -o $SRC/mize/marts/generated/src/spacetime --lang rust)?;
#[unsafe(no_mangle)]
extern "C" fn part_dev() -> MizeResult<()> {
let mut mize = get_global_mize()?;
let mut cli = generated::CliPart::get("cli")?;
cli.set_command("dev");
cli.subcommand(Command::new("test")?, |_| {println!("hello from test command"); Ok(())})?;
//cli.subcommand(Command::new("publish").alias("p"), publish_mize)?;
//cli.subcommand(Command::new("genBindings").alias("b"), gen_bindings)?;
Ok(())
}
pub fn publish_mize(_ : &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mize_src = mize.get_config("mize.src")?.value_string()?;
let cargo_dir = std::env::home_dir().unwrap().join(".cargo");
let targets = vec![
"x86_64-pc-windows-gnu",
"aarch64-pc-windows-gnullvm",
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"armv7-unknown-linux-gnueabihf",
"arm-unknown-linux-gnueabi",
"aarch64-apple-darwin",
"x86_64-apple-darwin",
];
for target_name in targets {
let docker_image = match target_name {
"aarch64-apple-darwin" => "darwin",
"x86_64-apple-darwin" => "darwin",
_ => "base",
};
sh!(docker build -t mize-build-$docker_image $mize_src/parts/mize.dev/targets/$docker_image)?;
let res = sh!(docker run -it --rm -v $cargo_dir/registry:/usr/local/cargo/registry -v $cargo_dir/git:/usr/local/cargo/git -v $mize_src:/src -v $mize_src/target:/src/target mize-build-$docker_image cargo build --target $target_name --release);
if res.is_err() {
info!("build for {target_name} failed...");
}
};
Ok(())
}
pub fn gen_bindings(_ : &ArgMatches, mize: Mize) -> MizeResult<()> {
Ok(())
}