From 8301fbfa162de0a34658fb5d64793608a44243d5 Mon Sep 17 00:00:00 2001 From: Skyler Lehmkuhl Date: Tue, 24 Feb 2026 14:40:16 -0500 Subject: [PATCH] windows build fixes --- lightningbeam-ui/Cargo.lock | 56 ++++++++++++++++++++++++++++-- lightningbeam-ui/build-windows.bat | 5 ++- nam-ffi/build.rs | 20 ++++++++--- nam-ffi/cmake/CMakeLists.txt | 16 +++++++++ nam-ffi/src/lib.rs | 34 +++++++++++++----- 5 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 nam-ffi/cmake/CMakeLists.txt diff --git a/lightningbeam-ui/Cargo.lock b/lightningbeam-ui/Cargo.lock index ca38b2f..677a974 100644 --- a/lightningbeam-ui/Cargo.lock +++ b/lightningbeam-ui/Cargo.lock @@ -1817,6 +1817,8 @@ dependencies = [ [[package]] name = "ecolor" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e" dependencies = [ "bytemuck", "emath", @@ -1826,6 +1828,8 @@ dependencies = [ [[package]] name = "eframe" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457481173e6db5ca9fa2be93a58df8f4c7be639587aeb4853b526c6cf87db4e6" dependencies = [ "ahash 0.8.12", "bytemuck", @@ -1861,6 +1865,8 @@ dependencies = [ [[package]] name = "egui" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" dependencies = [ "accesskit", "ahash 0.8.12", @@ -1879,6 +1885,8 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" dependencies = [ "ahash 0.8.12", "bytemuck", @@ -1897,6 +1905,8 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" dependencies = [ "accesskit_winit", "arboard", @@ -1926,6 +1936,8 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01d34e845f01c62e3fded726961092e70417d66570c499b9817ab24674ca4ed" dependencies = [ "ahash 0.8.12", "egui", @@ -1941,6 +1953,8 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6420863ea1d90e750f75075231a260030ad8a9f30a7cef82cdc966492dc4c4eb" dependencies = [ "bytemuck", "egui", @@ -1973,6 +1987,8 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "emath" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" dependencies = [ "bytemuck", "serde", @@ -2048,6 +2064,8 @@ dependencies = [ [[package]] name = "epaint" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009d0dd3c2163823a0abdb899451ecbc78798dec545ee91b43aff1fa790bab62" dependencies = [ "ab_glyph", "ahash 0.8.12", @@ -2065,6 +2083,8 @@ dependencies = [ [[package]] name = "epaint_default_fonts" version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fbe202b6578d3d56428fa185cdf114a05e49da05f477b3c7f0fbb221f1862" [[package]] name = "equator" @@ -4028,7 +4048,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 2.0.110", @@ -7111,7 +7131,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] @@ -8109,3 +8129,35 @@ dependencies = [ "syn 2.0.110", "winnow 0.7.13", ] + +[[patch.unused]] +name = "ecolor" +version = "0.33.2" + +[[patch.unused]] +name = "eframe" +version = "0.33.2" + +[[patch.unused]] +name = "egui" +version = "0.33.2" + +[[patch.unused]] +name = "egui-wgpu" +version = "0.33.2" + +[[patch.unused]] +name = "egui-winit" +version = "0.33.2" + +[[patch.unused]] +name = "egui_extras" +version = "0.33.2" + +[[patch.unused]] +name = "emath" +version = "0.33.2" + +[[patch.unused]] +name = "epaint" +version = "0.33.2" diff --git a/lightningbeam-ui/build-windows.bat b/lightningbeam-ui/build-windows.bat index 7ee3767..6ea2663 100644 --- a/lightningbeam-ui/build-windows.bat +++ b/lightningbeam-ui/build-windows.bat @@ -1,6 +1,9 @@ @echo off REM Build script for Windows -REM Requires: FFmpeg 8.0.0 dev files in C:\ffmpeg, LLVM installed +REM Requires: FFmpeg 8.0.0 dev files in C:\ffmpeg, LLVM installed, VS Build Tools + +REM Set up MSVC environment +call "C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64 REM FFmpeg location (headers + libs + DLLs) if not defined FFMPEG_DIR set FFMPEG_DIR=C:\ffmpeg diff --git a/nam-ffi/build.rs b/nam-ffi/build.rs index ec7cdc7..61be292 100644 --- a/nam-ffi/build.rs +++ b/nam-ffi/build.rs @@ -1,8 +1,21 @@ use std::env; +use std::path::Path; + +/// Canonicalize a path without the \\?\ prefix on Windows +fn clean_canonicalize(p: &Path) -> String { + let canon = p.canonicalize().unwrap(); + let s = canon.to_str().unwrap(); + s.strip_prefix(r"\\?\").unwrap_or(s).to_string() +} fn main() { - let dst = cmake::Config::new("../vendor/NeuralAudio") + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let wrapper_dir = Path::new(&manifest_dir).join("cmake"); + let neural_audio_dir = Path::new(&manifest_dir).join("../vendor/NeuralAudio"); + + let dst = cmake::Config::new(&wrapper_dir) .define("CMAKE_BUILD_TYPE", "Release") + .define("NEURALAUDIO_SOURCE_DIR", clean_canonicalize(&neural_audio_dir)) .define("BUILD_NAMCORE", "OFF") .define("BUILD_STATIC_RTNEURAL", "OFF") .define("BUILD_UTILS", "OFF") @@ -14,9 +27,8 @@ fn main() { let build_dir = dst.join("build"); - // Static libraries land in the build subdirectories - println!("cargo:rustc-link-search=native={}", build_dir.join("NeuralAudioCAPI").display()); - println!("cargo:rustc-link-search=native={}", build_dir.join("NeuralAudio").display()); + println!("cargo:rustc-link-search=native={}", build_dir.join("NeuralAudio").join("NeuralAudioCAPI").display()); + println!("cargo:rustc-link-search=native={}", build_dir.join("NeuralAudio").join("NeuralAudio").display()); println!("cargo:rustc-link-lib=static=NeuralAudioCAPI"); println!("cargo:rustc-link-lib=static=NeuralAudio"); diff --git a/nam-ffi/cmake/CMakeLists.txt b/nam-ffi/cmake/CMakeLists.txt new file mode 100644 index 0000000..2ea559e --- /dev/null +++ b/nam-ffi/cmake/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.5) +project(NeuralAudioStatic) + +# Override add_library to force STATIC even when SHARED is specified +macro(add_library name) + set(_args ${ARGN}) + list(FIND _args "SHARED" _shared_idx) + if(NOT _shared_idx EQUAL -1) + list(REMOVE_AT _args ${_shared_idx}) + _add_library(${name} STATIC ${_args}) + else() + _add_library(${name} ${_args}) + endif() +endmacro() + +add_subdirectory(${NEURALAUDIO_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/NeuralAudio) diff --git a/nam-ffi/src/lib.rs b/nam-ffi/src/lib.rs index 4eeda1f..d6d8366 100644 --- a/nam-ffi/src/lib.rs +++ b/nam-ffi/src/lib.rs @@ -1,9 +1,14 @@ -use std::ffi::CString; use std::path::Path; +#[cfg(windows)] +type WChar = u16; +#[cfg(not(windows))] +type WChar = u32; + #[allow(dead_code)] mod ffi { - use std::os::raw::{c_char, c_float, c_int}; + use super::WChar; + use std::os::raw::{c_float, c_int}; #[repr(C)] pub struct NeuralModel { @@ -11,7 +16,7 @@ mod ffi { } unsafe extern "C" { - pub fn CreateModelFromFile(model_path: *const c_char) -> *mut NeuralModel; + pub fn CreateModelFromFile(model_path: *const WChar) -> *mut NeuralModel; pub fn DeleteModel(model: *mut NeuralModel); pub fn SetLSTMLoadMode(load_mode: c_int); @@ -37,14 +42,12 @@ mod ffi { #[derive(Debug)] pub enum NamError { - NullPath, ModelLoadFailed(String), } impl std::fmt::Display for NamError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - NamError::NullPath => write!(f, "Path contains null byte"), NamError::ModelLoadFailed(path) => write!(f, "Failed to load NAM model: {}", path), } } @@ -56,12 +59,25 @@ pub struct NamModel { impl NamModel { pub fn from_file(path: &Path) -> Result { - let path_str = path.to_string_lossy(); - let c_path = CString::new(path_str.as_bytes()).map_err(|_| NamError::NullPath)?; + let wide: Vec = { + #[cfg(windows)] + { + use std::os::windows::ffi::OsStrExt; + path.as_os_str().encode_wide().chain(std::iter::once(0)).collect() + } + #[cfg(not(windows))] + { + path.to_string_lossy() + .chars() + .map(|c| c as WChar) + .chain(std::iter::once(0)) + .collect() + } + }; - let ptr = unsafe { ffi::CreateModelFromFile(c_path.as_ptr()) }; + let ptr = unsafe { ffi::CreateModelFromFile(wide.as_ptr()) }; if ptr.is_null() { - return Err(NamError::ModelLoadFailed(path_str.into_owned())); + return Err(NamError::ModelLoadFailed(path.display().to_string())); } Ok(NamModel { ptr })