diff --git a/README.md b/README.md index 2f5aec8..8bca933 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,56 @@ For more details, please see: * [`findfst`](findfst): tool for finding values of signals from FST waveform, like `fstminer` tool that comes with GTKWave but more powerful. * [`clipfst`](clipfst): tool for clipping from FST waveform. +## Building on Windows + +Windows requires additional setup due to dependencies that are not readily available: + +### Prerequisites + +- [Rust](https://rustup.rs/) (latest stable version) +- [vcpkg](https://github.com/Microsoft/vcpkg) package manager +- Visual Studio Build Tools or Visual Studio Community + +### Build Instructions + +1. **Install vcpkg:** + + It comes preinstalled with Visual Studio, but if you don't have it yet, you can install it by running the following commands in PowerShell: + ```powershell + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + .\bootstrap-vcpkg.bat + ``` + (tested with vcpkg version 2025-02-11-bec4296bf5289dc9ce83b4f5095943e44162f9c2) + +2. **Install required packages:** + ```powershell + vcpkg install zlib:x64-windows-static-md + vcpkg install pthreads:x64-windows-static-md + vcpkg install mman:x64-windows-static-md + ``` + (adjust vcpkg path as necessary, depending on whether it is on your PATH or not) + +3. **Build** + ```powershell + cargo build + ``` + +**Note:** The build requires the `x64-windows-static-md` triplet for vcpkg packages to ensure compatibility with Rust's MSVC toolchain. + +### Troubleshooting +``` + thread 'main' panicked at fstapi\build.rs:19:8: + called `Result::unwrap()` on an `Err` value: LibNotFound("package zlib is not installed for vcpkg triplet x64-windows-static-md") + note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` +This error indicates that the `zlib` package is not found for the specified vcpkg triplet. Ensure that you have installed `zlib` using the correct triplet as shown in step 2 above. +Similarly for pthreads or mman packages. + +Note that we're using pthreads (with an s) instead of pthread (without s) because the latter is deprecated in vcpkg. + + + ## Rust Wrapper for FST C API This repository contains a Rust wrapper for the FST C API provided by GTKWave. See the [`fstapi`](fstapi) directory. diff --git a/fstapi/Cargo.toml b/fstapi/Cargo.toml index c11cd9f..96a8e69 100644 --- a/fstapi/Cargo.toml +++ b/fstapi/Cargo.toml @@ -14,3 +14,6 @@ license = "MIT OR Apache-2.0" [build-dependencies] bindgen = "0.64.0" cc = { version = "1.0.79", features = ["parallel"] } + +[target.'cfg(windows)'.build-dependencies] +vcpkg = "0.2.15" diff --git a/fstapi/build.rs b/fstapi/build.rs index 6933c99..0296f58 100644 --- a/fstapi/build.rs +++ b/fstapi/build.rs @@ -1,26 +1,67 @@ -use std::{env, path::PathBuf}; +use std::{env, path::{PathBuf}}; fn main() { + + #[cfg(windows)] + let (zlib_include_dir, mman_include_dir) = { + // Find zlib via vcpkg. + let zlib = vcpkg::Config::new() + .emit_includes(true) + .find_package("zlib") + .unwrap(); + let zlib_include_dir = zlib.include_paths[0].clone(); + + vcpkg::Config::new() + .find_package("pthreads") + .unwrap(); + + let mman = vcpkg::Config::new() + .find_package("mman") + .unwrap(); + + // vcpkg installs mman under `mman/sys/mman.h` path structure. + // We need to include the parent `mman` directory so that + // fstapi.c can find `sys/mman.h` without modification. + let mman_base_path = mman.include_paths[0].clone(); + let mman_include_dir = mman_base_path.join(PathBuf::from("mman")); + + (zlib_include_dir, mman_include_dir) + }; + // Compile C sources to library. - cc::Build::new() + let mut cc_build = cc::Build::new(); + cc_build .files(["csrc/fastlz.c", "csrc/fstapi.c", "csrc/lz4.c"]) .define("FST_WRITER_PARALLEL", None) .include("csrc") - .flag_if_supported("-Wno-unused-but-set-variable") - .compile("fst"); + .flag_if_supported("-Wno-unused-but-set-variable"); + + #[cfg(windows)] + cc_build.include(&zlib_include_dir).include(&mman_include_dir); + + cc_build.compile("fst"); // Rebuild if C source changes. println!("cargo:rerun-if-changed=csrc"); // Link with zlib. + #[cfg(not(windows))] println!("cargo:rustc-link-lib=z"); // Generate bindings. - let bindings = bindgen::Builder::default() + let mut bindgen_builder = bindgen::Builder::default() .header("csrc/fstapi.h") .allowlist_type(r#"(fst|FST_)\w+"#) .allowlist_function(r#"(fst|FST_)\w+"#) .allowlist_var(r#"(fst|FST_)\w+"#) + .clang_arg("-Icsrc"); + + #[cfg(windows)] + { + bindgen_builder = bindgen_builder.clang_arg(format!("-I{}", zlib_include_dir.display())); + } + + let bindings = bindgen_builder .generate() .expect("failed to generate bindings"); diff --git a/fstapi/csrc/fst_win_unistd.h b/fstapi/csrc/fst_win_unistd.h index 15ab2c1..37ae6a0 100644 --- a/fstapi/csrc/fst_win_unistd.h +++ b/fstapi/csrc/fst_win_unistd.h @@ -38,6 +38,8 @@ #define unlink _unlink #define fileno _fileno #define lseek _lseeki64 +#define fseeko _fseeki64 +#define ftello _ftelli64 #ifdef _WIN64 #define ssize_t __int64 diff --git a/fstapi/src/reader.rs b/fstapi/src/reader.rs index 7a8bcb6..e6952ff 100644 --- a/fstapi/src/reader.rs +++ b/fstapi/src/reader.rs @@ -4,7 +4,7 @@ use crate::utils::*; use crate::{capi, Error, Result}; use std::marker::PhantomData; use std::num::NonZeroU32; -use std::os::raw; +use std::os::raw::{self}; use std::path::Path; use std::{ptr, slice}; @@ -283,7 +283,7 @@ pub enum Hier<'a> { impl<'a> Hier<'a> { /// Creates a new hierarchy. fn new(hier: &'a capi::fstHier) -> Self { - match hier.htyp as u32 { + match hier.htyp as capi::fstHierType { capi::fstHierType_FST_HT_SCOPE => Self::Scope(Scope(unsafe { &hier.u.scope })), capi::fstHierType_FST_HT_UPSCOPE => Self::Upscope, capi::fstHierType_FST_HT_VAR => Self::Var(Var(unsafe { &hier.u.var })), @@ -382,6 +382,18 @@ impl<'a> Attr<'a> { /// [`ArrayType`](crate::consts::ArrayType), /// [`EnumValueType`](crate::consts::EnumValueType) or /// [`PackType`](crate::consts::PackType). + #[cfg(windows)] + pub fn subtype(&self) -> raw::c_int { + self.0.subtype as raw::c_int + } + + /// Returns attribute subtype. + /// + /// The subtype may be one of [`MiscType`](crate::consts::MiscType), + /// [`ArrayType`](crate::consts::ArrayType), + /// [`EnumValueType`](crate::consts::EnumValueType) or + /// [`PackType`](crate::consts::PackType). + #[cfg(not(windows))] pub fn subtype(&self) -> raw::c_uint { self.0.subtype as raw::c_uint }