Skip to content

Commit

Permalink
Merge pull request #471 from moonbitlang/moon_query
Browse files Browse the repository at this point in the history
support moon query
  • Loading branch information
Young-Flash authored Nov 21, 2024
2 parents 5e297d6 + 9b5edc6 commit 18cc624
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 0 deletions.
4 changes: 4 additions & 0 deletions crates/moon/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod info;
pub mod mooncake_adapter;
pub mod new;
mod pre_build;
pub mod query;
pub mod run;
pub mod shell_completion;
pub mod test;
Expand All @@ -51,6 +52,7 @@ pub use generate_test_driver::*;
pub use info::*;
use moonbuild::upgrade::UpgradeSubcommand;
pub use new::*;
pub use query::*;
pub use run::*;
pub use shell_completion::*;
pub use test::*;
Expand Down Expand Up @@ -117,6 +119,8 @@ pub enum MoonBuildSubcommands {
// Misc
Coverage(CoverageSubcommand),
GenerateBuildMatrix(GenerateBuildMatrix),
#[clap(hide = true)]
Query(QuerySubcommand),

/// Upgrade toolchains
Upgrade(UpgradeSubcommand),
Expand Down
18 changes: 18 additions & 0 deletions crates/moon/src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ pub struct BuildSubcommand {
/// Monitor the file system and automatically build artifacts
#[clap(long, short)]
pub watch: bool,

#[clap(long, hide = true)]
pub show_artifacts: bool,
}

pub fn run_build(cli: &UniversalFlags, cmd: &BuildSubcommand) -> anyhow::Result<i32> {
Expand Down Expand Up @@ -193,5 +196,20 @@ fn run_build_internal(
trace::close();
}

if let (Ok(_), true) = (res.as_ref(), cmd.show_artifacts) {
// can't use HashMap because the order of the packages is not guaranteed
// can't use IndexMap because moonc cannot handled ordered map
let mut artifacts = Vec::new();
for pkg in module
.get_topo_pkgs()?
.iter()
.filter(|pkg| !pkg.is_third_party)
{
let mi = pkg.artifact.with_extension("mi");
let core = pkg.artifact.with_extension("core");
artifacts.push((pkg.full_name(), mi, core));
}
println!("{}", serde_json::to_string(&artifacts).unwrap());
}
res
}
85 changes: 85 additions & 0 deletions crates/moon/src/cli/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// moon: The build system and package manager for MoonBit.
// Copyright (C) 2024 International Digital Economy Academy
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn.

use moonutil::{cli::UniversalFlags, common::DEP_PATH};

use super::BuildFlags;

#[derive(Debug, clap::Parser, Clone)]
pub struct QuerySubcommand {
#[clap(flatten)]
pub build_flags: BuildFlags,

pub mod_name: String,
}

pub fn run_query(_cli: UniversalFlags, cmd: QuerySubcommand) -> anyhow::Result<i32> {
let temp_dir = std::env::temp_dir();
let moon_repl_dir = temp_dir.join("moon_repl");

if !moon_repl_dir.exists() {
std::fs::create_dir_all(&moon_repl_dir)?;
}

let mod_json_path = moon_repl_dir.join("moon.mod.json");
if !mod_json_path.exists() {
let mod_json_content = r#"{
"name": "moon/repl",
"version": "0.0.1"
}"#;
std::fs::write(mod_json_path, mod_json_content)?;
}

let mod_name = cmd.mod_name;

let moon_path = std::env::current_exe()
.map_or_else(|_| "moon".into(), |x| x.to_string_lossy().into_owned());

let moon_add_output = std::process::Command::new(&moon_path)
.arg("add")
.arg(&mod_name)
.arg("--source-dir")
.arg(moon_repl_dir.to_str().unwrap())
.output()?;

if !moon_add_output.status.success() {
eprintln!("{}", String::from_utf8_lossy(&moon_add_output.stdout));
eprintln!("{}", String::from_utf8_lossy(&moon_add_output.stderr));
anyhow::bail!("Failed to add module {}", mod_name);
}

let moon_build_output = std::process::Command::new(&moon_path)
.arg("build")
.arg("--source-dir")
.arg(
moon_repl_dir
.join(DEP_PATH)
.join(&mod_name)
.to_str()
.unwrap(),
)
.arg("--show-artifacts")
.output()?;

println!("{}", String::from_utf8_lossy(&moon_build_output.stdout));
if !moon_build_output.status.success() {
anyhow::bail!("Failed to build module {}", mod_name);
}

Ok(0)
}
1 change: 1 addition & 0 deletions crates/moon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ fn main1() -> anyhow::Result<i32> {
New(n) => cli::run_new(&flags, n),
Publish(p) => cli::mooncake_adapter::publish_cli(flags, p),
Package(p) => cli::mooncake_adapter::package_cli(flags, p),
Query(q) => cli::run_query(flags, q),
Register(r) => cli::mooncake_adapter::register_cli(flags, r),
Remove(r) => cli::remove_cli(flags, r),
Run(r) => cli::run_run(&flags, r),
Expand Down
16 changes: 16 additions & 0 deletions crates/moon/tests/test_cases/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7966,3 +7966,19 @@ fn test_run_doc_test() {
"#]],
);
}

