diff --git a/build.rs b/build.rs index 52b4fde..ac5ffc3 100644 --- a/build.rs +++ b/build.rs @@ -117,4 +117,53 @@ fn main() { for module in known_modules { println!("cargo::rustc-check-cfg=cfg(riot_module_{})", module); } + + // As a means of last resort, we emulate cfg(accessible(::path::to::thing)), as a + // workaround for https://github.com/rust-lang/rust/issues/64797 + // + // This is sometimes necessary when some C API compatible change (eg. renaming a field with a + // deprecated union while introducing a proper accessor, as done in + // https://github.com/RIOT-OS/RIOT/pull/20900) leads to changes in bindgen and c2rust outputs. + // + // This is similar to the markers that were previously used in riot-sys. We access files + // directly to avoid going through `links=` (see also + // <https://github.com/RIOT-OS/rust-riot-sys/pull/38>). This + // + // * limits the impact of source changes (this way, only changs to relevant headerst trigger + // a rebuild of riot-wrappers), and + // * removes the need for lock-stepping riot-sys and riot-wrappers. + // + // The downside of the tighter coupling with the paths in RIOT is reduced by keeping things + // local and the stabiity structure: All these access checks can be removed once riot-wrappers + // stops supporting a RIOT version that has the symbol unconditionally, without any concern for + // compatibility between crates (as the cfgs are just internal). + + let riotbase: std::path::PathBuf = env::var("RIOTBASE") + .expect("No RIOTBASE set, can not inspect source files for symbol presence.") + .into(); + println!("cargo:rerun-if-env-changed=RIOTBASE"); + + let emulate_accessible = [ + // It's a static inline function and riot-sys currently only gives the file for the bindgen + // output, not the c2rust output. Using coap_build_udp_hdr presence as a stand-in. + // + // Remove this after a release including coap_pkt_set_code + // <https://github.com/RIOT-OS/riot/issues/20900> has been published. + ( + &"inline_coap_pkt_set_code", + &"sys/include/net/nanocoap.h", + &"coap_pkt_set_code", + ), + ]; + + for (rust_name, header_file, header_search_string) in emulate_accessible { + let header_file = riotbase.join(header_file); + println!("cargo:rerun-if-changed={}", header_file.display()); + let header_code = + std::fs::read_to_string(&header_file).expect("Failed to read header file"); + println!("cargo:rustc-check-cfg=cfg(accessible_riot_sys_{rust_name})"); + if header_code.contains(header_search_string) { + println!("cargo:rustc-cfg=accessible_riot_sys_{rust_name}"); + } + } } diff --git a/src/gcoap.rs b/src/gcoap.rs index d7dddf5..fc1267e 100644 --- a/src/gcoap.rs +++ b/src/gcoap.rs @@ -380,7 +380,16 @@ impl<'b> PacketBuffer<'b> { } pub fn set_code_raw(&mut self, code: u8) { - unsafe { (*(*self.pkt).hdr).code = code }; + #[cfg(accessible_riot_sys_inline_coap_pkt_set_code)] + { + unsafe { + riot_sys::inline::coap_pkt_set_code(crate::inline_cast_ref_mut(self.pkt), code) + }; + } + #[cfg(not(accessible_riot_sys_inline_coap_pkt_set_code))] + { + unsafe { (*(*self.pkt).hdr).code = code }; + } } /// Return the total number of bytes in the message, given that `payload_used` bytes were diff --git a/src/gnrc/netreg.rs b/src/gnrc/netreg.rs index 0cf7e1d..b284389 100644 --- a/src/gnrc/netreg.rs +++ b/src/gnrc/netreg.rs @@ -30,7 +30,7 @@ type PktsnipPort = crate::msg::v2::SendPort< /// /// It might be convenient for this to return at some point (in case of short-lived network /// services). Deregistration could be done and everything returned alright -- but the grant would -/// still be lost. This could be mitigated by accepting a 'static PktsnipPort or a clonable version +/// still be lost. This could be mitigated by accepting a 'static PktsnipPort or a cloneable version /// thereof -- not that anything could still be recombined after that, but at least it could be /// used once more (with the risk that messages from the old registration arrive in the new one, /// which is wrong correctness-wise but safe because it'll still be a pointer to a pktsnip). diff --git a/src/msg/v2.rs b/src/msg/v2.rs index 05bcec6..6c21e38 100644 --- a/src/msg/v2.rs +++ b/src/msg/v2.rs @@ -74,7 +74,7 @@ pub struct ReceivePort<TYPE: Send, const TYPENO: u16> { /// share a shared reference), it would be possible to create a version of the SendPort /// that counts its clones at runtime and can only be returned when all of them are recombined, or /// just to create a version that can be cloned at will but never recombined any more. (One way to -/// do the latter would be to add a const boolean type parameter "CLONED"; a `.clonable(self) -> +/// do the latter would be to add a const boolean type parameter "CLONED"; a `.cloneable(self) -> /// Self` would switch that from false to true, and then copy and clone would be implemented for /// the result, whereas recombination would only be implemented for the CLONED = false version). pub struct SendPort<TYPE: Send, const TYPENO: u16> {