cmake_file_api/objects/codemodel_v2/
target.rs

1#![allow(clippy::module_name_repetitions)]
2#![allow(clippy::redundant_closure_for_method_calls)]
3
4use super::backtrace_graph::BacktraceGraph;
5use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7
8/// A codemodel "target" object is referenced by a "codemodel" version 2 object's targets array.
9#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11#[non_exhaustive]
12pub struct Target {
13    /// A string specifying the logical name of the target.
14    pub name: String,
15
16    /// A string uniquely identifying the target.
17    /// The format is unspecified and should not be interpreted by clients.
18    pub id: String,
19
20    /// A string specifying the type of the target.
21    /// The value is one of:
22    /// * EXECUTABLE
23    /// * STATIC_LIBRARY
24    /// * SHARED_LIBRARY
25    /// * MODULE_LIBRARY
26    /// * OBJECT_LIBRARY
27    /// * INTERFACE_LIBRARY
28    /// * UTILITY
29    #[serde(rename = "type")]
30    pub type_name: String,
31
32    /// Optional member that is present when a CMake language backtrace to the command in
33    /// the source code that created the target is available.
34    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
35    pub backtrace: Option<usize>,
36
37    /// Optional member that is present when the FOLDER target property is set.
38    pub folder: Option<Folder>,
39
40    /// Paths to the target's build and source directories.
41    pub paths: TargetPaths,
42
43    /// Optional member that is present for executable and library targets that are linked or archived into a single primary artifact.
44    /// The value is a string specifying the file name of that artifact on disk.
45    pub name_on_disk: Option<String>,
46
47    /// Optional member that is present for executable and library targets that
48    /// produce artifacts on disk meant for consumption by dependents.
49    /// The value is a JSON array of entries corresponding to the artifacts.
50    #[serde(default)]
51    pub artifacts: Vec<Artifact>,
52
53    /// Optional member that is present with boolean value true if the target is provided by CMake's
54    /// build system generator rather than by a command in the source code.
55    #[serde(default)]
56    pub is_generator_provided: bool,
57
58    /// Optional member that is present when the target has an install() rule.
59    pub install: Option<Install>,
60
61    /// Optional member that is present on executable targets that have at least one launcher specified by the project.
62    #[serde(default)]
63    pub launchers: Vec<Launcher>,
64
65    /// Optional member that is present for executables and shared library targets that link into a runtime binary.
66    pub link: Option<Link>,
67
68    /// Optional member that is present for static library targets.
69    pub archive: Option<Archive>,
70
71    /// Optional member that is present when the target depends on other targets.
72    #[serde(default)]
73    pub dependencies: Vec<Dependency>,
74
75    /// target's file sets
76    #[serde(default)]
77    pub file_sets: Vec<FileSet>,
78
79    /// target's sources
80    #[serde(default)]
81    pub sources: Vec<Source>,
82
83    /// Optional member that is present when sources are grouped together by the source_group() command or by default.
84    #[serde(default)]
85    pub source_groups: Vec<SourceGroup>,
86
87    /// Optional member that is present when the target has sources that compile.
88    #[serde(default)]
89    pub compile_groups: Vec<CompileGroup>,
90
91    /// A "codemodel" version 2 "backtrace graph" whose nodes are referenced from backtrace members elsewhere in this "target" object.
92    pub backtrace_graph: BacktraceGraph,
93}
94
95#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
96#[serde(rename_all = "camelCase")]
97#[non_exhaustive]
98pub struct Folder {
99    /// A string specifying the name of the target folder.
100    pub name: String,
101}
102
103#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase")]
105#[non_exhaustive]
106pub struct TargetPaths {
107    /// Path to the target's source directory, represented with forward slashes.
108    /// If the directory is inside the top-level source directory then the path is specified
109    /// relative to that directory (with . for the top-level source directory itself).
110    /// Otherwise, the path is absolute.
111    pub build: PathBuf,
112
113    /// Path to the target's build directory, represented with forward slashes.
114    /// If the directory is inside the top-level build directory then the path is specified
115    /// relative to that directory (with . for the top-level build directory itself).
116    /// Otherwise, the path is absolute.
117    pub source: PathBuf,
118}
119
120#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
121#[serde(rename_all = "camelCase")]
122#[non_exhaustive]
123pub struct Artifact {
124    /// Path to the file on disk, represented with forward slashes.
125    /// If the file is inside the top-level build directory then the path is specified
126    /// relative to that directory.
127    /// Otherwise, the path is absolute.
128    pub path: PathBuf,
129}
130#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
131#[serde(rename_all = "camelCase")]
132#[non_exhaustive]
133pub struct Install {
134    /// installation prefix
135    pub prefix: Prefix,
136
137    /// installation destination paths
138    #[serde(default)]
139    pub destinations: Vec<Destination>,
140}
141#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
142#[serde(rename_all = "camelCase")]
143#[non_exhaustive]
144pub struct Prefix {
145    /// Path value of CMAKE_INSTALL_PREFIX.
146    pub path: PathBuf,
147}
148#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
149#[serde(rename_all = "camelCase")]
150#[non_exhaustive]
151pub struct Destination {
152    /// Path of the installation destination path.
153    /// The path may be absolute or relative to the install prefix.
154    pub path: PathBuf,
155
156    /// Optional member that is present when a CMake language backtrace to the install() command invocation
157    /// that specified this destination is available.
158    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
159    pub backtrace: Option<usize>,
160}
161
162#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
163#[serde(rename_all = "camelCase")]
164#[non_exhaustive]
165pub struct Launcher {
166    ///  string specifying the path to the launcher on disk, represented with forward slashes.
167    /// If the file is inside the top-level source directory then the path is specified relative to that directory.
168    pub command: String,
169
170    /// Optional member that is present when the launcher command has arguments preceding the executable to be launched.
171    #[serde(default)]
172    pub arguments: Vec<String>,
173
174    /// A string specifying the type of launcher.
175    /// The value is one of the following:
176    ///  * emulator: An emulator for the target platform when cross-compiling. See the CROSSCOMPILING_EMULATOR target property.
177    /// * test: A start program for the execution of tests. See the TEST_LAUNCHER target property.
178    pub launcher_type: String,
179}
180
181#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183#[non_exhaustive]
184pub struct Link {
185    /// A string specifying the language (e.g. C, CXX, Fortran) of the toolchain is used to invoke the linker.
186    pub language: String,
187
188    /// Optional member that is present when fragments of the link command line invocation are available.
189    #[serde(default)]
190    pub command_fragments: Vec<CommandFragment>,
191
192    /// True when link-time optimization (a.k.a. interprocedural optimization or link-time code generation) is enabled.
193    #[serde(default)]
194    pub lto: bool,
195
196    /// Optional member that is present when the CMAKE_SYSROOT_LINK or CMAKE_SYSROOT variable is defined.
197    #[serde(default)]
198    pub sysroot: Option<SysRootPath>,
199}
200
201#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
202#[serde(rename_all = "camelCase")]
203#[non_exhaustive]
204pub struct CommandFragment {
205    /// A string specifying a fragment of the link command line invocation.
206    /// The value is encoded in the build system's native shell format.
207    pub fragment: String,
208
209    /// A string specifying the role of the fragment's content:
210    ///  * flags: archiver flags
211    pub role: String,
212}
213
214#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
215#[serde(rename_all = "camelCase")]
216#[non_exhaustive]
217pub struct SysRootPath {
218    /// Absolute path to the sysroot, represented with forward slashes.
219    pub path: PathBuf,
220}
221
222#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
223#[serde(rename_all = "camelCase")]
224#[non_exhaustive]
225pub struct Archive {
226    /// fragments of the archiver command line invocation.
227    #[serde(default)]
228    pub command_fragments: Vec<CommandFragment>,
229
230    /// True when link-time optimization (a.k.a. interprocedural optimization or link-time code generation) is enabled.
231    #[serde(default)]
232    pub lto: bool,
233}
234
235#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
236#[serde(rename_all = "camelCase")]
237#[non_exhaustive]
238pub struct Dependency {
239    /// A string uniquely identifying the target on which this target depends.
240    /// This matches the main id member of the other target.
241    pub id: String,
242
243    /// Optional member that is present when a CMake language backtrace to the add_dependencies(), target_link_libraries(),
244    /// or other command invocation that created this dependency is available.
245    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
246    pub backtrace: Option<usize>,
247}
248
249#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
250#[serde(rename_all = "camelCase")]
251#[non_exhaustive]
252pub struct FileSet {
253    /// A string specifying the name of the file set.
254    pub name: String,
255
256    /// A string specifying the type of the file set. See target_sources() supported file set types.
257    #[serde(rename = "type")]
258    pub type_name: String,
259
260    /// A string specifying the visibility of the file set; one of PUBLIC, PRIVATE, or INTERFACE.
261    pub visibility: String,
262
263    /// Base directories containing sources in the file set.
264    /// If the directory is inside the top-level source directory then the path is specified
265    /// relative to that directory.
266    /// Otherwise, the path is absolute.
267    pub base_directories: Vec<String>,
268}
269
270#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
271#[serde(rename_all = "camelCase")]
272#[non_exhaustive]
273pub struct Source {
274    /// Path to the source file on disk, represented with forward slashes.
275    /// If the file is inside the top-level source directory then the path is specified relative to that directory.
276    /// Otherwise the path is absolute.
277    pub path: PathBuf,
278
279    /// Optional member that is present when the source is compiled.
280    /// The value is an unsigned integer 0-based index into the compileGroups array.
281    pub compile_group_index: Option<usize>,
282
283    /// Optional member that is present when the source is part of a source group either via the source_group() command or by default.
284    /// The value is an unsigned integer 0-based index into the sourceGroups array.
285    pub source_group_index: Option<usize>,
286
287    /// True if the source is GENERATED.
288    #[serde(default)]
289    pub is_generated: bool,
290
291    /// Optional member that is present when the source is part of a file set.
292    /// The value is an unsigned integer 0-based index into the fileSets array.
293    /// This field was added in codemodel version 2.5.
294    pub file_set_index: Option<usize>,
295
296    /// Optional member that is present when a CMake language backtrace to the target_sources(), add_executable(), add_library(),
297    /// add_custom_target(), or other command invocation that added this source to the target is available.
298    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
299    pub backtrace: Option<usize>,
300}
301
302#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
303#[serde(rename_all = "camelCase")]
304#[non_exhaustive]
305pub struct SourceGroup {
306    /// A string specifying the name of the source group.
307    pub name: String,
308
309    /// Indices to sources belonging to the group.
310    /// Each entry is an unsigned integer 0-based index into the main sources array for the target.
311    pub source_indexes: Vec<usize>,
312}
313
314#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
315#[serde(rename_all = "camelCase")]
316#[non_exhaustive]
317pub struct CompileGroup {
318    /// Indices to sources belonging to the compile-group.
319    pub source_indexes: Vec<usize>,
320
321    /// A string specifying the language (e.g. C, CXX, Fortran) of the toolchain is used to compile the source file.
322    pub language: String,
323
324    /// Optional member that is present when the language standard is set explicitly (e.g. via CXX_STANDARD) or
325    /// implicitly by compile features.
326    /// This field was added in codemodel version 2.2.
327    pub language_standard: Option<LanguageStandard>,
328
329    /// Optional member that is present when fragments of the compiler command line invocation are available.
330    #[serde(default)]
331    pub compile_command_fragments: Vec<CompileCommandFragment>,
332
333    /// include directories.
334    #[serde(default)]
335    pub includes: Vec<Include>,
336
337    /// available frameworks (Apple)
338    /// This field was added in codemodel version 2.6.
339    #[serde(default)]
340    pub frameworks: Vec<Framework>,
341
342    /// precompiled headers
343    #[serde(default)]
344    pub precompile_headers: Vec<PrecompileHeader>,
345
346    /// defines
347    #[serde(default)]
348    pub defines: Vec<Define>,
349
350    /// Optional member that is present when the `CMAKE_SYSROOT_COMPILE` or `CMAKE_SYSROOT` variable is defined.
351    pub sysroot: Option<SysRootPath>,
352}
353
354#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
355#[serde(rename_all = "camelCase")]
356#[non_exhaustive]
357pub struct LanguageStandard {
358    /// Optional member that is present when a CMake language backtrace to the `<LANG>_STANDARD` setting is available.
359    /// If the language standard was set implicitly by compile features those are used as the backtrace(s).
360    /// It's possible for multiple compile features to require the same language standard so there could be multiple backtraces.
361    /// Each entry being an unsigned integer 0-based index into the backtraceGraph member's nodes array.
362    #[serde(default)]
363    pub backtraces: Vec<usize>,
364
365    /// String representing the language standard.
366    pub standard: String,
367}
368
369#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
370#[serde(rename_all = "camelCase")]
371#[non_exhaustive]
372pub struct CompileCommandFragment {
373    /// A string specifying a fragment of the compile command line invocation.
374    /// The value is encoded in the build system's native shell format.
375    pub fragment: String,
376}
377
378#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
379#[serde(rename_all = "camelCase")]
380#[non_exhaustive]
381pub struct Include {
382    /// Path to the include directory, represented with forward slashes.
383    pub path: PathBuf,
384
385    /// True if the include directory is marked as a system include directory.
386    #[serde(default)]
387    pub is_system: bool,
388
389    /// Optional member that is present when a CMake language backtrace to the target_include_directories() or
390    /// other command invocation that added this include directory is available.
391    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
392    pub backtrace: Option<usize>,
393}
394#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
395#[serde(rename_all = "camelCase")]
396#[non_exhaustive]
397pub struct Framework {
398    /// Path to the framework directory, represented with forward slashes.
399    pub path: PathBuf,
400
401    /// True if the framework is marked as a system one.
402    #[serde(default)]
403    pub is_system: bool,
404
405    /// Optional member that is present when a CMake language backtrace to the target_link_libraries() or
406    /// other command invocation that added this framework is available.
407    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
408    pub backtrace: Option<usize>,
409}
410
411#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
412#[serde(rename_all = "camelCase")]
413#[non_exhaustive]
414pub struct PrecompileHeader {
415    /// Full path to the precompile header file.
416    pub header: PathBuf,
417
418    /// Optional member that is present when a CMake language backtrace to the target_precompile_headers() or
419    /// other command invocation that added this precompiled header is available.
420    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
421    pub backtrace: Option<usize>,
422}
423
424#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
425#[serde(rename_all = "camelCase")]
426#[non_exhaustive]
427pub struct Define {
428    /// A string specifying the preprocessor definition in the format `<name>[=<value>]`, e.g. `DEF` or `DEF=1`.
429    pub define: String,
430
431    /// Optional member that is present when a CMake language backtrace to the target_compile_definitions() or
432    /// other command invocation that added this preprocessor definition is available.
433    /// The value is an unsigned integer 0-based index into the backtraceGraph member's nodes array.
434    pub backtrace: Option<usize>,
435}
436
437impl CompileGroup {
438    /// Returns a list of defines for the compile group
439    ///
440    /// Compile command fragments can contain defines as well (/D or -D).
441    #[must_use]
442    pub fn defines(&self) -> Vec<String> {
443        let mut defines: Vec<String> = self
444            .defines
445            .iter()
446            .map(|define| define.define.clone())
447            .collect();
448        defines.extend(self.compile_fragments().iter().filter_map(|flag| {
449            if Self::is_define(flag) {
450                flag.get(2..).map(|define| define.to_owned())
451            } else {
452                None
453            }
454        }));
455        defines
456    }
457
458    /// Returns a list of compile flags for the compile group
459    ///
460    /// Compile command fragments are split into single flags and defines (/D or -D) are filtered out.
461    #[must_use]
462    pub fn flags(&self) -> Vec<String> {
463        self.compile_fragments()
464            .iter()
465            .filter(|&flag| !Self::is_define(flag))
466            .cloned()
467            .collect()
468    }
469
470    fn is_define(flag: &str) -> bool {
471        flag.starts_with("/D") || flag.starts_with("-D")
472    }
473
474    #[must_use]
475    /// Compile command fragments are split into single flags.
476    pub fn compile_fragments(&self) -> Vec<String> {
477        self.compile_command_fragments
478            .iter()
479            .filter_map(|frag| shlex::split(&frag.fragment))
480            .flatten()
481            .collect()
482    }
483}
484
485#[cfg(test)]
486mod tests {
487    use crate::objects::codemodel_v2::target::*;
488    use crate::objects::codemodel_v2::Node;
489    use serde_json::json;
490
491    #[test]
492    fn test_target() {
493        let json = json!({
494            "backtrace" : 0,
495            "backtraceGraph" :
496            {
497                "commands" : [],
498                "files" :
499                [
500                    "CMakeLists.txt"
501                ],
502                "nodes" :
503                [
504                    {
505                        "file" : 0
506                    }
507                ]
508            },
509            "dependencies" :
510            [
511                {
512                    "id" : "ZERO_CHECK::@6890427a1f51a3e7e1df"
513                },
514                {
515                    "id" : "subbinary::@6890427a1f51a3e7e1df"
516                }
517            ],
518            "id" : "ALL_BUILD::@6890427a1f51a3e7e1df",
519            "isGeneratorProvided" : true,
520            "name" : "ALL_BUILD",
521            "paths" :
522            {
523                "build" : ".",
524                "source" : "."
525            },
526            "sources" : [],
527            "type" : "UTILITY"
528        }
529        );
530
531        let target = serde_json::from_value::<Target>(json).unwrap();
532        assert_eq!(
533            target,
534            Target {
535                backtrace: Some(0),
536                backtrace_graph: BacktraceGraph {
537                    commands: vec![],
538                    files: vec!["CMakeLists.txt".into()],
539                    nodes: vec![Node {
540                        file: 0,
541                        ..Default::default()
542                    }]
543                },
544                dependencies: vec![
545                    Dependency {
546                        id: "ZERO_CHECK::@6890427a1f51a3e7e1df".to_string(),
547                        ..Default::default()
548                    },
549                    Dependency {
550                        id: "subbinary::@6890427a1f51a3e7e1df".to_string(),
551                        ..Default::default()
552                    }
553                ],
554                id: "ALL_BUILD::@6890427a1f51a3e7e1df".to_string(),
555                is_generator_provided: true,
556                name: "ALL_BUILD".to_string(),
557                paths: TargetPaths {
558                    build: ".".into(),
559                    source: ".".into()
560                },
561                sources: vec![],
562                type_name: "UTILITY".to_string(),
563                ..Default::default()
564            }
565        );
566    }
567}