#[cfg(unix)]
#[test]
fn test_moon_query() {
let dir = TestDir::new("test_filter_pkg_with_test_imports.in");

check(
get_stdout(&dir, ["build", "--show-artifacts"]),
// need topological order
expect![[r#"
[["username/hello/lib6","$ROOT/target/wasm-gc/release/build/lib6/lib6.mi","$ROOT/target/wasm-gc/release/build/lib6/lib6.core"],["username/hello/lib7","$ROOT/target/wasm-gc/release/build/lib7/lib7.mi","$ROOT/target/wasm-gc/release/build/lib7/lib7.core"],["username/hello/lib3","$ROOT/target/wasm-gc/release/build/lib3/lib3.mi","$ROOT/target/wasm-gc/release/build/lib3/lib3.core"],["username/hello/lib1","$ROOT/target/wasm-gc/release/build/lib1/lib1.mi","$ROOT/target/wasm-gc/release/build/lib1/lib1.core"],["username/hello/lib5","$ROOT/target/wasm-gc/release/build/lib5/lib5.mi","$ROOT/target/wasm-gc/release/build/lib5/lib5.core"],["username/hello/lib4","$ROOT/target/wasm-gc/release/build/lib4/lib4.mi","$ROOT/target/wasm-gc/release/build/lib4/lib4.core"],["username/hello/lib2","$ROOT/target/wasm-gc/release/build/lib2/lib2.mi","$ROOT/target/wasm-gc/release/build/lib2/lib2.core"],["username/hello/lib","$ROOT/target/wasm-gc/release/build/lib/lib.mi","$ROOT/target/wasm-gc/release/build/lib/lib.core"],["username/hello/main","$ROOT/target/wasm-gc/release/build/main/main.mi","$ROOT/target/wasm-gc/release/build/main/main.core"]]
"#]],
);

get_stdout(&dir, ["query", "moonbitlang/x"]);
}
40 changes: 40 additions & 0 deletions crates/moonutil/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ impl ModuleDB {
self.packages.values().find(|it| it.root_path == path)
}

pub fn get_topo_pkgs(&self) -> anyhow::Result<Vec<&Package>> {
use petgraph::graph::NodeIndex;

let mut graph = DiGraph::<String, usize>::new();
let mut name_to_idx: IndexMap<String, NodeIndex> = IndexMap::new();
let mut idx_to_name = IndexMap::new();

for (to_node, pkg) in self.packages.iter() {
if !name_to_idx.contains_key(to_node) {
let to_idx = graph.add_node(to_node.clone());
name_to_idx.insert(to_node.clone(), to_idx);
idx_to_name.insert(to_idx, to_node.clone());
}

let to_idx = name_to_idx[to_node];

for dep in pkg.imports.iter() {
let from_node = dep.path.make_full_path();
if !name_to_idx.contains_key(&from_node) {
let to_idx = graph.add_node(from_node.clone());
name_to_idx.insert(from_node.clone(), to_idx);
idx_to_name.insert(to_idx, from_node.clone());
}
let from_idx = name_to_idx[&from_node];
graph.add_edge(from_idx, to_idx, 0);
}
}

let topo_pkgs = match petgraph::algo::toposort(&graph, None) {
Ok(res) => res
.into_iter()
.map(|idx| self.get_package_by_name(idx_to_name[&idx].as_str()))
.collect::<Vec<_>>(),
Err(cycle) => {
bail!("cyclic dependency detected: {:?}", cycle);
}
};
Ok(topo_pkgs)
}

pub fn get_package_by_path_mut(&mut self, path: &Path) -> Option<&mut Package> {
self.packages
.iter_mut()
Expand Down

0 comments on commit 18cc624

Please sign in to comment.