// Copyright 2023 LiveKit, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::path::Path; use std::path::PathBuf; use std::{env, path, process::Command}; fn main() { if env::var("DOCS_RS").is_ok() { return; } println!("cargo:rerun-if-env-changed=LK_DEBUG_WEBRTC"); println!("cargo:rerun-if-env-changed=LK_CUSTOM_WEBRTC"); let mut builder = cxx_build::bridges([ "src/peer_connection.rs", "src/peer_connection_factory.rs", "src/media_stream.rs", "src/media_stream_track.rs", "src/audio_track.rs", "src/video_track.rs", "src/data_channel.rs", "src/frame_cryptor.rs", "src/jsep.rs", "src/candidate.rs", "src/rtp_parameters.rs", "src/rtp_sender.rs", "src/rtp_receiver.rs", "src/rtp_transceiver.rs", "src/rtc_error.rs", "src/webrtc.rs", "src/video_frame.rs", "src/video_frame_buffer.rs", "src/helper.rs", "src/yuv_helper.rs", "src/audio_resampler.rs", "src/android.rs", ]); builder.files(&[ "src/peer_connection.cpp", "src/peer_connection_factory.cpp", "src/media_stream.cpp", "src/media_stream_track.cpp", "src/audio_track.cpp", "src/video_track.cpp", "src/data_channel.cpp", "src/jsep.cpp", "src/candidate.cpp", "src/rtp_receiver.cpp", "src/rtp_sender.cpp", "src/rtp_transceiver.cpp", "src/rtp_parameters.cpp", "src/rtc_error.cpp", "src/webrtc.cpp", "src/video_frame.cpp", "src/video_frame_buffer.cpp", "src/video_encoder_factory.cpp", "src/video_decoder_factory.cpp", "src/audio_device.cpp", "src/audio_resampler.cpp", "src/frame_cryptor.cpp", ]); let webrtc_dir = webrtc_sys_build::webrtc_dir(); let webrtc_include = webrtc_dir.join("include"); let webrtc_lib = webrtc_dir.join("lib"); if !webrtc_dir.exists() { webrtc_sys_build::download_webrtc().unwrap(); } builder.includes(&[ path::PathBuf::from("./include"), webrtc_include.clone(), webrtc_include.join("third_party/abseil-cpp/"), webrtc_include.join("third_party/libyuv/include/"), webrtc_include.join("third_party/libc++/"), // For mac & ios webrtc_include.join("sdk/objc"), webrtc_include.join("sdk/objc/base"), ]); println!("cargo:rustc-link-search=native={}", webrtc_lib.to_str().unwrap()); for (key, value) in webrtc_sys_build::webrtc_defines() { let value = value.as_deref(); builder.define(key.as_str(), value); } // Link webrtc library println!("cargo:rustc-link-lib=static=webrtc"); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); match target_os.as_str() { "windows" => { println!("cargo:rustc-link-lib=dylib=msdmo"); println!("cargo:rustc-link-lib=dylib=wmcodecdspuuid"); println!("cargo:rustc-link-lib=dylib=dmoguids"); println!("cargo:rustc-link-lib=dylib=crypt32"); println!("cargo:rustc-link-lib=dylib=iphlpapi"); println!("cargo:rustc-link-lib=dylib=ole32"); println!("cargo:rustc-link-lib=dylib=secur32"); println!("cargo:rustc-link-lib=dylib=winmm"); println!("cargo:rustc-link-lib=dylib=ws2_32"); println!("cargo:rustc-link-lib=dylib=strmiids"); println!("cargo:rustc-link-lib=dylib=d3d11"); println!("cargo:rustc-link-lib=dylib=gdi32"); println!("cargo:rustc-link-lib=dylib=dxgi"); println!("cargo:rustc-link-lib=dylib=dwmapi"); println!("cargo:rustc-link-lib=dylib=shcore"); builder.flag("/std:c++20").flag("/EHsc"); } "linux" => { println!("cargo:rustc-link-lib=dylib=Xext"); println!("cargo:rustc-link-lib=dylib=X11"); println!("cargo:rustc-link-lib=dylib=GL"); println!("cargo:rustc-link-lib=dylib=rt"); println!("cargo:rustc-link-lib=dylib=dl"); println!("cargo:rustc-link-lib=dylib=pthread"); println!("cargo:rustc-link-lib=dylib=m"); builder.flag("-std=c++2a"); } "macos" => { println!("cargo:rustc-link-lib=framework=Foundation"); println!("cargo:rustc-link-lib=framework=AVFoundation"); println!("cargo:rustc-link-lib=framework=CoreAudio"); println!("cargo:rustc-link-lib=framework=AudioToolbox"); println!("cargo:rustc-link-lib=framework=Appkit"); println!("cargo:rustc-link-lib=framework=CoreMedia"); println!("cargo:rustc-link-lib=framework=CoreGraphics"); println!("cargo:rustc-link-lib=framework=VideoToolbox"); println!("cargo:rustc-link-lib=framework=CoreVideo"); println!("cargo:rustc-link-lib=framework=OpenGL"); println!("cargo:rustc-link-lib=framework=Metal"); println!("cargo:rustc-link-lib=framework=MetalKit"); println!("cargo:rustc-link-lib=framework=QuartzCore"); println!("cargo:rustc-link-lib=framework=IOKit"); println!("cargo:rustc-link-lib=framework=IOSurface"); configure_darwin_sysroot(&mut builder); builder .file("src/objc_video_factory.mm") .file("src/objc_video_frame_buffer.mm") .flag("-stdlib=libc++") .flag("-std=c++20"); } "ios" => { println!("cargo:rustc-link-lib=framework=CoreFoundation"); println!("cargo:rustc-link-lib=framework=AVFoundation"); println!("cargo:rustc-link-lib=framework=CoreAudio"); println!("cargo:rustc-link-lib=framework=UIKit"); println!("cargo:rustc-link-lib=framework=CoreVideo"); println!("cargo:rustc-link-lib=framework=CoreGraphics"); println!("cargo:rustc-link-lib=framework=CoreMedia"); println!("cargo:rustc-link-lib=framework=VideoToolbox"); println!("cargo:rustc-link-lib=framework=AudioToolbox"); println!("cargo:rustc-link-lib=framework=OpenGLES"); println!("cargo:rustc-link-lib=framework=GLKit"); println!("cargo:rustc-link-lib=framework=Metal"); println!("cargo:rustc-link-lib=framework=MetalKit"); println!("cargo:rustc-link-lib=framework=Network"); println!("cargo:rustc-link-lib=framework=QuartzCore"); configure_darwin_sysroot(&mut builder); builder .file("src/objc_video_factory.mm") .file("src/objc_video_frame_buffer.mm") .flag("-std=c++20"); } "android" => { webrtc_sys_build::configure_jni_symbols().unwrap(); println!("cargo:rustc-link-lib=EGL"); println!("cargo:rustc-link-lib=c++abi"); println!("cargo:rustc-link-lib=OpenSLES"); configure_android_sysroot(&mut builder); builder.file("src/android.cpp").flag("-std=c++20").cpp_link_stdlib("c++_static"); } _ => { panic!("Unsupported target, {}", target_os); } } // TODO(theomonnom) Only add this define when building tests builder.define("LIVEKIT_TEST", None); builder.warnings(false).compile("webrtcsys-cxx"); for entry in glob::glob("./src/**/*.cpp").unwrap() { println!("cargo:rerun-if-changed={}", entry.unwrap().display()); } for entry in glob::glob("./src/**/*.mm").unwrap() { println!("cargo:rerun-if-changed={}", entry.unwrap().display()); } for entry in glob::glob("./include/**/*.h").unwrap() { println!("cargo:rerun-if-changed={}", entry.unwrap().display()); } if target_os.as_str() == "android" { copy_libwebrtc_jar(&PathBuf::from(Path::new(&webrtc_dir))); } } fn copy_libwebrtc_jar(webrtc_dir: &PathBuf) { let jar_path = webrtc_dir.join("libwebrtc.jar"); let output_path = get_output_path(); let output_jar_path = output_path.join("libwebrtc.jar"); let res = std::fs::copy(jar_path, output_jar_path); if let Err(e) = res { println!("Failed to copy libwebrtc.jar: {}", e); } } fn get_output_path() -> PathBuf { let manifest_dir_string = env::var("CARGO_MANIFEST_DIR").unwrap(); let build_type = env::var("PROFILE").unwrap(); let build_target = env::var("TARGET").unwrap(); let path = Path::new(&manifest_dir_string).join("../target").join(build_target).join(build_type); return PathBuf::from(path); } fn configure_darwin_sysroot(builder: &mut cc::Build) { let target_os = webrtc_sys_build::target_os(); let sdk = match target_os.as_str() { "mac" => "macosx", "ios-device" => "iphoneos", "ios-simulator" => "iphonesimulator", _ => panic!("Unsupported target_os: {}", target_os), }; let clang_rt = match target_os.as_str() { "mac" => "clang_rt.osx", "ios-device" => "clang_rt.ios", "ios-simulator" => "clang_rt.iossim", _ => panic!("Unsupported target_os: {}", target_os), }; println!("cargo:rustc-link-lib={}", clang_rt); println!("cargo:rustc-link-arg=-ObjC"); let sysroot = Command::new("xcrun").args(["--sdk", sdk, "--show-sdk-path"]).output().unwrap(); let sysroot = String::from_utf8_lossy(&sysroot.stdout); let sysroot = sysroot.trim(); let search_dirs = Command::new("clang").arg("--print-search-dirs").output().unwrap(); let search_dirs = String::from_utf8_lossy(&search_dirs.stdout); for line in search_dirs.lines() { if line.contains("libraries: =") { let path = line.split('=').nth(1).unwrap(); let path = format!("{}/lib/darwin", path); println!("cargo:rustc-link-search={}", path); } } builder.flag(format!("-isysroot{}", sysroot).as_str()); } fn configure_android_sysroot(builder: &mut cc::Build) { let toolchain = webrtc_sys_build::android_ndk_toolchain().unwrap(); let toolchain_lib = toolchain.join("lib"); let sysroot = toolchain.join("sysroot").canonicalize().unwrap(); println!("cargo:rustc-link-search={}", toolchain_lib.display()); builder.flag(format!("-isysroot{}", sysroot.display()).as_str()); }