Skip to content

Commit

Permalink
Add unsafe to extern blocks for Rust 2024 (#36)
Browse files Browse the repository at this point in the history
## Description

This replaces the declaration of `extern "C"` blocks with `unsafe extern
"C"` as will be required by Rust 2024. Remove this when
rust-lang/rust-bindgen#2901 is merged and
[bindgen](https://crates.io/crates/bindgen) can generate these blocks
automatically as required.
  • Loading branch information
sgoll authored Nov 15, 2024
1 parent 452051f commit 295a61d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ include = [
bindgen = { version = "0.69.4", features = ["experimental"] }
cc = "1.0.83"
cmake = "0.1.50"
version_check = "0.9.5"

[lints.rust]
future_incompatible = { level = "warn", priority = -1 }
Expand Down
41 changes: 40 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{
env,
fs::File,
io::{self, Write as _},
path::{Path, PathBuf},
};

Expand All @@ -16,6 +18,16 @@ const LIB_BASE: &str = "open62541";
/// the `cc` build adds it as `rustc-link-lib` automatically.
const LIB_EXT: &str = "open62541-ext";

/// Pattern to search for compatibility with Edition 2024.
///
/// See also [`LEGACY_EXTERN_REPLACEMENT`].
const LEGACY_EXTERN_PATTERN: &str = r#"extern "C" {"#;

/// Replacement to use for compatibility with Edition 2024.
///
/// See also [`LEGACY_EXTERN_PATTERN`].
const LEGACY_EXTERN_REPLACEMENT: &str = r#"unsafe extern "C" {"#;

fn main() {
let src = env::current_dir().expect("should get current directory");

Expand Down Expand Up @@ -122,9 +134,22 @@ fn main() {
.expect("should generate `Bindings` instance");

bindings
.write_to_file(out_bindings_rs)
.write_to_file(out_bindings_rs.clone())
.expect("should write `bindings.rs`");

// Until <https://github.com/rust-lang/rust-bindgen/issues/2901> is resolved, we replace `extern
// "C"` with `unsafe extern "C"` manually here. Remove this when `bindgen` is able to do it.
if version_check::is_min_version("1.82.0") == Some(true) {
// We can only use `unsafe extern` starting with Rust 1.82.0. See
// <https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#safe-items-with-unsafe-extern>.
replace_in_file(
&out_bindings_rs,
LEGACY_EXTERN_PATTERN,
LEGACY_EXTERN_REPLACEMENT,
)
.expect("should add unsafe to extern statements");
}

// Build `extern.c` and our custom `wrapper.c` that both hold additional helpers that we want to
// link in addition to the base `open62541` library.
cc::Build::new()
Expand Down Expand Up @@ -184,3 +209,17 @@ impl bindgen::callbacks::ParseCallbacks for CustomCallbacks {
original_item_name.strip_prefix("RS_").map(str::to_owned)
}
}

/// Replaces all occurrences of pattern in file.
///
/// Note that this is not particularly efficient because it reads the entire file into memory before
/// writing it back. Care should be taken when operating on large files.
fn replace_in_file(path: &Path, pattern: &str, replacement: &str) -> io::Result<()> {
let buf = io::read_to_string(File::open(path)?)?;

let buf = buf.replace(pattern, replacement);

File::create(path)?.write_all(buf.as_bytes())?;

Ok(())
}

0 comments on commit 295a61d

Please sign in to comment.