Repository: dtolnay/cxx (language: rust)

Issue:
Support for #include "rust/cxx.h"
It seems like the generated header and cpp file will include types from cxx/rust.h inline. This is probably the right choice, cxx doesn't know what the final file structure will be. But it would be nice if there was a way to tell cxx where `cxx/rust.h` can be found so that it may omit these types from the header file (resulting in a cleaner header file)


Discussion / hints:

Fix patch:
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 378467b66..adcd04887 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -126,51 +126,55 @@ pub(super) fn write(out: &mut OutFile) {
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    writeln!(out, "// #include \"rust/cxx.h\"");
 
-    ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
+    let cxx_header = include.has_cxx_header();
+    if !cxx_header {
+        writeln!(out, "// #include \"rust/cxx.h\"");
 
-    if builtin.rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
+        ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
 
-    if builtin.friend_impl {
-        out.begin_block(Block::AnonymousNamespace);
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl;");
-        out.end_block(Block::AnonymousNamespace);
-    }
+        if builtin.rust_string {
+            out.next_section();
+            writeln!(out, "struct unsafe_bitcopy_t;");
+        }
 
-    out.next_section();
-    if builtin.rust_str && !builtin.rust_string {
-        writeln!(out, "class String;");
-    }
-    if builtin.layout && !builtin.opaque {
-        writeln!(out, "class Opaque;");
-    }
+        if builtin.friend_impl {
+            out.begin_block(Block::AnonymousNamespace);
+            writeln!(out, "template <typename T>");
+            writeln!(out, "class impl;");
+            out.end_block(Block::AnonymousNamespace);
+        }
 
-    if builtin.rust_slice {
         out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t size_of();");
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t align_of();");
-    }
+        if builtin.rust_str && !builtin.rust_string {
+            writeln!(out, "class String;");
+        }
+        if builtin.layout && !builtin.opaque {
+            writeln!(out, "class Opaque;");
+        }
+
+        if builtin.rust_slice {
+            out.next_section();
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t size_of();");
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t align_of();");
+        }
 
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
-    ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
-    ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
-    ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+        ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
+        ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
+        ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
+        ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+        ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
+        ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
+        ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
+        ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
+        ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+        ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
+        ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
+        ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
+        ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+    }
 
     if builtin.rust_str_new_unchecked {
         out.next_section();
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 93ce60b99..2f59f9767 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -50,11 +50,18 @@ impl<'a> Includes<'a> {
     pub fn insert(&mut self, include: impl Into<Include>) {
         self.custom.push(include.into());
     }
+
+    pub fn has_cxx_header(&self) -> bool {
+        self.custom
+            .iter()
+            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
+    }
 }
 
 pub(super) fn write(out: &mut OutFile) {
     let header = out.header;
     let include = &mut out.include;
+    let cxx_header = include.has_cxx_header();
     let out = &mut include.content;
 
     if header {
@@ -95,69 +102,69 @@ pub(super) fn write(out: &mut OutFile) {
         content: _,
     } = *include;
 
-    if algorithm {
+    if algorithm && !cxx_header {
         writeln!(out, "#include <algorithm>");
     }
-    if array {
+    if array && !cxx_header {
         writeln!(out, "#include <array>");
     }
-    if cassert {
+    if cassert && !cxx_header {
         writeln!(out, "#include <cassert>");
     }
-    if cstddef {
+    if cstddef && !cxx_header {
         writeln!(out, "#include <cstddef>");
     }
-    if cstdint {
+    if cstdint && !cxx_header {
         writeln!(out, "#include <cstdint>");
     }
     if cstring {
         writeln!(out, "#include <cstring>");
     }
-    if exception {
+    if exception && !cxx_header {
         writeln!(out, "#include <exception>");
     }
     if functional {
         writeln!(out, "#include <functional>");
     }
-    if initializer_list {
+    if initializer_list && !cxx_header {
         writeln!(out, "#include <initializer_list>");
     }
-    if iterator {
+    if iterator && !cxx_header {
         writeln!(out, "#include <iterator>");
     }
     if memory {
         writeln!(out, "#include <memory>");
     }
-    if new {
+    if new && !cxx_header {
         writeln!(out, "#include <new>");
     }
-    if string {
+    if string && !cxx_header {
         writeln!(out, "#include <string>");
     }
-    if type_traits {
+    if type_traits && !cxx_header {
         writeln!(out, "#include <type_traits>");
     }
-    if utility {
+    if utility && !cxx_header {
         writeln!(out, "#include <utility>");
     }
-    if vector {
+    if vector && !cxx_header {
         writeln!(out, "#include <vector>");
     }
-    if basetsd {
+    if basetsd && !cxx_header {
         writeln!(out, "#if defined(_WIN32)");
         writeln!(out, "#include <basetsd.h>");
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         if basetsd {
             writeln!(out, "#else");
         } else {
             writeln!(out, "#if not defined(_WIN32)");
         }
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         writeln!(out, "#include <sys/types.h>");
     }
-    if basetsd || sys_types {
+    if (basetsd || sys_types) && !cxx_header {
         writeln!(out, "#endif");
     }
 }


Test patch: