Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there currently a way to do conditional compilation? #989

Closed
laptou opened this issue Dec 27, 2021 · 5 comments
Closed

Is there currently a way to do conditional compilation? #989

laptou opened this issue Dec 27, 2021 · 5 comments

Comments

@laptou
Copy link

laptou commented Dec 27, 2021

I want to bind to some C++ methods which only exist on Android. However, if I try to do something like this:

        #[cfg(target_os = "android")]
        type CallInvokerHolder;

        #[cfg(target_os = "android")]
        pub fn getCallInvoker(self: Pin<&mut CallInvokerHolder>) -> SharedPtr<CallInvoker>;

I get the following error:

  error[cxxbridge]: unsupported attribute
      ┌─ src/ffi.rs:326:5
      │
  326 │     #[cfg(target_os = "android")]
      │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported attribute

Is there a workaround?

@dtolnay
Copy link
Owner

dtolnay commented Dec 27, 2021

This is definitely something we can support, but it's not implemented yet.

Basically in Cargo-based builds cxx-build would need to examine CARGO_CFG_TARGET_OS in the build script's environment to decide whether or not to write those types/functions into the generated C++ code, with no other action required on the user's part other than writing cfg(...) inside their cxx::bridge module; and Bazel/Buck/CMake/etc would need the build system to pass something like --cfg=target_os=android / --cfg=target_os=linux as part of their cxxbridge invocation.

For now the easiest workaround would be to move the android-specific signatures to a different cxx::bridge module in a different file, and gate that whole file with #[cfg(target_os = "android")].

Something like:

// lib.rs

#[cfg(target_os = "android")]
mod android;
// android.rs

#[cxx::bridge]
mod ffi {
    extern "C++" {
        type CallInvokerHolder;
        fn getCallInvoker(self: Pin<&mut CallInvokerHolder>) -> SharedPtr<CallInvoker>;
        ...
    }
}
// build.rs

let mut bridge_modules = vec!["src/lib.rs"];
if std::env::var_os("CARGO_CFG_TARGET_OS").unwrap() == "android" {
    bridge_modules.push("src/android.rs");
}
cxx_build::bridges(bridge_modules)
    ...
    .compile(...);

@laptou
Copy link
Author

laptou commented Dec 27, 2021

Thanks for the tip! This is exactly what I ended up doing.

@dtolnay
Copy link
Owner

dtolnay commented Jan 18, 2022

I published an implementation of #[cfg(...)] conditional compilation in cxx 1.0.63. In Cargo-based builds it should just work. In non-Cargo builds you'll need your build system to pass --cfg flags to the cxxbridge CLI just like you'd pass to rustc.

@dtolnay dtolnay closed this as completed Jan 18, 2022
@lukaz-vaultree-com
Copy link

lukaz-vaultree-com commented Jan 30, 2022

Just bumped my cxx version (build and non build versions) to 1.0.63. Then doing:

#[allow(dead_code)]
#[cxx::bridge]
pub(crate) mod ffi {
       #[cfg(debug_assertions)]
       unsafe extern "C++" {
            unsafe fn do_something(
                context: SharedPtr<Context>,
                buffer: *const u8,
                size: usize,
        ) -> bool;
       }

gives undefined reference error on

e::ffi::do_something':
          /workspaces/something/src/bridge.rs:108: undefined reference to `cxxbridge1$do_something'
          collect2: error: ld returned 1 exit status

help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link

Edit: simply taking out #[cfg(debug_assertions)] makes it work

@dtolnay
Copy link
Owner

dtolnay commented Jan 30, 2022

There are a few special cfgs that Cargo conceals from build scripts. I added a workaround for that one in cxx-build 1.0.64.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants