cc_args/
lib.rs

1#[cfg(feature = "pkg-config")]
2pub use pkg_config;
3
4#[cfg(feature = "bindgen")]
5pub use bindgen;
6
7#[cfg(feature = "cc")]
8pub use cc;
9
10use std::{iter::Chain, path::Path};
11
12#[cfg(feature = "pkg-config")]
13use std::path::PathBuf;
14
15pub mod iter;
16
17pub trait CcArgs<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1>
18where
19    P1: AsRef<Path> + 'a,
20    P2: AsRef<Path> + 'a,
21    P3: AsRef<Path> + 'a,
22    S1: AsRef<str> + 'a,
23    S2: AsRef<str> + 'a,
24    S3: AsRef<str> + 'a,
25    S4: AsRef<str> + 'a,
26    S5: AsRef<str> + 'a,
27    I1: Iterator<Item = S3> + 'a,
28{
29    type LinkPathsIter: Iterator<Item = P1>;
30
31    fn link_paths(&'a self) -> Self::LinkPathsIter;
32
33    #[inline]
34    fn link_paths_args(&'a self) -> iter::LinkPathsArgsIter<P1, Self::LinkPathsIter> {
35        self.link_paths().into()
36    }
37
38    type IncludePathsIter: Iterator<Item = P2>;
39
40    fn include_paths(&'a self) -> Self::IncludePathsIter;
41
42    #[inline]
43    fn include_paths_args(&'a self) -> iter::IncludePathsArgsIter<P2, Self::IncludePathsIter> {
44        self.include_paths().into()
45    }
46
47    type FrameworkPathsIter: Iterator<Item = P3>;
48
49    fn framework_paths(&'a self) -> Self::FrameworkPathsIter;
50
51    #[inline]
52    fn framework_paths_args(
53        &'a self,
54    ) -> iter::FrameworkPathsArgsIter<P3, Self::FrameworkPathsIter> {
55        self.framework_paths().into()
56    }
57
58    type FrameworksIter: Iterator<Item = S1>;
59
60    fn frameworks(&'a self) -> Self::FrameworksIter;
61
62    #[inline]
63    fn frameworks_args(&'a self) -> iter::FrameworksArgsIter<S1, Self::FrameworksIter> {
64        self.frameworks().into()
65    }
66
67    type LibsIter: Iterator<Item = S2>;
68
69    fn libs(&'a self) -> Self::LibsIter;
70
71    #[inline]
72    fn libs_args(&'a self) -> iter::LibsArgsIter<S2, Self::LibsIter> {
73        self.libs().into()
74    }
75
76    type LdArgsIter: Iterator<Item = I1>;
77
78    fn ld_args(&'a self) -> Self::LdArgsIter;
79
80    #[inline]
81    fn ld_args_args(&'a self) -> iter::LdArgsArgsIter<S3, I1, Self::LdArgsIter> {
82        self.ld_args().into()
83    }
84
85    type DefinesIter: Iterator<Item = (S4, &'a Option<S5>)>;
86
87    fn defines(&'a self) -> Self::DefinesIter;
88
89    #[inline]
90    fn defines_args(&'a self) -> iter::DefinesArgsIter<'a, S4, S5, Self::DefinesIter> {
91        self.defines().into()
92    }
93
94    fn cc_args(
95        &'a self,
96    ) -> Chain<
97        Chain<
98            Chain<
99                Chain<
100                    Chain<
101                        Chain<
102                            iter::LinkPathsArgsIter<P1, Self::LinkPathsIter>,
103                            iter::IncludePathsArgsIter<P2, Self::IncludePathsIter>,
104                        >,
105                        iter::FrameworkPathsArgsIter<P3, Self::FrameworkPathsIter>,
106                    >,
107                    iter::FrameworksArgsIter<S1, Self::FrameworksIter>,
108                >,
109                iter::LibsArgsIter<S2, Self::LibsIter>,
110            >,
111            iter::LdArgsArgsIter<S3, I1, Self::LdArgsIter>,
112        >,
113        iter::DefinesArgsIter<'a, S4, S5, Self::DefinesIter>,
114    > {
115        self.link_paths_args()
116            .chain(self.include_paths_args())
117            .chain(self.framework_paths_args())
118            .chain(self.frameworks_args())
119            .chain(self.libs_args())
120            .chain(self.ld_args_args())
121            .chain(self.defines_args())
122    }
123}
124
125pub trait MergeCcArgs {
126    fn merge_cc_args<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1, A>(self, lib: &'a A) -> Self
127    where
128        P1: AsRef<Path> + 'a,
129        P2: AsRef<Path> + 'a,
130        P3: AsRef<Path> + 'a,
131        S1: AsRef<str> + 'a,
132        S2: AsRef<str> + 'a,
133        S3: AsRef<str> + 'a,
134        S4: AsRef<str> + 'a,
135        S5: AsRef<str> + 'a,
136        I1: Iterator<Item = S3> + 'a,
137        A: CcArgs<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1>;
138}
139
140#[cfg(feature = "bindgen")]
141impl MergeCcArgs for bindgen::Builder {
142    fn merge_cc_args<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1, A>(self, lib: &'a A) -> Self
143    where
144        P1: AsRef<Path> + 'a,
145        P2: AsRef<Path> + 'a,
146        P3: AsRef<Path> + 'a,
147        S1: AsRef<str> + 'a,
148        S2: AsRef<str> + 'a,
149        S3: AsRef<str> + 'a,
150        S4: AsRef<str> + 'a,
151        S5: AsRef<str> + 'a,
152        I1: Iterator<Item = S3> + 'a,
153        A: CcArgs<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1>,
154    {
155        self.clang_args(lib.cc_args())
156    }
157}
158
159#[cfg(feature = "pkg-config")]
160#[inline]
161pub(crate) fn vec_iter<'a, T>(v: &'a Vec<T>) -> std::slice::Iter<'a, T> {
162    v.iter()
163}
164
165#[cfg(feature = "pkg-config")]
166impl<'a>
167    CcArgs<
168        'a,
169        &'a PathBuf,
170        &'a PathBuf,
171        &'a PathBuf,
172        &'a String,
173        &'a String,
174        &'a String,
175        &'a String,
176        String,
177        std::slice::Iter<'a, String>,
178    > for pkg_config::Library
179{
180    type LinkPathsIter = std::slice::Iter<'a, PathBuf>;
181
182    fn link_paths(&'a self) -> Self::LinkPathsIter {
183        self.link_paths.iter()
184    }
185
186    type IncludePathsIter = std::slice::Iter<'a, PathBuf>;
187
188    fn include_paths(&'a self) -> Self::IncludePathsIter {
189        self.include_paths.iter()
190    }
191
192    type FrameworkPathsIter = std::slice::Iter<'a, PathBuf>;
193
194    fn framework_paths(&'a self) -> Self::FrameworkPathsIter {
195        self.framework_paths.iter()
196    }
197
198    type FrameworksIter = std::slice::Iter<'a, String>;
199
200    fn frameworks(&'a self) -> Self::FrameworksIter {
201        self.frameworks.iter()
202    }
203
204    type LibsIter = std::slice::Iter<'a, String>;
205
206    fn libs(&'a self) -> Self::LibsIter {
207        self.libs.iter()
208    }
209
210    type LdArgsIter = std::iter::Map<
211        std::slice::Iter<'a, Vec<String>>,
212        fn(&'a Vec<String>) -> std::slice::Iter<'a, String>,
213    >;
214
215    fn ld_args(&'a self) -> Self::LdArgsIter {
216        self.ld_args.iter().map(vec_iter)
217    }
218
219    type DefinesIter = std::collections::hash_map::Iter<'a, String, Option<String>>;
220
221    fn defines(&'a self) -> Self::DefinesIter {
222        self.defines.iter()
223    }
224}
225
226#[cfg(feature = "cc")]
227impl MergeCcArgs for cc::Build {
228    fn merge_cc_args<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1, A>(mut self, lib: &'a A) -> Self
229    where
230        P1: AsRef<Path> + 'a,
231        P2: AsRef<Path> + 'a,
232        P3: AsRef<Path> + 'a,
233        S1: AsRef<str> + 'a,
234        S2: AsRef<str> + 'a,
235        S3: AsRef<str> + 'a,
236        S4: AsRef<str> + 'a,
237        S5: AsRef<str> + 'a,
238        I1: Iterator<Item = S3> + 'a,
239        A: CcArgs<'a, P1, P2, P3, S1, S2, S3, S4, S5, I1>,
240    {
241        for (name, value) in lib.defines() {
242            let value = value.as_ref();
243            self.define(name.as_ref(), value.map(|x| x.as_ref()));
244        }
245
246        for path in lib.include_paths() {
247            self.include(path);
248        }
249
250        for arg in lib
251            .link_paths_args()
252            .chain(lib.framework_paths_args())
253            .chain(lib.libs_args())
254            .chain(lib.frameworks_args())
255            .chain(lib.ld_args_args())
256        {
257            self.flag(&arg);
258        }
259
260        self
261    }
262}