diff --git a/scarb/src/ops/package.rs b/scarb/src/ops/package.rs index 7e4df4bda..45362c2a5 100644 --- a/scarb/src/ops/package.rs +++ b/scarb/src/ops/package.rs @@ -4,7 +4,7 @@ use std::io::{Seek, SeekFrom, Write}; use anyhow::{bail, ensure, Context, Result}; use camino::Utf8PathBuf; -use indoc::writedoc; +use indoc::{formatdoc, writedoc}; use scarb_ui::components::Status; use scarb_ui::{HumanBytes, HumanCount}; @@ -156,6 +156,20 @@ fn list_one_impl( } fn prepare_archive_recipe(pkg: &Package) -> Result { + ensure!( + pkg.manifest.targets.iter().any(|x| x.is_lib()), + formatdoc! { + r#" + package `{package_name}` does not provide a `[lib]` target. + if a package does not provide a library target, it cannot be used as a dependency. + help: add `[lib]` section to package manifest + --> Scarb.toml + + [lib] + "#, + package_name=pkg.id.name, + } + ); + let mut recipe = source_files(pkg)?; // Sort the recipe before any checks, to ensure generated errors are reproducible. diff --git a/scarb/tests/package.rs b/scarb/tests/package.rs index af015babf..2016ffac5 100644 --- a/scarb/tests/package.rs +++ b/scarb/tests/package.rs @@ -837,3 +837,31 @@ fn ignore_whitelist_pattern() { src/lib.cairo "#})); } + +#[test] +fn no_lib_target() { + let t = TempDir::new().unwrap(); + let name = "foo"; + let version = "1.0.0"; + ProjectBuilder::start() + .name(name) + .version(version) + .manifest_extra(indoc! {r#" + [[target.starknet-contract]] + "#}) + .build(&t); + + Scarb::quick_snapbox() + .arg("package") + .current_dir(&t) + .assert() + .failure() + .stdout_matches(formatdoc! {r#" + [..] Packaging {name} v{version} [..] + error: package `{name}` does not provide a `[lib]` target. + if a package does not provide a library target, it cannot be used as a dependency. + help: add `[lib]` section to package manifest + --> Scarb.toml + + [lib] + "#}); +}