diff --git a/Cargo.toml b/Cargo.toml index 383c98db..c5c0d3da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ trycmd = "0.14" [dependencies] #qpm -qpm_package = { git = "https://github.com/QuestPackageManager/QPM.Package.git" } +qpm_package = { git = "https://github.com/QuestPackageManager/QPM.Package.git", tag = "v0.3.0"} qpm_qmod = { git = "https://github.com/QuestPackageManager/QPM.Qmod.git" } qpm_arg_tokenizer = { git = "https://github.com/QuestPackageManager/QPM.arg_tokenizer.git" } templatr = { git = "https://github.com/QuestPackageManager/templatr.git", optional = true } diff --git a/src/commands/install.rs b/src/commands/install.rs index 184ca954..1098d371 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -2,13 +2,12 @@ use std::path::PathBuf; use clap::Args; use color_eyre::eyre::Context; -use qpm_package::{ - extensions::package_metadata::PackageMetadataExtensions, - models::{dependency::SharedPackageConfig, package::PackageConfig}, -}; +use qpm_package::{models::{dependency::SharedPackageConfig, package::PackageConfig}, extensions::package_metadata::PackageMetadataExtensions}; use crate::{ - models::package::{PackageConfigExtensions, SharedPackageConfigExtensions}, + models::{ + package::{PackageConfigExtensions, SharedPackageConfigExtensions} + }, repository::{local::FileRepository, multi::MultiDependencyRepository}, }; @@ -17,6 +16,7 @@ use super::Command; #[derive(Args, Debug, Clone)] pub struct InstallCommand { pub binary_path: Option, + pub static_path: Option, pub debug_binary_path: Option, #[clap(long)] @@ -51,6 +51,7 @@ impl Command for InstallCommand { } let mut binary_path = self.binary_path; + let mut static_path = self.static_path; let mut debug_binary_path = self.debug_binary_path; let header_only = shared_package @@ -61,8 +62,7 @@ impl Command for InstallCommand { .unwrap_or(false); #[cfg(debug_assertions)] println!("Header only: {header_only}"); - - // TODO: Handle static library + if !header_only { if binary_path.is_none() && self.cmake_build.unwrap_or(true) { binary_path = Some( @@ -73,6 +73,15 @@ impl Command for InstallCommand { .canonicalize().context("Failed to retrieve release binary for publishing since it is not header only")?, ); } + if static_path.is_none() && self.cmake_build.unwrap_or(true) { + static_path = Some( + PathBuf::from(format!( + "./build/{}", + shared_package.config.info.get_static_name().file_name().unwrap().to_string_lossy() + )) + .canonicalize().context("Failed to retrieve release binary for publishing since it is not header only")?, + ); + } if debug_binary_path.is_none() && self.cmake_build.unwrap_or(true) { debug_binary_path = Some( @@ -103,6 +112,7 @@ impl Command for InstallCommand { PathBuf::from(".").canonicalize()?, binary_path, debug_binary_path, + static_path, true, true, )?; diff --git a/src/commands/publish/mod.rs b/src/commands/publish/mod.rs index e353033b..b83efa41 100644 --- a/src/commands/publish/mod.rs +++ b/src/commands/publish/mod.rs @@ -4,7 +4,10 @@ use owo_colors::OwoColorize; use qpm_package::models::{dependency::SharedPackageConfig, package::PackageConfig}; use crate::{ - models::{config::get_publish_keyring, package::PackageConfigExtensions}, + models::{ + config::get_publish_keyring, + package::{PackageConfigExtensions, SharedPackageConfigExtensions}, + }, repository::{qpackages::QPMRepository, Repository}, terminal::colors::QPMColor, }; @@ -28,6 +31,9 @@ impl Command for PublishCommand { let qpackages = QPMRepository::default(); let shared_package = SharedPackageConfig::read(".")?; + + shared_package.verify()?; + let resolved_deps = &shared_package.restored_dependencies; // check if all dependencies are available off of qpackages diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 4be8448e..1aab7819 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -82,6 +82,8 @@ impl Command for RestoreCommand { // write the ndk path to a file if available let _config = get_combine_config(); + shared_package.verify()?; + dependency::restore(".", &shared_package, &resolved_deps, &mut repo)?; shared_package.write(".")?; diff --git a/src/models/mod.rs b/src/models/mod.rs index 67db119c..1a6030ff 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -2,4 +2,5 @@ pub mod android_repo; pub mod config; pub mod mod_json; pub mod package; -pub mod toolchain; \ No newline at end of file +pub mod toolchain; +pub mod package_dependeny; diff --git a/src/models/package.rs b/src/models/package.rs index 17f88fc2..a82ced42 100644 --- a/src/models/package.rs +++ b/src/models/package.rs @@ -1,6 +1,9 @@ use std::{collections::HashSet, fs::File, io::BufReader, path::Path}; -use color_eyre::{eyre::Context, Result}; +use color_eyre::{ + eyre::{bail, Context}, + Result, +}; use itertools::Itertools; use qpm_package::{ extensions::package_metadata::PackageMetadataExtensions, @@ -44,6 +47,7 @@ pub trait SharedPackageConfigExtensions: Sized { fn to_mod_json(self) -> ModJson; fn try_write_toolchain(&self, repo: &impl Repository) -> Result<()>; + fn verify(&self) -> color_eyre::Result<()>; } impl PackageConfigExtensions for PackageConfig { @@ -284,6 +288,14 @@ impl SharedPackageConfigExtensions for SharedPackageConfig { } } + fn verify(&self) -> color_eyre::Result<()> { + if self.config.info.additional_data.static_linking.is_some() { + bail!("Using deprecated feature static_linking! Please remove!"); + } + + Ok(()) + } + fn try_write_toolchain(&self, repo: &impl Repository) -> Result<()> { let Some(toolchain_path) = self.config.info.additional_data.toolchain_out.as_ref() else { return Ok(()); diff --git a/src/models/package_dependeny.rs b/src/models/package_dependeny.rs new file mode 100644 index 00000000..5c679eb6 --- /dev/null +++ b/src/models/package_dependeny.rs @@ -0,0 +1,43 @@ +use qpm_package::models::{ + dependency::{Dependency, SharedDependency}, + extra::DependencyLibType, + package::{PackageConfig, PackageDependency}, +}; + +pub trait PackageDependencyExtensions { + fn infer_lib_type(&self, package: &PackageConfig) -> DependencyLibType; + + fn use_as_header_only(&self, package: &PackageConfig) -> bool; + fn use_as_static(&self, package: &PackageConfig) -> bool; + fn use_as_shared(&self, package: &PackageConfig) -> bool; +} + +impl PackageDependencyExtensions for PackageDependency { + fn infer_lib_type(&self, package: &PackageConfig) -> DependencyLibType { + let data = self.additional_data.clone(); + + let inferred = if package.info.additional_data.static_linking.is_some() + || package.info.additional_data.static_link.is_some() + { + DependencyLibType::Static + } else if package.info.additional_data.headers_only == Some(true) { + DependencyLibType::HeaderOnly + } else { + DependencyLibType::Shared + }; + + data.lib_type.unwrap_or(inferred) + } + + fn use_as_header_only(&self, package: &PackageConfig) -> bool { + self.infer_lib_type(package) == DependencyLibType::HeaderOnly + } + + fn use_as_static(&self, package: &PackageConfig) -> bool { + self.infer_lib_type(package) == DependencyLibType::Static + } + + fn use_as_shared(&self, package: &PackageConfig) -> bool { + self.infer_lib_type(package) == DependencyLibType::Shared + } +} diff --git a/src/repository/local.rs b/src/repository/local.rs index 39656873..a7bc5a5b 100644 --- a/src/repository/local.rs +++ b/src/repository/local.rs @@ -15,11 +15,17 @@ use std::{ use qpm_package::{ extensions::package_metadata::PackageMetadataExtensions, - models::{backend::PackageVersion, dependency::SharedPackageConfig, package::PackageConfig}, + models::{ + backend::PackageVersion, dependency::SharedPackageConfig, extra::DependencyLibType, + package::PackageConfig, + }, }; use crate::{ - models::{config::get_combine_config, package::PackageConfigExtensions}, + models::{ + config::get_combine_config, package::PackageConfigExtensions, + package_dependeny::PackageDependencyExtensions, + }, utils::{fs::copy_things, json}, }; @@ -84,6 +90,7 @@ impl FileRepository { project_folder: PathBuf, binary_path: Option, debug_binary_path: Option, + static_binary_path: Option, copy: bool, overwrite_existing: bool, ) -> Result<()> { @@ -93,6 +100,7 @@ impl FileRepository { project_folder, binary_path, debug_binary_path, + static_binary_path, false, )?; } @@ -106,6 +114,7 @@ impl FileRepository { project_folder: PathBuf, binary_path: Option, debug_binary_path: Option, + static_binary_path: Option, validate: bool, ) -> Result<()> { println!( @@ -130,9 +139,10 @@ impl FileRepository { fs::create_dir_all(&src_path).context("Failed to create lib path")?; - if binary_path.is_some() || debug_binary_path.is_some() { + if binary_path.is_some() || debug_binary_path.is_some() || static_binary_path.is_some() { let lib_path = cache_path.join("lib"); let so_path = lib_path.join(package.config.info.get_so_name()); + let static_path = lib_path.join(package.config.info.get_static_name()); let debug_so_path = lib_path.join(format!( "debug_{}", package @@ -151,6 +161,9 @@ impl FileRepository { if let Some(debug_binary_path_unwrapped) = &debug_binary_path { copy_things(debug_binary_path_unwrapped, &debug_so_path)?; } + if let Some(static_binary_path_unwrapped) = &static_binary_path { + copy_things(static_binary_path_unwrapped, &static_path)?; + } } let original_shared_path = project_folder.join(&package.config.shared_dir); @@ -343,6 +356,8 @@ impl FileRepository { .join(shared_dep.config.info.version.to_string()); let libs_path = dep_cache_path.join("lib"); + let lib_type_opt = referenced_dep.infer_lib_type(&shared_dep.config); + // skip header only deps if shared_dep .config @@ -350,31 +365,58 @@ impl FileRepository { .additional_data .headers_only .unwrap_or(false) + // if dependency is requested as header only + || lib_type_opt == DependencyLibType::HeaderOnly { + if referenced_dep + .additional_data + .lib_type + .as_ref() + .is_some_and(|t| *t != DependencyLibType::HeaderOnly) + { + eprintln!( + "Header only library {} is requested as {:?}", + shared_dep.config.info.id, lib_type_opt + ); + } continue; } // Not header only let data = &shared_dep.config.info.additional_data; - // get so name or release so name - let name = match data.debug_so_link.is_none() { - true => shared_dep - .config - .info - .get_so_name() - .file_name() - .unwrap() - .to_string_lossy() - .to_string(), - false => format!( - "debug_{}", - shared_dep - .config - .info - .get_so_name() - .file_name() - .unwrap() - .to_string_lossy() + + let name = match lib_type_opt { + // if has so link and is not using static_link + // use so name + DependencyLibType::Shared + if (data.debug_so_link.is_some() || data.so_link.is_some()) => + { + match data.debug_so_link.is_none() { + true => shared_dep.config.info.get_so_name(), + false => format!( + "debug_{}", + shared_dep + .config + .info + .get_so_name() + .file_name() + .unwrap() + .to_string_lossy() + ) + .into(), + } + } + // if dependency is static and has static_linking + DependencyLibType::Static + if data.static_linking.unwrap_or(false) && data.so_link.is_some() => + { + shared_dep.config.info.get_so_name().with_extension("a") + } + DependencyLibType::Static if data.static_link.is_some() => { + shared_dep.config.info.get_static_name() + } + _ => bail!( + "Attempting to use dependency as {lib_type_opt:?} but failed. Info: {data:?}" ), }; @@ -382,7 +424,8 @@ impl FileRepository { if !src_binary.exists() { bail!( - "Missing binary {name} for {}:{}", + "Missing binary {} for {}:{}", + name.file_name().unwrap().to_string_lossy(), referenced_dep.id, shared_dep.config.info.version ); @@ -390,7 +433,7 @@ impl FileRepository { paths.insert( src_binary, - extern_binaries.join(shared_dep.config.info.get_so_name()), + extern_binaries.join(name.file_name().unwrap().to_str()), ); } diff --git a/src/repository/qpackages.rs b/src/repository/qpackages.rs index e6a6e901..dd5f0e97 100644 --- a/src/repository/qpackages.rs +++ b/src/repository/qpackages.rs @@ -17,13 +17,14 @@ use zip::ZipArchive; use serde::Deserialize; -use qpm_package::{ - extensions::package_metadata::PackageMetadataExtensions, - models::{backend::PackageVersion, dependency::SharedPackageConfig, package::PackageConfig}, -}; +use qpm_package::{models::{ + backend::PackageVersion, dependency::SharedPackageConfig, package::PackageConfig, +}, extensions::package_metadata::PackageMetadataExtensions}; use crate::{ - models::{config::get_combine_config, package::PackageConfigExtensions}, + models::{ + config::get_combine_config, package::PackageConfigExtensions, + }, network::agent::{download_file_report, get_agent}, terminal::colors::QPMColor, utils::git, @@ -137,15 +138,8 @@ impl QPMRepository { } let so_path = lib_path.join(config.info.get_so_name()); - let debug_so_path = lib_path.join(format!( - "debug_{}", - config - .info - .get_so_name() - .file_name() - .unwrap() - .to_string_lossy() - )); + let static_path = lib_path.join(config.info.get_static_name()); + let debug_so_path = lib_path.join(format!("debug_{}", config.info.get_so_name().file_name().unwrap().to_string_lossy())); // Downloads the repo / zip file into src folder w/ subfolder taken into account if !src_path.exists() { @@ -285,6 +279,7 @@ impl QPMRepository { Ok(()) }; + download_binary(&static_path, config.info.additional_data.static_link.as_ref())?; download_binary(&so_path, config.info.additional_data.so_link.as_ref())?; download_binary( &debug_so_path, diff --git a/src/utils/cmake.rs b/src/utils/cmake.rs index 3f091547..e11f962e 100644 --- a/src/utils/cmake.rs +++ b/src/utils/cmake.rs @@ -5,10 +5,7 @@ use std::{ }; use color_eyre::{eyre::Context, Result}; -use qpm_package::{ - extensions::package_metadata::PackageMetadataExtensions, - models::dependency::SharedPackageConfig, -}; +use qpm_package::{models::dependency::SharedPackageConfig, extensions::package_metadata::PackageMetadataExtensions}; use crate::repository::Repository; use std::fmt::Write as OtherWrite;