Skip to main content

miden_project/
target.rs

1use alloc::string::{String, ToString};
2
3use miden_assembly_syntax::Path;
4
5use crate::*;
6
7/// Represents build target configuration
8#[derive(Debug, Clone)]
9pub struct Target {
10    pub ty: TargetType,
11    /// The effective name of this target
12    ///
13    /// If unspecified in the project file, the name is the same as `namespace`
14    ///
15    /// The name must be unique within a project
16    pub name: Span<Arc<str>>,
17    /// The namespace root for this target
18    pub namespace: Span<Arc<Path>>,
19    /// The path from the project manifest to the root source file for this target
20    ///
21    /// If not provided, it is expected that source modules will be provided to the assembler
22    /// through other means. For example, `midenc` will compile Rust code to MASM, and then provide
23    /// the MASM modules to an instantiated assembler when assembling this project.
24    pub path: Option<Span<Uri>>,
25}
26
27impl Target {
28    /// Construct a new virtual executable target named `name`
29    pub fn executable(name: impl Into<Arc<str>>) -> Self {
30        Self::r#virtual(TargetType::Executable, name.into(), Path::exec_path())
31    }
32
33    /// Construct a new virtual library target named `name` with namespace `namespace`
34    pub fn library(namespace: impl Into<Arc<Path>>) -> Self {
35        let namespace = namespace.into();
36        let name: Arc<str> = namespace.as_str().into();
37        Self::r#virtual(TargetType::Library, name, namespace)
38    }
39
40    /// Construct a new virtual target of type `ty`, with the given `name` and `namespace`
41    pub fn r#virtual(
42        ty: TargetType,
43        name: impl Into<Arc<str>>,
44        namespace: impl Into<Arc<Path>>,
45    ) -> Self {
46        Self {
47            ty,
48            name: Span::unknown(name.into()),
49            namespace: Span::unknown(namespace.into()),
50            path: None,
51        }
52    }
53
54    /// Construct this [Target] with the given root module [Uri].
55    pub fn with_path(mut self, path: impl Into<Uri>) -> Self {
56        self.path = Some(Span::unknown(path.into()));
57        self
58    }
59
60    /// Returns true if this target is an executable target
61    pub const fn is_executable(&self) -> bool {
62        matches!(self.ty, TargetType::Executable)
63    }
64
65    /// Returns true if this target is a non-executable target
66    pub const fn is_library(&self) -> bool {
67        !self.is_executable()
68    }
69
70    /// Returns true if this target is a kernel target
71    pub const fn is_kernel(&self) -> bool {
72        matches!(self.ty, TargetType::Kernel)
73    }
74
75    /// Append the selected target fields that affect package artifact reuse to `out`.
76    pub fn append_build_provenance_projection(&self, out: &mut String) {
77        let Self { ty, name, namespace, path } = self;
78
79        out.push_str("target:kind:");
80        out.push_str(ty.to_string().as_str());
81        out.push('\n');
82        out.push_str("target:name:");
83        out.push_str(name.inner().as_ref());
84        out.push('\n');
85        out.push_str("target:namespace:");
86        out.push_str(namespace.inner().as_str());
87        out.push('\n');
88        out.push_str("target:path:");
89        match path.as_ref() {
90            Some(path) => out.push_str(path.inner().path()),
91            None => out.push_str("<virtual>"),
92        }
93        out.push('\n');
94    }
95}