blob: 609db59e2ece2e6663dc01ea42350df7b7e62810 [file] [log] [blame]
David Tolnay864ab8c2020-03-29 22:25:40 -07001//! **[https://github.com/dtolnay/cxx]**
2//!
3//! <br>
4//!
David Tolnay7db73692019-10-20 14:51:12 -04005//! This library provides a **safe** mechanism for calling C++ code from Rust
6//! and Rust code from C++, not subject to the many ways that things can go
7//! wrong when using bindgen or cbindgen to generate unsafe C-style bindings.
8//!
David Tolnayccd39752020-01-08 09:33:51 -08009//! This doesn't change the fact that 100% of C++ code is unsafe. When auditing
10//! a project, you would be on the hook for auditing all the unsafe Rust code
11//! and *all* the C++ code. The core safety claim under this new model is that
12//! auditing just the C++ side would be sufficient to catch all problems, i.e.
13//! the Rust side can be 100% safe.
14//!
David Tolnay7db73692019-10-20 14:51:12 -040015//! <br>
16//!
David Tolnayb606ce32020-03-16 01:16:16 -070017//! *Compiler support: requires rustc 1.42+*
David Tolnay7db73692019-10-20 14:51:12 -040018//!
19//! <br>
20//!
21//! # Overview
22//!
23//! The idea is that we define the signatures of both sides of our FFI boundary
24//! embedded together in one Rust module (the next section shows an example).
25//! From this, CXX receives a complete picture of the boundary to perform static
26//! analyses against the types and function signatures to uphold both Rust's and
27//! C++'s invariants and requirements.
28//!
29//! If everything checks out statically, then CXX uses a pair of code generators
30//! to emit the relevant `extern "C"` signatures on both sides together with any
31//! necessary static assertions for later in the build process to verify
32//! correctness. On the Rust side this code generator is simply an attribute
33//! procedural macro. On the C++ side it can be a small Cargo build script if
34//! your build is managed by Cargo, or for other build systems like Bazel or
35//! Buck we provide a command line tool which generates the header and source
36//! file and should be easy to integrate.
37//!
38//! The resulting FFI bridge operates at zero or negligible overhead, i.e. no
39//! copying, no serialization, no memory allocation, no runtime checks needed.
40//!
41//! The FFI signatures are able to use native types from whichever side they
42//! please, such as Rust's `String` or C++'s `std::string`, Rust's `Box` or
43//! C++'s `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any
44//! combination. CXX guarantees an ABI-compatible signature that both sides
45//! understand, based on builtin bindings for key standard library types to
46//! expose an idiomatic API on those types to the other language. For example
47//! when manipulating a C++ string from Rust, its `len()` method becomes a call
48//! of the `size()` member function defined by C++; when manipulation a Rust
49//! string from C++, its `size()` member function calls Rust's `len()`.
50//!
51//! <br>
52//!
53//! # Example
54//!
55//! A runnable version of this example is provided under the *demo-rs* directory
David Tolnayd763f182020-03-12 00:50:19 -070056//! of [https://github.com/dtolnay/cxx] (with the C++ side of the implementation
David Tolnay7db73692019-10-20 14:51:12 -040057//! in the *demo-cxx* directory). To try it out, jump into demo-rs and run
58//! `cargo run`.
59//!
60//! ```no_run
61//! #[cxx::bridge]
62//! mod ffi {
63//! // Any shared structs, whose fields will be visible to both languages.
64//! struct SharedThing {
65//! z: i32,
66//! y: Box<ThingR>,
67//! x: UniquePtr<ThingC>,
68//! }
69//!
70//! extern "C" {
71//! // One or more headers with the matching C++ declarations. Our code
72//! // generators don't read it but it gets #include'd and used in static
73//! // assertions to ensure our picture of the FFI boundary is accurate.
74//! include!("demo-cxx/demo.h");
75//!
76//! // Zero or more opaque types which both languages can pass around but
77//! // only C++ can see the fields.
78//! type ThingC;
79//!
80//! // Functions implemented in C++.
81//! fn make_demo(appname: &str) -> UniquePtr<ThingC>;
David Tolnayb6a5f672020-04-17 15:04:56 -070082//! fn get_name(thing: &ThingC) -> &CxxString;
David Tolnay7db73692019-10-20 14:51:12 -040083//! fn do_thing(state: SharedThing);
84//! }
85//!
86//! extern "Rust" {
87//! // Zero or more opaque types which both languages can pass around but
88//! // only Rust can see the fields.
89//! type ThingR;
90//!
91//! // Functions implemented in Rust.
92//! fn print_r(r: &ThingR);
93//! }
94//! }
95//! #
96//! # pub struct ThingR(usize);
97//! #
98//! # fn print_r(r: &ThingR) {
99//! # println!("called back with r={}", r.0);
100//! # }
101//! #
102//! # fn main() {}
103//! ```
104//!
105//! Now we simply provide C++ definitions of all the things in the `extern "C"`
106//! block and Rust definitions of all the things in the `extern "Rust"` block,
107//! and get to call back and forth safely.
108//!
109//! Here are links to the complete set of source files involved in the demo:
110//!
111//! - [demo-rs/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/src/main.rs)
112//! - [demo-rs/build.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/build.rs)
113//! - [demo-cxx/demo.h](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.h)
114//! - [demo-cxx/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.cc)
115//!
116//! To look at the code generated in both languages for the example by the CXX
117//! code generators:
118//!
119//! ```console
120//! # run Rust code generator and print to stdout
121//! # (requires https://github.com/dtolnay/cargo-expand)
122//! $ cargo expand --manifest-path demo-rs/Cargo.toml
123//!
124//! # run C++ code generator and print to stdout
125//! $ cargo run --manifest-path cmd/Cargo.toml -- demo-rs/src/main.rs
126//! ```
127//!
128//! <br>
129//!
130//! # Details
131//!
132//! As seen in the example, the language of the FFI boundary involves 3 kinds of
133//! items:
134//!
135//! - **Shared structs** &mdash; their fields are made visible to both
136//! languages. The definition written within cxx::bridge is the single source
137//! of truth.
138//!
139//! - **Opaque types** &mdash; their fields are secret from the other language.
140//! These cannot be passed across the FFI by value but only behind an
141//! indirection, such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can
142//! be a type alias for an arbitrarily complicated generic language-specific
143//! type depending on your use case.
144//!
145//! - **Functions** &mdash; implemented in either language, callable from the
146//! other language.
147//!
148//! Within the `extern "C"` part of the CXX bridge we list the types and
149//! functions for which C++ is the source of truth, as well as the header(s)
150//! that declare those APIs. In the future it's possible that this section could
151//! be generated bindgen-style from the headers but for now we need the
152//! signatures written out; static assertions will verify that they are
153//! accurate.
154//!
155//! Within the `extern "Rust"` part, we list types and functions for which Rust
156//! is the source of truth. These all implicitly refer to the `super` module,
157//! the parent module of the CXX bridge. You can think of the two items listed
158//! in the example above as being like `use super::ThingR` and `use
159//! super::print_r` except re-exported to C++. The parent module will either
160//! contain the definitions directly for simple things, or contain the relevant
161//! `use` statements to bring them into scope from elsewhere.
162//!
163//! Your function implementations themselves, whether in C++ or Rust, *do not*
164//! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the
165//! right shims where necessary to make it all work.
166//!
167//! <br>
168//!
169//! # Comparison vs bindgen and cbindgen
170//!
171//! Notice that with CXX there is repetition of all the function signatures:
172//! they are typed out once where the implementation is defined (in C++ or Rust)
173//! and again inside the cxx::bridge module, though compile-time assertions
174//! guarantee these are kept in sync. This is different from [bindgen] and
175//! [cbindgen] where function signatures are typed by a human once and the tool
176//! consumes them in one language and emits them in the other language.
177//!
178//! [bindgen]: https://github.com/rust-lang/rust-bindgen
179//! [cbindgen]: https://github.com/eqrion/cbindgen/
180//!
181//! This is because CXX fills a somewhat different role. It is a lower level
182//! tool than bindgen or cbindgen in a sense; you can think of it as being a
183//! replacement for the concept of `extern "C"` signatures as we know them,
184//! rather than a replacement for a bindgen. It would be reasonable to build a
185//! higher level bindgen-like tool on top of CXX which consumes a C++ header
186//! and/or Rust module (and/or IDL like Thrift) as source of truth and generates
187//! the cxx::bridge, eliminating the repetition while leveraging the static
188//! analysis safety guarantees of CXX.
189//!
190//! But note in other ways CXX is higher level than the bindgens, with rich
191//! support for common standard library types. Frequently with bindgen when we
192//! are dealing with an idiomatic C++ API we would end up manually wrapping that
193//! API in C-style raw pointer functions, applying bindgen to get unsafe raw
194//! pointer Rust functions, and replicating the API again to expose those
195//! idiomatically in Rust. That's a much worse form of repetition because it is
196//! unsafe all the way through.
197//!
198//! By using a CXX bridge as the shared understanding between the languages,
199//! rather than `extern "C"` C-style signatures as the shared understanding,
200//! common FFI use cases become expressible using 100% safe code.
201//!
202//! It would also be reasonable to mix and match, using CXX bridge for the 95%
203//! of your FFI that is straightforward and doing the remaining few oddball
204//! signatures the old fashioned way with bindgen and cbindgen, if for some
205//! reason CXX's static restrictions get in the way. Please file an issue if you
206//! end up taking this approach so that we know what ways it would be worthwhile
207//! to make the tool more expressive.
208//!
209//! <br>
210//!
211//! # Cargo-based setup
212//!
213//! For builds that are orchestrated by Cargo, you will use a build script that
214//! runs CXX's C++ code generator and compiles the resulting C++ code along with
215//! any other C++ code for your crate.
216//!
217//! The canonical build script is as follows. The indicated line returns a
218//! [`cc::Build`] instance (from the usual widely used `cc` crate) on which you
219//! can set up any additional source files and compiler flags as normal.
220//!
221//! [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
222//!
223//! ```no_run
224//! // build.rs
225//!
226//! fn main() {
227//! cxx::Build::new()
228//! .bridge("src/main.rs") // returns a cc::Build
229//! .file("../demo-cxx/demo.cc")
230//! .flag("-std=c++11")
231//! .compile("cxxbridge-demo");
232//!
233//! println!("cargo:rerun-if-changed=src/main.rs");
234//! println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
235//! println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
236//! }
237//! ```
238//!
239//! <br><br>
240//!
241//! # Non-Cargo setup
242//!
243//! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
244//! way of invoking the C++ code generator as a standalone command line tool.
245//! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
David Tolnayd763f182020-03-12 00:50:19 -0700246//! built from the *cmd* directory of [https://github.com/dtolnay/cxx].
David Tolnay7db73692019-10-20 14:51:12 -0400247//!
248//! ```bash
249//! $ cargo install cxxbridge-cmd
250//!
251//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
252//! $ cxxbridge src/main.rs > path/to/mybridge.cc
253//! ```
254//!
255//! <br>
256//!
257//! # Safety
258//!
259//! Be aware that the design of this library is intentionally restrictive and
260//! opinionated! It isn't a goal to be powerful enough to handle arbitrary
261//! signatures in either language. Instead this project is about carving out a
262//! reasonably expressive set of functionality about which we can make useful
263//! safety guarantees today and maybe extend over time. You may find that it
264//! takes some practice to use CXX bridge effectively as it won't work in all
265//! the ways that you are used to.
266//!
267//! Some of the considerations that go into ensuring safety are:
268//!
269//! - By design, our paired code generators work together to control both sides
270//! of the FFI boundary. Ordinarily in Rust writing your own `extern "C"`
271//! blocks is unsafe because the Rust compiler has no way to know whether the
272//! signatures you've written actually match the signatures implemented in the
273//! other language. With CXX we achieve that visibility and know what's on the
274//! other side.
275//!
276//! - Our static analysis detects and prevents passing types by value that
277//! shouldn't be passed by value from C++ to Rust, for example because they
278//! may contain internal pointers that would be screwed up by Rust's move
279//! behavior.
280//!
281//! - To many people's surprise, it is possible to have a struct in Rust and a
282//! struct in C++ with exactly the same layout / fields / alignment /
283//! everything, and still not the same ABI when passed by value. This is a
284//! longstanding bindgen bug that leads to segfaults in absolutely
285//! correct-looking code ([rust-lang/rust-bindgen#778]). CXX knows about this
286//! and can insert the necessary zero-cost workaround transparently where
287//! needed, so go ahead and pass your structs by value without worries. This
288//! is made possible by owning both sides of the boundary rather than just
289//! one.
290//!
291//! - Template instantiations: for example in order to expose a UniquePtr\<T\>
292//! type in Rust backed by a real C++ unique\_ptr, we have a way of using a
293//! Rust trait to connect the behavior back to the template instantiations
294//! performed by the other language.
295//!
296//! [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
297//!
298//! <br>
299//!
300//! # Builtin types
301//!
David Tolnay559fbb32020-03-17 23:32:20 -0700302//! In addition to all the primitive types (i32 &lt;=&gt; int32_t), the
303//! following common types may be used in the fields of shared structs and the
304//! arguments and returns of functions.
David Tolnay7db73692019-10-20 14:51:12 -0400305//!
306//! <table>
307//! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
David Tolnay750755e2020-03-01 13:04:08 -0800308//! <tr><td>String</td><td>rust::String</td><td></td></tr>
309//! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
David Tolnayefe81052020-04-14 16:28:24 -0700310//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
David Tolnayf51dc4d2020-03-12 00:45:30 -0700311//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
David Tolnay750755e2020-03-01 13:04:08 -0800312//! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
David Tolnayf51dc4d2020-03-12 00:45:30 -0700313//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
David Tolnayaddc7482020-03-29 22:19:44 -0700314//! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
David Tolnay31b5aad2020-04-10 19:35:47 -0700315//! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
David Tolnay7db73692019-10-20 14:51:12 -0400316//! </table>
317//!
David Tolnay736cbca2020-03-11 16:49:18 -0700318//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
David Tolnayd763f182020-03-12 00:50:19 -0700319//! in [https://github.com/dtolnay/cxx]. You will need to include this header in
David Tolnay736cbca2020-03-11 16:49:18 -0700320//! your C++ code when working with those types.
David Tolnay7db73692019-10-20 14:51:12 -0400321//!
322//! The following types are intended to be supported "soon" but are just not
323//! implemented yet. I don't expect any of these to be hard to make work but
324//! it's a matter of designing a nice API for each in its non-native language.
325//!
326//! <table>
327//! <tr><th>name in Rust</th><th>name in C++</th></tr>
David Tolnay84f232e2020-01-08 12:22:56 -0800328//! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
329//! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
330//! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
David Tolnay239d05f2020-03-13 01:36:50 -0700331//! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
David Tolnay84f232e2020-01-08 12:22:56 -0800332//! <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
333//! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
334//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
David Tolnay239d05f2020-03-13 01:36:50 -0700335//! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
David Tolnay7db73692019-10-20 14:51:12 -0400336//! </table>
David Tolnayd763f182020-03-12 00:50:19 -0700337//!
338//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
David Tolnay7db73692019-10-20 14:51:12 -0400339
David Tolnay4272d982020-04-14 16:57:00 -0700340#![doc(html_root_url = "https://docs.rs/cxx/0.2.9")]
David Tolnay7db73692019-10-20 14:51:12 -0400341#![deny(improper_ctypes)]
342#![allow(
David Tolnay4bc98152020-04-09 23:24:01 -0700343 clippy::cognitive_complexity,
David Tolnayd2bb3da2020-03-18 17:19:39 -0700344 clippy::declare_interior_mutable_const,
David Tolnay30d214c2020-03-15 23:54:34 -0700345 clippy::inherent_to_string,
David Tolnay7db73692019-10-20 14:51:12 -0400346 clippy::large_enum_variant,
347 clippy::missing_safety_doc,
348 clippy::module_inception,
David Tolnay30d214c2020-03-15 23:54:34 -0700349 clippy::needless_doctest_main,
David Tolnay7db73692019-10-20 14:51:12 -0400350 clippy::new_without_default,
351 clippy::or_fun_call,
352 clippy::ptr_arg,
353 clippy::toplevel_ref_arg,
David Tolnay7db73692019-10-20 14:51:12 -0400354 clippy::useless_let_if_seq
355)]
356
David Tolnayaf60e232020-01-24 15:22:09 -0800357extern crate link_cplusplus;
358
David Tolnayda5bd272020-03-16 21:53:22 -0700359#[macro_use]
360mod assert;
361
David Tolnay7db73692019-10-20 14:51:12 -0400362mod cxx_string;
363mod error;
David Tolnayebef4a22020-03-17 15:33:47 -0700364mod exception;
David Tolnay75dca2e2020-03-25 20:17:52 -0700365mod function;
David Tolnay7db73692019-10-20 14:51:12 -0400366mod gen;
367mod opaque;
368mod paths;
David Tolnay486b6ec2020-03-17 01:19:57 -0700369mod result;
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700370mod rust_sliceu8;
David Tolnay7db73692019-10-20 14:51:12 -0400371mod rust_str;
372mod rust_string;
373mod syntax;
374mod unique_ptr;
375mod unwind;
376
377pub use crate::cxx_string::CxxString;
David Tolnayebef4a22020-03-17 15:33:47 -0700378pub use crate::exception::Exception;
David Tolnay7db73692019-10-20 14:51:12 -0400379pub use crate::unique_ptr::UniquePtr;
380pub use cxxbridge_macro::bridge;
381
382// Not public API.
383#[doc(hidden)]
384pub mod private {
David Tolnay75dca2e2020-03-25 20:17:52 -0700385 pub use crate::function::FatFunction;
David Tolnay7db73692019-10-20 14:51:12 -0400386 pub use crate::opaque::Opaque;
David Tolnay486b6ec2020-03-17 01:19:57 -0700387 pub use crate::result::{r#try, Result};
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700388 pub use crate::rust_sliceu8::RustSliceU8;
David Tolnay7db73692019-10-20 14:51:12 -0400389 pub use crate::rust_str::RustStr;
390 pub use crate::rust_string::RustString;
391 pub use crate::unique_ptr::UniquePtrTarget;
392 pub use crate::unwind::catch_unwind;
393}
394
395use crate::error::Result;
David Tolnay33d30292020-03-18 18:02:02 -0700396use crate::gen::Opt;
David Tolnay366ef8b2020-01-26 14:15:59 -0800397use anyhow::anyhow;
David Tolnay7db73692019-10-20 14:51:12 -0400398use std::fs;
399use std::io::{self, Write};
400use std::path::Path;
401use std::process;
402
403/// The CXX code generator for constructing and compiling C++ code.
404///
405/// This is intended to be used from Cargo build scripts to execute CXX's
406/// C++ code generator, set up any additional compiler flags depending on
407/// the use case, and make the C++ compiler invocation.
408///
409/// <br>
410///
411/// # Example
412///
413/// Example of a canonical Cargo build script that builds a CXX bridge:
414///
415/// ```no_run
416/// // build.rs
417///
418/// fn main() {
419/// cxx::Build::new()
420/// .bridge("src/main.rs")
421/// .file("../demo-cxx/demo.cc")
422/// .flag("-std=c++11")
423/// .compile("cxxbridge-demo");
424///
425/// println!("cargo:rerun-if-changed=src/main.rs");
426/// println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
427/// println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
428/// }
429/// ```
430///
431/// A runnable working setup with this build script is shown in the
David Tolnayd763f182020-03-12 00:50:19 -0700432/// *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
433///
434/// [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
David Tolnay7db73692019-10-20 14:51:12 -0400435///
436/// <br>
437///
438/// # Alternatives
439///
440/// For use in non-Cargo builds like Bazel or Buck, CXX provides an
441/// alternate way of invoking the C++ code generator as a standalone command
442/// line tool. The tool is packaged as the `cxxbridge-cmd` crate.
443///
444/// ```bash
445/// $ cargo install cxxbridge-cmd # or build it from the repo
446///
447/// $ cxxbridge src/main.rs --header > path/to/mybridge.h
448/// $ cxxbridge src/main.rs > path/to/mybridge.cc
449/// ```
450#[must_use]
451pub struct Build {
452 _private: (),
453}
454
455impl Build {
456 /// Begin with a [`cc::Build`] in its default configuration.
457 pub fn new() -> Self {
458 Build { _private: () }
459 }
460
461 /// This returns a [`cc::Build`] on which you should continue to set up
462 /// any additional source files or compiler flags, and lastly call its
463 /// [`compile`] method to execute the C++ build.
464 ///
465 /// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
466 #[must_use]
467 pub fn bridge(&self, rust_source_file: impl AsRef<Path>) -> cc::Build {
468 match try_generate_bridge(rust_source_file.as_ref()) {
469 Ok(build) => build,
470 Err(err) => {
David Tolnay366ef8b2020-01-26 14:15:59 -0800471 let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
David Tolnay7db73692019-10-20 14:51:12 -0400472 process::exit(1);
473 }
474 }
475 }
476}
477
478fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
David Tolnay33d30292020-03-18 18:02:02 -0700479 let header = gen::do_generate_header(rust_source_file, Opt::default());
David Tolnay7db73692019-10-20 14:51:12 -0400480 let header_path = paths::out_with_extension(rust_source_file, ".h")?;
481 fs::create_dir_all(header_path.parent().unwrap())?;
482 fs::write(&header_path, header)?;
483 paths::symlink_header(&header_path, rust_source_file);
484
David Tolnay33d30292020-03-18 18:02:02 -0700485 let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
David Tolnay7db73692019-10-20 14:51:12 -0400486 let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
487 fs::write(&bridge_path, bridge)?;
488 let mut build = paths::cc_build();
489 build.file(&bridge_path);
490
David Tolnay736cbca2020-03-11 16:49:18 -0700491 let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
492 let _ = fs::create_dir_all(cxx_h.parent().unwrap());
493 let _ = fs::remove_file(cxx_h);
494 let _ = fs::write(cxx_h, gen::include::HEADER);
David Tolnayc43627a2020-01-28 00:50:25 -0800495
David Tolnay7db73692019-10-20 14:51:12 -0400496 Ok(build)
497}