Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 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 livekit-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ prost-build = "0.14.1"
webrtc-sys-build = { workspace = true }

[dev-dependencies]
libloading = "0.8.9"
livekit-api = { workspace = true }

[lib]
Expand Down
30 changes: 29 additions & 1 deletion livekit-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{env, path::Path};
use std::{
env,
path::{Path, PathBuf},
};

const PROTO_SRC_DIR: &str = "protocol";

Expand All @@ -23,6 +26,7 @@ fn main() {
download_webrtc();
copy_webrtc_license();
configure_linker();
get_lib_path();
generate_protobuf();
}

Expand Down Expand Up @@ -61,6 +65,30 @@ fn configure_linker() {
}
}

/// Get the path of the built library in the target directory, used for integration testing.
fn get_lib_path() {
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let target_dir = out_dir.ancestors().nth(4).expect("Failed to find target directory");

let build_profile = env::var("PROFILE").unwrap();
let output_dir = target_dir.join(build_profile);

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let lib_extension = match target_os.as_str() {
"windows" => "dll",
"linux" | "android" => "so",
"macos" => "dylib",
"ios" => "a",
_ => {
panic!("Unsupported target, {}", target_os);
}
};
let crate_name = env::var("CARGO_PKG_NAME").unwrap();
let lib_name = format!("lib{}.{}", crate_name.replace("-", "_"), lib_extension);
let lib_path = output_dir.join(lib_name);
println!("cargo::rustc-env=FFI_LIB_PATH={}", lib_path.display());
}

fn generate_protobuf() {
let paths: Vec<_> = std::fs::read_dir(PROTO_SRC_DIR)
.expect("Failed to read protobuf source directory")
Expand Down
39 changes: 39 additions & 0 deletions livekit-ffi/tests/lib_load_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use libloading::{Library, Symbol};
use std::{path::Path, process::Command};

const FFI_LIB_PATH: &str = env!("FFI_LIB_PATH"); // Set by build.rs

const EXPECTED_SYMBOLS: &[&str] = &[
"livekit_ffi_initialize",
"livekit_ffi_request",
"livekit_ffi_drop_handle",
"livekit_ffi_dispose",
];

#[test]
fn lib_load_test() {
println!("Library path: {}", FFI_LIB_PATH);
build_lib_if_required();
unsafe {
let lib = Library::new(FFI_LIB_PATH).expect("Unable to load library");
for symbol in EXPECTED_SYMBOLS {
let _loaded_symbol: Symbol<unsafe extern "C" fn() -> u32> =
lib.get(symbol.as_bytes()).expect(&format!("Missing symbol: {}", symbol));
}
}
}

fn build_lib_if_required() {
let path = Path::new(FFI_LIB_PATH);
if !path.try_exists().unwrap() {
println!("Library not found, building…");
let status = Command::new("cargo")
.args(&["build", "--lib"])
.status()
.expect("Failed to run cargo build for test");

if !status.success() || !path.try_exists().unwrap() {
panic!("Failed to build lib to run test");
}
}
}
Loading