diff --git a/src/generator/msvc.rs b/src/generator/msvc.rs index 9c53f64..b6b939c 100644 --- a/src/generator/msvc.rs +++ b/src/generator/msvc.rs @@ -468,19 +468,24 @@ impl Msvc { Self::generate_inner(subproject, proj_opts, targets)?; } - for lib in &project.static_libraries { - if !targets.contains_key(&as_key(lib)) { - add_static_lib(lib, proj_opts, targets)?; - } - } - for lib in &project.object_libraries { - if !targets.contains_key(&as_key(lib)) { - add_object_lib(lib, proj_opts, targets)?; - } - } - for lib in &project.shared_libraries { - if !targets.contains_key(&as_key(lib)) { - add_shared_lib(lib, proj_opts, targets)?; + for lib in &project.link_targets { + match lib { + LinkPtr::Static(lib) => { + if !targets.contains_key(&as_key(lib)) { + add_static_lib(lib, proj_opts, targets)?; + } + } + LinkPtr::Object(lib) => { + if !targets.contains_key(&as_key(lib)) { + add_object_lib(lib, proj_opts, targets)?; + } + } + LinkPtr::Interface(_) => {} + LinkPtr::Shared(lib) => { + if !targets.contains_key(&as_key(lib)) { + add_shared_lib(lib, proj_opts, targets)?; + } + } } } for exe in &project.executables { diff --git a/src/generator/ninja.rs b/src/generator/ninja.rs index 72b560b..9afa7cf 100644 --- a/src/generator/ninja.rs +++ b/src/generator/ninja.rs @@ -385,27 +385,28 @@ impl Ninja { Ninja::generate_inner(subproject, generator_opts, rules, build_lines, link_targets)?; } - for lib in &project.static_libraries { - if !link_targets.contains_key(&LinkPtr::Static(lib.clone())) { - add_static_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; - } - } - - for lib in &project.object_libraries { - if !link_targets.contains_key(&LinkPtr::Object(lib.clone())) { - add_object_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; + for lib in &project.link_targets { + match lib { + LinkPtr::Static(lib) => { + if !link_targets.contains_key(&LinkPtr::Static(lib.clone())) { + add_static_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; + } + } + LinkPtr::Object(lib) => { + if !link_targets.contains_key(&LinkPtr::Object(lib.clone())) { + add_object_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; + } + } + LinkPtr::Interface(lib) => { + let key = LinkPtr::Interface(lib.clone()); + link_targets.entry(key).or_default(); + } + LinkPtr::Shared(lib) => { + add_shared_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; + } } } - for lib in &project.interface_libraries { - let key = LinkPtr::Interface(lib.clone()); - link_targets.entry(key).or_default(); - } - - for lib in &project.shared_libraries { - add_shared_lib_target(lib, generator_opts, rules, build_lines, link_targets)?; - } - for exe in &project.executables { add_executable_target(exe, generator_opts, rules, build_lines, link_targets)?; } @@ -1271,10 +1272,7 @@ fn test_position_independent_code() { generator_vars: None, output_name: None, })], - static_libraries: vec![create_lib(weak_parent)], - object_libraries: Vec::new(), - interface_libraries: Vec::new(), - shared_libraries: Vec::new(), + link_targets: vec![LinkPtr::Static(create_lib(weak_parent))], }); let toolchain = Toolchain { msvc_platforms: vec!["x64".to_owned(), "Win32".to_owned(), "ARM64".to_owned()], diff --git a/src/generator/xcode.rs b/src/generator/xcode.rs index f06b361..86b34dc 100644 --- a/src/generator/xcode.rs +++ b/src/generator/xcode.rs @@ -1115,92 +1115,95 @@ fn project_targets( let mut native_target_keys = Vec::new(); let mut external_projects = HashMap::::new(); - for lib in &project.object_libraries { - let key = new_native_target_archive( - lib.as_ref(), - &lib.sources, - &lib.generator_vars, - native_target_build_configs, - toolchain, - graph, - id_gen, - global_targets, - &mut external_projects, - build_dir, - )?; - let nt = graph.native_targets.get(&key).unwrap(); - let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); - global_targets.insert( - as_key(lib), - GlobalTargetMeta { - project_info: project.info.clone(), - native_target_id: nt.id.clone(), - product_reference_id: prod_ref.id.clone(), - target_name: nt.name.clone(), - product_name: nt.product_name.clone(), - local_key: key, - product_kind: XcodeProductKind::StaticArchive, - }, - ); - native_target_keys.push(key); - } - - for lib in &project.static_libraries { - let key = new_native_target_archive( - lib.as_ref(), - &lib.sources, - &lib.generator_vars, - native_target_build_configs, - toolchain, - graph, - id_gen, - global_targets, - &mut external_projects, - build_dir, - )?; - let nt = graph.native_targets.get(&key).unwrap(); - let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); - global_targets.insert( - as_key(lib), - GlobalTargetMeta { - project_info: project.info.clone(), - native_target_id: nt.id.clone(), - product_reference_id: prod_ref.id.clone(), - target_name: nt.name.clone(), - product_name: nt.product_name.clone(), - local_key: key, - product_kind: XcodeProductKind::StaticArchive, - }, - ); - native_target_keys.push(key); - } - - for lib in &project.shared_libraries { - let key = new_native_target_shared( - lib, - native_target_build_configs, - toolchain, - graph, - id_gen, - global_targets, - &mut external_projects, - build_dir, - )?; - let nt = graph.native_targets.get(&key).unwrap(); - let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); - global_targets.insert( - as_key(lib), - GlobalTargetMeta { - project_info: project.info.clone(), - native_target_id: nt.id.clone(), - product_reference_id: prod_ref.id.clone(), - target_name: nt.name.clone(), - product_name: nt.product_name.clone(), - local_key: key, - product_kind: XcodeProductKind::DynamicLibrary, - }, - ); - native_target_keys.push(key); + for lib in &project.link_targets { + match lib { + LinkPtr::Static(lib) => { + let key = new_native_target_archive( + lib.as_ref(), + &lib.sources, + &lib.generator_vars, + native_target_build_configs, + toolchain, + graph, + id_gen, + global_targets, + &mut external_projects, + build_dir, + )?; + let nt = graph.native_targets.get(&key).unwrap(); + let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); + global_targets.insert( + as_key(lib), + GlobalTargetMeta { + project_info: project.info.clone(), + native_target_id: nt.id.clone(), + product_reference_id: prod_ref.id.clone(), + target_name: nt.name.clone(), + product_name: nt.product_name.clone(), + local_key: key, + product_kind: XcodeProductKind::StaticArchive, + }, + ); + native_target_keys.push(key); + } + LinkPtr::Object(lib) => { + let key = new_native_target_archive( + lib.as_ref(), + &lib.sources, + &lib.generator_vars, + native_target_build_configs, + toolchain, + graph, + id_gen, + global_targets, + &mut external_projects, + build_dir, + )?; + let nt = graph.native_targets.get(&key).unwrap(); + let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); + global_targets.insert( + as_key(lib), + GlobalTargetMeta { + project_info: project.info.clone(), + native_target_id: nt.id.clone(), + product_reference_id: prod_ref.id.clone(), + target_name: nt.name.clone(), + product_name: nt.product_name.clone(), + local_key: key, + product_kind: XcodeProductKind::StaticArchive, + }, + ); + native_target_keys.push(key); + } + LinkPtr::Shared(lib) => { + let key = new_native_target_shared( + lib, + native_target_build_configs, + toolchain, + graph, + id_gen, + global_targets, + &mut external_projects, + build_dir, + )?; + let nt = graph.native_targets.get(&key).unwrap(); + let prod_ref = graph.file_references.get(&nt.product_reference).unwrap(); + global_targets.insert( + as_key(lib), + GlobalTargetMeta { + project_info: project.info.clone(), + native_target_id: nt.id.clone(), + product_reference_id: prod_ref.id.clone(), + target_name: nt.name.clone(), + product_name: nt.product_name.clone(), + local_key: key, + product_kind: XcodeProductKind::DynamicLibrary, + }, + ); + native_target_keys.push(key); + } + LinkPtr::Interface(_) => {} + } } for exe in &project.executables { @@ -2443,10 +2446,11 @@ fn test_pbxproj_generation() { }), dependencies: Vec::new(), executables: vec![exe], - static_libraries: vec![adder], - object_libraries: vec![subtracter], - interface_libraries: vec![arithmetic], - shared_libraries: Vec::new(), + link_targets: vec![ + LinkPtr::Object(subtracter.clone()), + LinkPtr::Static(adder.clone()), + LinkPtr::Interface(arithmetic.clone()), + ], } }); @@ -2552,10 +2556,7 @@ fn test_xcode_transform() { }), dependencies: Vec::new(), executables: vec![exe], - static_libraries: vec![adder], - object_libraries: Vec::new(), - interface_libraries: vec![iface], - shared_libraries: Vec::new(), + link_targets: vec![LinkPtr::Static(adder.clone()), LinkPtr::Interface(iface.clone())], } }); diff --git a/src/lib.rs b/src/lib.rs index c90f298..1d3e0be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ mod executable; pub mod generator; mod interface_library; -mod link_type; +pub mod link_type; mod misc; mod object_library; pub mod project; @@ -37,8 +37,7 @@ use reqwest::StatusCode; use serde::Deserialize; use starlark::{ environment::{ - Globals, // - GlobalsBuilder, + GlobalsBuilder, // Module, }, eval::Evaluator, diff --git a/src/object_library.rs b/src/object_library.rs index 6f6f1f6..35e3337 100644 --- a/src/object_library.rs +++ b/src/object_library.rs @@ -233,22 +233,20 @@ mod tests { info: Arc::new(crate::project::ProjectInfo { name: "test".to_owned(), path: PathBuf::from(".") }), dependencies: Vec::new(), executables: Vec::new(), - static_libraries: vec![ - leaf_shared, - leaf_pub_pub, - leaf_pub_priv, - leaf_priv_pub, - leaf_priv_priv, - mid_pub, - mid_priv, + link_targets: vec![ + LinkPtr::Object(main_lib.clone()), + LinkPtr::Static(leaf_shared.clone()), + LinkPtr::Static(leaf_pub_pub.clone()), + LinkPtr::Static(leaf_pub_priv.clone()), + LinkPtr::Static(leaf_priv_pub.clone()), + LinkPtr::Static(leaf_priv_priv.clone()), + LinkPtr::Static(mid_pub.clone()), + LinkPtr::Static(mid_priv.clone()), ], - object_libraries: vec![main_lib], - interface_libraries: Vec::new(), - shared_libraries: Vec::new(), } }); - let main_lib = project.object_libraries.iter().find(|x| x.name == "main_lib").unwrap(); + let main_lib = project.link_targets.iter().find(|x| x.name() == "main_lib").unwrap(); let internal_includes = main_lib.internal_includes(); diff --git a/src/project.rs b/src/project.rs index a45049f..cbb51f9 100644 --- a/src/project.rs +++ b/src/project.rs @@ -5,10 +5,7 @@ use std::{ use crate::{ executable::Executable, // - interface_library::InterfaceLibrary, - object_library::ObjectLibrary, - shared_library::SharedLibrary, - static_library::StaticLibrary, + link_type::LinkPtr, }; #[derive(Debug)] @@ -22,8 +19,5 @@ pub struct Project { pub info: Arc, pub dependencies: Vec>, pub executables: Vec>, - pub static_libraries: Vec>, - pub object_libraries: Vec>, - pub interface_libraries: Vec>, - pub shared_libraries: Vec>, + pub link_targets: Vec, } diff --git a/src/starlark_api.rs b/src/starlark_api.rs index 22964e5..dba0579 100644 --- a/src/starlark_api.rs +++ b/src/starlark_api.rs @@ -19,7 +19,7 @@ use starlark::{ use crate::{ starlark_executable::{StarExecutable, StarExecutableWrapper}, starlark_interface_library::{StarIfaceLibWrapper, StarIfaceLibrary}, - starlark_link_target::StarLinkTarget, + starlark_link_target::{StarLinkTarget, StarLinkTargetRef}, starlark_object_library::{StarGeneratorVars, StarObjLibWrapper, StarObjectLibrary}, starlark_project::StarProject, starlark_shared_library::{StarSharedLibWrapper, StarSharedLibrary}, @@ -131,7 +131,7 @@ pub(crate) fn build_api(builder: &mut GlobalsBuilder) { output_name: None, // TODO(Travers) }); let mut project = state.project.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?; - project.static_libraries.push(lib.clone()); + project.link_targets.push(StarLinkTargetRef::Static(lib.clone())); Ok(StarStaticLibWrapper(lib)) } @@ -168,7 +168,7 @@ pub(crate) fn build_api(builder: &mut GlobalsBuilder) { output_name: None, // TODO(Travers) }); let mut project = state.project.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?; - project.object_libraries.push(lib.clone()); + project.link_targets.push(StarLinkTargetRef::Object(lib.clone())); Ok(StarObjLibWrapper(lib)) } @@ -196,7 +196,7 @@ pub(crate) fn build_api(builder: &mut GlobalsBuilder) { // generator_vars: generator_func(generator_vars, eval)?, }); let mut project = state.project.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?; - project.interface_libraries.push(lib.clone()); + project.link_targets.push(StarLinkTargetRef::Interface(lib.clone())); Ok(StarIfaceLibWrapper(lib)) } @@ -233,7 +233,7 @@ pub(crate) fn build_api(builder: &mut GlobalsBuilder) { output_name: None, // TODO(Travers) }); let mut project = state.project.lock().map_err(|e| anyhow::anyhow!(e.to_string()))?; - project.shared_libraries.push(lib.clone()); + project.link_targets.push(StarLinkTargetRef::Shared(lib.clone())); Ok(StarSharedLibWrapper(lib)) } diff --git a/src/starlark_interface_library.rs b/src/starlark_interface_library.rs index 94d370f..f987fc3 100644 --- a/src/starlark_interface_library.rs +++ b/src/starlark_interface_library.rs @@ -76,8 +76,7 @@ impl StarLinkTarget for StarIfaceLibrary { ) -> Result { let data = self.as_library(parent, parent_path, link_map, gen_name_map)?; let arc = Arc::new(data); - // let ptr = PtrLinkTarget(arc.clone()); - link_map.insert_interface(ptr, arc.clone()); + link_map.insert(ptr, LinkPtr::Interface(arc.clone())); Ok(LinkPtr::Interface(arc)) } diff --git a/src/starlark_link_target.rs b/src/starlark_link_target.rs index 280967f..7fad5e2 100644 --- a/src/starlark_link_target.rs +++ b/src/starlark_link_target.rs @@ -11,7 +11,11 @@ use starlark::values::OwnedFrozenValue; use super::{ link_type::LinkPtr, project::Project, // + starlark_interface_library::StarIfaceLibrary, + starlark_object_library::StarObjectLibrary, starlark_project::StarLinkTargetCache, + starlark_shared_library::StarSharedLibrary, + starlark_static_library::StarStaticLibrary, }; pub(super) trait StarLinkTarget: Send + Sync + fmt::Debug + Allocative { @@ -28,7 +32,7 @@ pub(super) trait StarLinkTarget: Send + Sync + fmt::Debug + Allocative { fn public_includes_recursive(&self) -> Vec; } -#[derive(Clone)] +#[derive(Allocative, Clone, Debug)] pub(super) struct PtrLinkTarget(pub Arc); impl cmp::PartialEq for PtrLinkTarget { @@ -45,3 +49,31 @@ impl hash::Hash for PtrLinkTarget { (Arc::as_ptr(&self.0) as *const ()).hash(hasher) } } + +#[derive(Clone, Debug, Allocative)] +pub(super) enum StarLinkTargetRef { + Static(Arc), + Object(Arc), + Interface(Arc), + Shared(Arc), +} + +impl StarLinkTargetRef { + pub(super) fn name(&self) -> &str { + match self { + Self::Static(x) => &x.name, + Self::Object(x) => &x.name, + Self::Interface(x) => &x.name, + Self::Shared(x) => &x.name, + } + } + + pub(super) fn as_ptr_link_target(&self) -> PtrLinkTarget { + match self { + Self::Static(x) => PtrLinkTarget(x.clone()), + Self::Object(x) => PtrLinkTarget(x.clone()), + Self::Interface(x) => PtrLinkTarget(x.clone()), + Self::Shared(x) => PtrLinkTarget(x.clone()), + } + } +} diff --git a/src/starlark_object_library.rs b/src/starlark_object_library.rs index 6adc403..188e7df 100644 --- a/src/starlark_object_library.rs +++ b/src/starlark_object_library.rs @@ -98,7 +98,7 @@ impl StarLinkTarget for StarObjectLibrary { gen_name_map: &HashMap, ) -> Result { let arc = Arc::new(self.as_library(parent, parent_path, link_map, gen_name_map)?); - link_map.insert_object(ptr, arc.clone()); + link_map.insert(ptr, LinkPtr::Object(arc.clone())); Ok(LinkPtr::Object(arc)) } diff --git a/src/starlark_project.rs b/src/starlark_project.rs index afb5296..d9f03e9 100644 --- a/src/starlark_project.rs +++ b/src/starlark_project.rs @@ -12,8 +12,7 @@ use starlark::{ MethodsBuilder, MethodsStatic, }, - // starlark_complex_value, - starlark_module, + starlark_module, // starlark_simple_value, values::{ Heap, // @@ -26,18 +25,15 @@ use starlark::{ }; use crate::{ - interface_library::InterfaceLibrary, link_type::LinkPtr, - object_library::ObjectLibrary, project::{Project, ProjectInfo}, - shared_library::SharedLibrary, starlark_executable::StarExecutable, // - starlark_interface_library::{StarIfaceLibWrapper, StarIfaceLibrary}, - starlark_link_target::PtrLinkTarget, - starlark_object_library::{StarObjLibWrapper, StarObjectLibrary}, - starlark_shared_library::{StarSharedLibWrapper, StarSharedLibrary}, - starlark_static_library::{StarStaticLibWrapper, StarStaticLibrary}, - static_library::StaticLibrary, + starlark_interface_library::StarIfaceLibWrapper, + starlark_link_target::{PtrLinkTarget, StarLinkTargetRef}, + starlark_object_library::StarObjLibWrapper, + starlark_shared_library::StarSharedLibWrapper, + starlark_static_library::StarStaticLibWrapper, + target::Target, }; #[derive(Clone, Debug, ProvidesStaticType, NoSerialize, Allocative)] @@ -46,11 +42,7 @@ pub(super) struct StarProject { pub path: PathBuf, pub dependencies: Vec>, pub executables: Vec>, - pub static_libraries: Vec>, - pub object_libraries: Vec>, - pub interface_libraries: Vec>, - pub shared_libraries: Vec>, - + pub link_targets: Vec, pub generator_names: HashMap, } @@ -74,140 +66,41 @@ impl<'v> StarlarkValue<'v> for StarProject { project_methods() } fn get_attr(&self, attribute: &str, heap: &'v Heap) -> Option> { - for lib in &self.static_libraries { - if lib.name == attribute { - return Some(heap.alloc(StarStaticLibWrapper(lib.clone()))); - } - } - for lib in &self.object_libraries { - if lib.name == attribute { - return Some(heap.alloc(StarObjLibWrapper(lib.clone()))); - } - } - for lib in &self.interface_libraries { - if lib.name == attribute { - return Some(heap.alloc(StarIfaceLibWrapper(lib.clone()))); - } - } - for lib in &self.shared_libraries { - if lib.name == attribute { - return Some(heap.alloc(StarSharedLibWrapper(lib.clone()))); + for link_target in &self.link_targets { + if link_target.name() == attribute { + let value = match link_target { + StarLinkTargetRef::Static(lib) => heap.alloc(StarStaticLibWrapper(lib.clone())), + StarLinkTargetRef::Object(lib) => heap.alloc(StarObjLibWrapper(lib.clone())), + StarLinkTargetRef::Interface(lib) => heap.alloc(StarIfaceLibWrapper(lib.clone())), + StarLinkTargetRef::Shared(lib) => heap.alloc(StarSharedLibWrapper(lib.clone())), + }; + return Some(value); } } None } fn has_attr(&self, attribute: &str, _: &'v Heap) -> bool { - for lib in &self.static_libraries { - if lib.name == attribute { - return true; - } - } - for lib in &self.object_libraries { - if lib.name == attribute { - return true; - } - } - for lib in &self.interface_libraries { - if lib.name == attribute { - return true; - } - } - false + self.link_targets.iter().any(|x| x.name() == attribute) } fn dir_attr(&self) -> Vec { - let mut attrs = Vec::new(); - for lib in &self.static_libraries { - attrs.push(lib.name.to_owned()); - } - for lib in &self.object_libraries { - attrs.push(lib.name.to_owned()); - } - for lib in &self.interface_libraries { - attrs.push(lib.name.to_owned()); - } - attrs + self.link_targets.iter().map(|x| x.name().to_owned()).collect() } } starlark_simple_value!(StarProject); -pub(super) struct StarLinkTargetCache { - all_targets: HashSet, - static_libs: HashMap>, - object_libs: HashMap>, - interface_libs: HashMap>, - shared_libs: HashMap>, -} +pub(super) struct StarLinkTargetCache(HashMap); impl StarLinkTargetCache { fn new() -> StarLinkTargetCache { - StarLinkTargetCache { - all_targets: HashSet::new(), - static_libs: HashMap::new(), - object_libs: HashMap::new(), - interface_libs: HashMap::new(), - shared_libs: HashMap::new(), - } - } - pub fn get_static(&self, key: &PtrLinkTarget) -> Option<&Arc> { - if self.all_targets.contains(key) { - self.static_libs.get(key) - } else { - None - } - } - pub fn get_object(&self, key: &PtrLinkTarget) -> Option<&Arc> { - if self.all_targets.contains(key) { - self.object_libs.get(key) - } else { - None - } - } - pub fn get_interface(&self, key: &PtrLinkTarget) -> Option<&Arc> { - if self.all_targets.contains(key) { - self.interface_libs.get(key) - } else { - None - } - } - pub fn get_shared(&self, key: &PtrLinkTarget) -> Option<&Arc> { - if self.all_targets.contains(key) { - self.shared_libs.get(key) - } else { - None - } + StarLinkTargetCache(HashMap::new()) } pub fn get(&self, key: &PtrLinkTarget) -> Option { - if let Some(x) = self.get_static(key) { - return Some(LinkPtr::Static(x.clone())); - } - if let Some(x) = self.get_object(key) { - return Some(LinkPtr::Object(x.clone())); - } - if let Some(x) = self.get_interface(key) { - return Some(LinkPtr::Interface(x.clone())); - } - if let Some(x) = self.get_shared(key) { - return Some(LinkPtr::Shared(x.clone())); - } - None - } - pub fn insert_static(&mut self, key: PtrLinkTarget, value: Arc) { - self.static_libs.insert(key.clone(), value); - self.all_targets.insert(key); + self.0.get(key).cloned() } - pub fn insert_object(&mut self, key: PtrLinkTarget, value: Arc) { - self.object_libs.insert(key.clone(), value); - self.all_targets.insert(key); - } - pub fn insert_interface(&mut self, key: PtrLinkTarget, value: Arc) { - self.interface_libs.insert(key.clone(), value); - self.all_targets.insert(key); - } - pub fn insert_shared(&mut self, key: PtrLinkTarget, value: Arc) { - self.shared_libs.insert(key.clone(), value); - self.all_targets.insert(key); + pub fn insert(&mut self, key: PtrLinkTarget, value: LinkPtr) { + self.0.insert(key, value); } } @@ -218,11 +111,7 @@ impl StarProject { path, dependencies, executables: Vec::new(), - static_libraries: Vec::new(), - object_libraries: Vec::new(), - interface_libraries: Vec::new(), - shared_libraries: Vec::new(), - + link_targets: Vec::new(), generator_names: HashMap::new(), } } @@ -248,67 +137,24 @@ impl StarProject { } ) .collect::>()?, - static_libraries: self - .static_libraries - .iter() - .map(|x| -> Result,String>{ - let ptr = PtrLinkTarget(x.clone()); - if let Some(lib) = link_map.get_static(&ptr) { - Ok(lib.clone()) - } else { - let data = x.as_library(Weak::new(), &self.path, link_map, &self.generator_names)?; - let arc = Arc::new(data); - link_map.insert_static(ptr, arc.clone()); - Ok(arc) - } - }) - .collect::>()?, - object_libraries: self - .object_libraries - .iter() - .map(|x| -> Result,String>{ - let ptr = PtrLinkTarget(x.clone()); - if let Some(lib) = link_map.get_object(&ptr) { - Ok(lib.clone()) - } else { - let data = x.as_library(Weak::new(), &self.path, link_map, &self.generator_names)?; - let arc = Arc::new(data); - link_map.insert_object(ptr, arc.clone()); - Ok(arc) - } - }) - .collect::>()?, - interface_libraries: self - .interface_libraries - .iter() - .map(|x| -> Result<_,String>{ - let ptr = PtrLinkTarget(x.clone()); - if let Some(lib) = link_map.get_interface(&ptr) { - Ok(lib.clone()) - } else { - let data = x.as_library(Weak::new(), &self.path, link_map, &self.generator_names)?; - let arc = Arc::new(data); - link_map.insert_interface(ptr, arc.clone()); - Ok(arc) - } - }) - .collect::>()?, - shared_libraries: self - .shared_libraries - .iter() - .map(|x| -> Result,String>{ - let ptr = PtrLinkTarget(x.clone()); - if let Some(lib) = link_map.get_shared(&ptr) { - Ok(lib.clone()) - } else { - let data = x.as_library(Weak::new(), &self.path, link_map, &self.generator_names)?; - let arc = Arc::new(data); - link_map.insert_shared(ptr, arc.clone()); - Ok(arc) - } - }) - .collect::>()?, - }; //); + link_targets: self + .link_targets + .iter() + .map(|x| -> Result { + let ptr = x.as_ptr_link_target(); + if let Some(lib) = link_map.get(&ptr) { + Ok(lib) + } else { + let data = ptr.0.as_link_target(Weak::new(), &self.path, ptr.clone(), link_map, &self.generator_names)?; + // let arc = Arc::new(data); + link_map.insert(ptr, data.clone()); + Ok(data) + } + }) + .collect::>()?, + }; + + validate_library_dependency_order(&project)?; let ret = Arc::::new_cyclic(move |weak_parent: &Weak| -> Project { // We need one of the following to set the Weak parent without using unsafe: @@ -317,21 +163,26 @@ impl StarProject { for exe in &mut project.executables { Arc::get_mut(exe).unwrap().set_parent(weak_parent.clone()); } - for lib in &mut project.static_libraries { - let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; - lib_mut.set_parent(weak_parent.clone()); - } - for lib in &mut project.object_libraries { - let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; - lib_mut.set_parent(weak_parent.clone()); - } - for lib in &mut project.interface_libraries { - let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; - lib_mut.set_parent(weak_parent.clone()); - } - for lib in &mut project.shared_libraries { - let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; - lib_mut.set_parent(weak_parent.clone()); + + for lib in &mut project.link_targets { + match lib { + LinkPtr::Static(lib) => { + let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; + lib_mut.set_parent(weak_parent.clone()); + } + LinkPtr::Object(lib) => { + let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; + lib_mut.set_parent(weak_parent.clone()); + } + LinkPtr::Interface(lib) => { + let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; + lib_mut.set_parent(weak_parent.clone()); + } + LinkPtr::Shared(lib) => { + let lib_mut = unsafe { &mut (*Arc::as_ptr(lib).cast_mut()) }; + lib_mut.set_parent(weak_parent.clone()); + } + } } project }); @@ -339,3 +190,27 @@ impl StarProject { Ok(ret) } } + +fn validate_library_dependency_order(project: &Project) -> Result<(), String> { + let mut all_targets = HashSet::new(); + let mut seen_targets = HashSet::new(); + for target in &project.link_targets { + all_targets.insert(target.clone()); + } + for target in &project.link_targets { + for dependency in target.internal_links() { + if all_targets.contains(&dependency) && !seen_targets.contains(&dependency) { + return Err(format!( + "Library order violation in project \"{}\": target \"{}\" depends on \"{}\" which is declared later. Declare \"{}\" before \"{}\".", + project.info.name, + target.name(), + dependency.name(), + dependency.name(), + target.name() + )); + } + } + seen_targets.insert(target.clone()); + } + Ok(()) +} diff --git a/src/starlark_shared_library.rs b/src/starlark_shared_library.rs index 6aff519..9ad3bf8 100644 --- a/src/starlark_shared_library.rs +++ b/src/starlark_shared_library.rs @@ -97,8 +97,7 @@ impl StarLinkTarget for StarSharedLibrary { gen_name_map: &HashMap, ) -> Result { let arc = Arc::new(self.as_library(parent, parent_path, link_map, gen_name_map)?); - // let ptr = PtrLinkTarget(arc.clone()); - link_map.insert_shared(ptr, arc.clone()); + link_map.insert(ptr, LinkPtr::Shared(arc.clone())); Ok(LinkPtr::Shared(arc)) } diff --git a/src/starlark_static_library.rs b/src/starlark_static_library.rs index 9405e5a..fe7b83f 100644 --- a/src/starlark_static_library.rs +++ b/src/starlark_static_library.rs @@ -97,8 +97,7 @@ impl StarLinkTarget for StarStaticLibrary { gen_name_map: &HashMap, ) -> Result { let arc = Arc::new(self.as_library(parent, parent_path, link_map, gen_name_map)?); - // let ptr = PtrLinkTarget(arc.clone()); - link_map.insert_static(ptr, arc.clone()); + link_map.insert(ptr, LinkPtr::Static(arc.clone())); Ok(LinkPtr::Static(arc)) } diff --git a/src/static_library.rs b/src/static_library.rs index 8dbf356..444d03f 100644 --- a/src/static_library.rs +++ b/src/static_library.rs @@ -233,23 +233,20 @@ mod tests { info: Arc::new(crate::project::ProjectInfo { name: "test".to_owned(), path: PathBuf::from(".") }), dependencies: Vec::new(), executables: Vec::new(), - static_libraries: vec![ - leaf_shared, - leaf_pub_pub, - leaf_pub_priv, - leaf_priv_pub, - leaf_priv_priv, - mid_pub, - mid_priv, - main_lib, + link_targets: vec![ + LinkPtr::Static(leaf_shared.clone()), + LinkPtr::Static(leaf_pub_pub.clone()), + LinkPtr::Static(leaf_pub_priv.clone()), + LinkPtr::Static(leaf_priv_pub.clone()), + LinkPtr::Static(leaf_priv_priv.clone()), + LinkPtr::Static(mid_pub.clone()), + LinkPtr::Static(mid_priv.clone()), + LinkPtr::Static(main_lib.clone()), ], - object_libraries: Vec::new(), - interface_libraries: Vec::new(), - shared_libraries: Vec::new(), } }); - let main_lib = project.static_libraries.iter().find(|x| x.name == "main_lib").unwrap(); + let main_lib = project.link_targets.iter().find(|x| x.name() == "main_lib").unwrap(); let internal_includes = main_lib.internal_includes(); diff --git a/test_data/test_01/build.catapult b/test_data/test_01/build.catapult index 59ee5e0..df40541 100644 --- a/test_data/test_01/build.catapult +++ b/test_data/test_01/build.catapult @@ -1,10 +1,15 @@ +mylib_helper = add_static_library( + name = "mylib_helper", + include_dirs_public = ["."], + sources = ["mylib_helper.cpp"], +) mylib = add_shared_library( name = "mylib", sources = ["mylib.cpp"], defines_private = ["MYLIB_EXPORT"], include_dirs_public = ["."], - link_private = [my_depend.my_depend_lib], + link_private = [mylib_helper, my_depend.my_depend_lib], ) print('--- ' + str(mylib)) diff --git a/test_data/test_01/mylib_helper.cpp b/test_data/test_01/mylib_helper.cpp new file mode 100644 index 0000000..f1b6626 --- /dev/null +++ b/test_data/test_01/mylib_helper.cpp @@ -0,0 +1,7 @@ +#include "mylib_helper.hpp" + +#include + +void add_two_helper() { + std::cout << "add_two_helper()\n"; +} diff --git a/test_data/test_01/mylib_helper.hpp b/test_data/test_01/mylib_helper.hpp new file mode 100644 index 0000000..369f69f --- /dev/null +++ b/test_data/test_01/mylib_helper.hpp @@ -0,0 +1,3 @@ +#pragma once + +void add_two_helper(); diff --git a/tests/test.rs b/tests/test.rs index b5d3517..f6e3f1c 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -3,7 +3,11 @@ use std::{ env, }; -use catapult::{target::Target, toolchain::Toolchain}; +use catapult::{ + link_type::LinkPtr, // + target::Target, + toolchain::Toolchain, +}; #[test] fn test_01() { @@ -28,9 +32,18 @@ fn test_01() { assert_eq!(my_depends.len(), 1); let my_depend = my_depends.first().unwrap(); assert_eq!(my_depend.executables.len(), 1); - assert_eq!(my_depend.static_libraries.len(), 1); - let static_lib = my_depend.static_libraries.first().unwrap(); + let my_depend_static_libs = my_depend + .link_targets + .iter() + .filter_map(|x| match x { + LinkPtr::Static(lib) => Some(lib.clone()), + _ => None, + }) + .collect::>(); + assert_eq!(my_depend_static_libs.len(), 1); + + let static_lib = my_depend_static_libs.first().unwrap(); assert_eq!(static_lib.name, "my_depend_lib"); assert_eq!(static_lib.sources.cpp.len(), 1); assert_eq!(static_lib.sources.cpp[0].full, cwd.join("submodules").join("my_depend").join("my_depend.cpp")); @@ -41,9 +54,19 @@ fn test_01() { .filter(|x| x.info.name == "blobject") .collect::>(); assert_eq!(blobjects.len(), 1); + let blobject = blobjects.first().unwrap(); - assert_eq!(blobject.object_libraries.len(), 1); - let obj_lib = blobject.object_libraries.first().unwrap(); + let blobject_obj_libs = blobject + .link_targets + .iter() + .filter_map(|x| match x { + LinkPtr::Object(lib) => Some(lib.clone()), + _ => None, + }) + .collect::>(); + assert_eq!(blobject_obj_libs.len(), 1); + + let obj_lib = blobject_obj_libs.first().unwrap(); assert_eq!(obj_lib.name, "blobject"); assert_eq!(obj_lib.sources.c.len(), 1); assert_eq!(obj_lib.sources.c[0].full, cwd.join("submodules").join("blobject").join("blobject2.c")); @@ -51,11 +74,32 @@ fn test_01() { assert_eq!(obj_lib.sources.cpp[0].full, cwd.join("submodules").join("blobject").join("blobject1.cpp")); assert_eq!(project.info.name, "test_one"); + let test_one = project; println!("test_one: {:?}", *test_one); assert_eq!(test_one.executables.len(), 1); - assert_eq!(test_one.static_libraries.len(), 0); - assert_eq!(test_one.shared_libraries.len(), 1); + assert_eq!( + test_one + .link_targets + .iter() + .filter_map(|x| match x { + LinkPtr::Static(lib) => Some(lib.clone()), + _ => None, + }) + .count(), + 1 + ); + assert_eq!( + test_one + .link_targets + .iter() + .filter_map(|x| match x { + LinkPtr::Shared(lib) => Some(lib.clone()), + _ => None, + }) + .count(), + 1 + ); let exe = test_one.executables.first().unwrap(); assert_eq!(exe.name, "myexe"); @@ -68,7 +112,17 @@ fn test_01() { assert_eq!(exe.links[3].name(), "nasmobjs"); assert_eq!(exe.links[4].name(), "zstd"); - let lib = test_one.shared_libraries.first().unwrap(); + let test_one_shared_libs = test_one + .link_targets + .iter() + .filter_map(|x| match x { + LinkPtr::Shared(lib) => Some(lib.clone()), + _ => None, + }) + .collect::>(); + assert_eq!(test_one_shared_libs.len(), 1); + + let lib = test_one_shared_libs.first().unwrap(); assert_eq!(lib.name, "mylib"); assert_eq!(lib.sources.cpp.len(), 1); assert_eq!(lib.sources.cpp[0].full, cwd.join("mylib.cpp"));