python_packaging/
libpython.rs

1// Copyright 2022 Gregory Szorc.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9/*! Functionality for building a library containing Python */
10
11use {
12    crate::licensing::LicensedComponents,
13    simple_file_manifest::FileData,
14    std::{
15        collections::{BTreeMap, BTreeSet},
16        path::PathBuf,
17    },
18};
19
20/// Holds state necessary to build and link a libpython.
21///
22/// Note that this context is only for producing libpython: it is very
23/// linker centric and doesn't track state like Python resources.
24#[derive(Clone, Debug, Default, PartialEq)]
25pub struct LibPythonBuildContext {
26    /// Compiled flags to use when compiling the object containing Py_inittab.
27    pub inittab_cflags: Option<Vec<String>>,
28
29    /// Include files defining Python headers.
30    ///
31    /// These are necessary to compile code that references Python types.
32    pub includes: BTreeMap<PathBuf, FileData>,
33
34    /// Object files that will be linked together.
35    pub object_files: Vec<FileData>,
36
37    /// Filesystem paths to add to linker search path.
38    pub library_search_paths: BTreeSet<PathBuf>,
39
40    /// System libraries that will be linked against.
41    pub system_libraries: BTreeSet<String>,
42
43    /// Dynamic libraries that will be linked against.
44    pub dynamic_libraries: BTreeSet<String>,
45
46    /// Static libraries that will be linked against.
47    pub static_libraries: BTreeSet<String>,
48
49    /// Frameworks that will be linked against.
50    ///
51    /// Used on Apple platforms.
52    pub frameworks: BTreeSet<String>,
53
54    /// Builtin extension module initialization functions.
55    ///
56    /// Key is extension name. Value is initialization function. The
57    /// function can have the special value `NULL`.
58    pub init_functions: BTreeMap<String, String>,
59
60    /// Holds licensing info for things being linked together.
61    pub licensed_components: LicensedComponents,
62}
63
64impl LibPythonBuildContext {
65    /// Merge multiple `LinkingContext` together to produce an aggregate instance.
66    pub fn merge(contexts: &[&Self]) -> Self {
67        let mut inittab_cflags = None;
68        let mut includes = BTreeMap::new();
69        let mut object_files = Vec::new();
70        let mut library_search_paths = BTreeSet::new();
71        let mut system_libraries = BTreeSet::new();
72        let mut dynamic_libraries = BTreeSet::new();
73        let mut static_libraries = BTreeSet::new();
74        let mut frameworks = BTreeSet::new();
75        let mut init_functions = BTreeMap::new();
76        let mut licensed_components = LicensedComponents::default();
77
78        for context in contexts {
79            // Last write wins.
80            if let Some(flags) = &context.inittab_cflags {
81                inittab_cflags = Some(flags.clone());
82            }
83            for (k, v) in &context.includes {
84                includes.insert(k.clone(), v.clone());
85            }
86            for o in &context.object_files {
87                object_files.push(o.clone());
88            }
89            for p in &context.library_search_paths {
90                library_search_paths.insert(p.clone());
91            }
92            for l in &context.system_libraries {
93                system_libraries.insert(l.clone());
94            }
95            for l in &context.dynamic_libraries {
96                dynamic_libraries.insert(l.clone());
97            }
98            for l in &context.static_libraries {
99                static_libraries.insert(l.clone());
100            }
101            for f in &context.frameworks {
102                frameworks.insert(f.clone());
103            }
104            for (k, v) in &context.init_functions {
105                init_functions.insert(k.clone(), v.clone());
106            }
107            for c in context.licensed_components.iter_components() {
108                licensed_components.add_component(c.clone());
109            }
110        }
111
112        Self {
113            inittab_cflags,
114            includes,
115            object_files,
116            library_search_paths,
117            system_libraries,
118            dynamic_libraries,
119            static_libraries,
120            frameworks,
121            init_functions,
122            licensed_components,
123        }
124    }
125}