Check for disallowed include strings
error[cxxbridge]: #include relative to `.` or `..` is not supported in Cargo builds
┌─ src/main.rs:10:18
│
10 │ include!("../header.h");
│ ^^^^^^^^^^^^^ #include relative to `.` or `..` is not supported in Cargo builds
│
= note: use a path starting with the crate name
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index e6de985..3e37143 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -271,7 +271,10 @@
}
fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
- let opt = Opt::default();
+ let opt = Opt {
+ allow_dot_includes: false,
+ ..Opt::default()
+ };
let generated = gen::generate_from_path(rust_source_file, &opt);
let ref rel_path = paths::local_relative_path(rust_source_file);
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index cd58307..c723039 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -66,6 +66,7 @@
cxx_impl_annotations: opt.cxx_impl_annotations,
gen_header,
gen_implementation,
+ ..Default::default()
};
let generated_code = if let Some(input) = opt.input {
diff --git a/gen/src/check.rs b/gen/src/check.rs
new file mode 100644
index 0000000..35929ad
--- /dev/null
+++ b/gen/src/check.rs
@@ -0,0 +1,27 @@
+use crate::gen::Opt;
+use crate::syntax::report::Errors;
+use crate::syntax::{error, Api};
+use quote::{quote, quote_spanned};
+use std::path::{Component, Path};
+
+pub(super) use crate::syntax::check::typecheck;
+
+pub(super) fn precheck(cx: &mut Errors, apis: &[Api], opt: &Opt) {
+ if !opt.allow_dot_includes {
+ check_dot_includes(cx, apis);
+ }
+}
+
+fn check_dot_includes(cx: &mut Errors, apis: &[Api]) {
+ for api in apis {
+ if let Api::Include(include) = api {
+ let first_component = Path::new(&include.path).components().next();
+ if let Some(Component::CurDir) | Some(Component::ParentDir) = first_component {
+ let begin = quote_spanned!(include.begin_span=> .);
+ let end = quote_spanned!(include.end_span=> .);
+ let span = quote!(#begin #end);
+ cx.error(span, error::DOT_INCLUDE.msg);
+ }
+ }
+ }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 1a3febd..236fece 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
// Functionality that is shared between the cxx_build::bridge entry point and
// the cxxbridge CLI command.
+mod check;
pub(super) mod error;
mod file;
pub(super) mod fs;
@@ -13,7 +14,7 @@
use self::file::File;
use self::include::Include;
use crate::syntax::report::Errors;
-use crate::syntax::{self, check, Types};
+use crate::syntax::{self, Types};
use std::path::Path;
/// Options for C++ code generation.
@@ -45,6 +46,7 @@
pub(super) gen_header: bool,
pub(super) gen_implementation: bool,
+ pub(super) allow_dot_includes: bool,
}
/// Results of code generation.
@@ -63,6 +65,7 @@
cxx_impl_annotations: None,
gen_header: true,
gen_implementation: true,
+ allow_dot_includes: true,
}
}
}
@@ -112,6 +115,7 @@
let trusted = bridge.unsafety.is_some();
let ref apis = syntax::parse_items(errors, bridge.content, trusted);
let ref types = Types::collect(errors, apis);
+ check::precheck(errors, apis, opt);
errors.propagate()?;
check::typecheck(errors, namespace, apis, types);
errors.propagate()?;
diff --git a/syntax/error.rs b/syntax/error.rs
index a60b7da..9597089 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -19,6 +19,7 @@
CXX_STRING_BY_VALUE,
CXX_TYPE_BY_VALUE,
DISCRIMINANT_OVERFLOW,
+ DOT_INCLUDE,
DOUBLE_UNDERSCORE,
RUST_TYPE_BY_VALUE,
USE_NOT_ALLOWED,
@@ -54,6 +55,12 @@
note: Some("note: explicitly set `= 0` if that is desired outcome"),
};
+pub static DOT_INCLUDE: Error = Error {
+ msg: "#include relative to `.` or `..` is not supported in Cargo builds",
+ label: Some("#include relative to `.` or `..` is not supported in Cargo builds"),
+ note: Some("note: use a path starting with the crate name"),
+};
+
pub static DOUBLE_UNDERSCORE: Error = Error {
msg: "identifiers containing double underscore are reserved in C++",
label: Some("reserved identifier"),