Skip to content
Merged
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
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions fstapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
51 changes: 46 additions & 5 deletions fstapi/build.rs
Original file line number Diff line number Diff line change
@@ -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");

Expand Down
2 changes: 2 additions & 0 deletions fstapi/csrc/fst_win_unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions fstapi/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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 })),
Expand Down Expand Up @@ -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
}
Expand Down
Loading