Skip to main content

cargo_fmi/
lib.rs

1#![doc = include_str!("../README.md")]
2//! ## Feature flags
3#![deny(clippy::all)]
4
5use clap::{Parser, Subcommand, ValueEnum};
6use std::ffi::OsString;
7
8mod builder;
9mod bundle;
10mod extractor;
11mod info;
12mod inspect;
13mod metadata;
14mod new;
15mod packager;
16
17#[derive(Parser, Debug)]
18#[command(name = "cargo-fmi", bin_name = "cargo-fmi")]
19#[command(about = "Cargo subcommand for FMI packaging and tooling")]
20struct Cli {
21    /// Default package to operate on (can be specified before or after subcommand)
22    #[arg(short = 'p', long = "package", global = true)]
23    package: Option<String>,
24    #[command(subcommand)]
25    command: Commands,
26}
27
28#[derive(Subcommand, Debug)]
29enum Commands {
30    /// Create a new FMI-export capable project (wrapper around cargo new)
31    New {
32        /// Path for the new package
33        #[arg(value_name = "PATH")]
34        path: std::path::PathBuf,
35        /// Override the package name
36        #[arg(long)]
37        name: Option<String>,
38    },
39    /// Bundle a package as an FMU for single platform
40    Bundle {
41        /// Name of the package
42        #[arg(short = 'p', long = "package")]
43        package: Option<String>,
44        /// Target platform(s) (e.g., x86_64-unknown-linux-gnu), can be specified multiple times
45        #[arg(long)]
46        target: Option<Vec<String>>,
47        /// Build in release mode
48        #[arg(long, default_value_t = false)]
49        release: bool,
50    },
51    /// Inspect a packaged FMU (.fmu)
52    Inspect {
53        /// Path to the FMU file to inspect
54        #[arg(value_name = "FMU_PATH")]
55        fmu: std::path::PathBuf,
56        /// Output format for inspection results
57        #[arg(long, value_enum, default_value_t = InspectFormat::ModelDescription)]
58        format: InspectFormat,
59    },
60    /// Print the model description struct for a package
61    Info {
62        /// Name of the package
63        #[arg(short = 'p', long = "package")]
64        package: Option<String>,
65        /// Target platform(s) (e.g., x86_64-unknown-linux-gnu), can be specified multiple times
66        #[arg(long)]
67        target: Option<Vec<String>>,
68        /// Build in release mode
69        #[arg(long, default_value_t = false)]
70        release: bool,
71    },
72}
73
74#[derive(Clone, Debug, ValueEnum)]
75enum InspectFormat {
76    /// Emit the full modelDescription.xml
77    ModelDescription,
78    /// Emit debug output for all other FMU contents
79    Debug,
80}
81
82pub fn entrypoint() -> anyhow::Result<()> {
83    entrypoint_from(std::env::args_os())
84}
85
86pub fn entrypoint_from<I, T>(args: I) -> anyhow::Result<()>
87where
88    I: IntoIterator<Item = T>,
89    T: Into<OsString> + Clone,
90{
91    flexi_logger::Logger::try_with_env_or_str("info")?
92        .set_palette("b1;3;2;4;6".to_string())
93        .start()?;
94
95    let Cli {
96        command,
97        package: global_package,
98    } = Cli::parse_from(args);
99
100    match command {
101        Commands::New { path, name } => new::new_project(new::NewArgs { path, name })?,
102        Commands::Bundle {
103            package,
104            target,
105            release,
106        } => bundle::bundle(&package.or(global_package), &target, release)?,
107        Commands::Inspect { fmu, format } => inspect::inspect(&fmu, format)?,
108        Commands::Info {
109            package,
110            target,
111            release,
112        } => info::info(&package.or(global_package), &target, release)?,
113    }
114
115    Ok(())
116}