Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cdylib support by building some static tables in C #1322

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rust-version = "1.79"

[lib]
path = "lib.rs"
crate-type = ["staticlib", "rlib"]
crate-type = ["staticlib", "rlib", "cdylib"]

[dependencies]
assert_matches = "1.5.0"
Expand Down
205 changes: 139 additions & 66 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,111 @@
#![deny(clippy::all)]

#[cfg(feature = "asm")]
mod asm {
use std::collections::HashSet;
use std::env;
use std::fmt::Display;
use std::fs;
use std::path::PathBuf;
use std::str::FromStr;
use std::env;
use std::fmt::Display;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;

#[derive(Clone, Copy, PartialEq, Eq)]
enum Arch {
X86(ArchX86),
Arm(ArchArm),
RiscV(ArchRiscV),
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum Arch {
X86(ArchX86),
Arm(ArchArm),
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum ArchX86 {
X86_32,
X86_64,
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum ArchX86 {
X86_32,
X86_64,
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum ArchArm {
Arm32,
Arm64,
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum ArchRiscV {
RiscV32,
RiscV64,
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum ArchArm {
Arm32,
Arm64,
impl FromStr for Arch {
type Err = String;

fn from_str(arch: &str) -> Result<Self, Self::Err> {
Ok(match arch {
"x86" => Self::X86(ArchX86::X86_32),
"x86_64" => Self::X86(ArchX86::X86_64),
"arm" => Self::Arm(ArchArm::Arm32),
"aarch64" => Self::Arm(ArchArm::Arm64),
"riscv32" => Self::RiscV(ArchRiscV::RiscV32),
"riscv64" => Self::RiscV(ArchRiscV::RiscV64),
_ => return Err(format!("unexpected arch: {arch}")),
})
}
}

struct Define {
name: &'static str,
value: String,
}

impl FromStr for Arch {
type Err = String;

fn from_str(arch: &str) -> Result<Self, Self::Err> {
Ok(match arch {
"x86" => Self::X86(ArchX86::X86_32),
"x86_64" => Self::X86(ArchX86::X86_64),
"arm" => Self::Arm(ArchArm::Arm32),
"aarch64" => Self::Arm(ArchArm::Arm64),
_ => return Err(format!("unexpected arch: {arch}")),
})
impl Define {
pub fn new(name: &'static str, value: impl Display) -> Self {
Self {
name,
value: value.to_string(),
}
}

struct Define {
name: &'static str,
value: String,
pub fn bool(name: &'static str, value: bool) -> Self {
Self::new(name, value as u8)
}
}

impl Define {
pub fn new(name: &'static str, value: impl Display) -> Self {
Self {
name,
value: value.to_string(),
}
}
fn generate_config(
defines: &[Define],
define_prefix: &str,
config_dir: &Path,
config_file_name: &str,
) {
let config_lines = defines
.iter()
.map(|Define { name, value }| format!("{define_prefix}define {name} {value}"))
.collect::<Vec<_>>();
let config_contents = config_lines.join("\n");

let config_path = config_dir.join(config_file_name);
fs::create_dir_all(&config_dir).unwrap();
fs::write(&config_path, &config_contents).unwrap();
}

pub fn bool(name: &'static str, value: bool) -> Self {
Self::new(name, value as u8)
}
}
#[cfg(feature = "asm")]
mod asm {
use super::generate_config;
use super::Arch;
use super::ArchArm;
use super::ArchX86;
use super::Define;
use std::collections::HashSet;
use std::env;
use std::path::Path;
use std::path::PathBuf;

pub fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
pub fn main(out_dir: &Path, arch: Arch) {
// TODO: Add support for assembly on riscv architectures.
if matches!(arch, Arch::RiscV(..)) {
return;
}

let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap();

// Nothing to do on unknown architectures
let Ok(arch) = arch.parse::<Arch>() else {
return;
};
let os = os.as_str();
let vendor = vendor.as_str();
let pointer_width = pointer_width.as_str();
Expand Down Expand Up @@ -126,19 +160,13 @@ mod asm {
let use_nasm = match arch {
Arch::X86(..) => true,
Arch::Arm(..) => false,
Arch::RiscV(..) => unreachable!(),
};

let define_prefix = if use_nasm { "%" } else { " #" };

let config_lines = defines
.iter()
.map(|Define { name, value }| format!("{define_prefix}define {name} {value}"))
.collect::<Vec<_>>();

let config_contents = config_lines.join("\n");
let config_file_name = if use_nasm { "config.asm" } else { "config.h" };
let config_path = out_dir.join(config_file_name);
fs::write(&config_path, &config_contents).unwrap();
let config_dir = out_dir.join("asm");
generate_config(&defines, define_prefix, &config_dir, config_file_name);

// Note that avx* is never (at runtime) supported on x86.
let x86_generic = &["cdef_sse", "itx_sse", "msac", "pal", "refmvs"][..];
Expand Down Expand Up @@ -248,11 +276,13 @@ mod asm {
Arch::X86(ArchX86::X86_32) => x86_all,
Arch::X86(ArchX86::X86_64) => x86_64_all,
Arch::Arm(..) => arm_all,
Arch::RiscV(..) => unreachable!(),
};

let asm_file_dir = match arch {
Arch::X86(..) => ["x86", "."],
Arch::Arm(..) => ["arm", pointer_width],
Arch::RiscV(..) => unreachable!(),
};
let asm_extension = if use_nasm { "asm" } else { "S" };

Expand All @@ -278,7 +308,7 @@ mod asm {
nasm.flag("-Fdwarf");
#[cfg(all(debug_assertions, windows))]
nasm.flag("-fwin64");
nasm.flag(&format!("-I{}/", out_dir.to_str().unwrap()));
nasm.flag(&format!("-I{}/", config_dir.to_str().unwrap()));
nasm.flag("-Isrc/");
let obj = nasm.compile_objects().unwrap_or_else(|e| {
println!("cargo:warning={e}");
Expand All @@ -296,7 +326,7 @@ mod asm {
cc::Build::new()
.files(asm_file_paths)
.include(".")
.include(&out_dir)
.include(&config_dir)
.debug(cfg!(debug_assertions))
.compile(rav1dasm);
}
Expand All @@ -306,9 +336,52 @@ mod asm {
}

fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();

// Nothing to do on unknown architectures.
let Ok(arch) = arch.parse::<Arch>() else {
return;
};

let mut defines = Vec::new();

match arch {
Arch::X86(arch) => {
defines.push(Define::bool("ARCH_X86", true));
defines.push(Define::bool("ARCH_X86_32", arch == ArchX86::X86_32));
defines.push(Define::bool("ARCH_X86_64", arch == ArchX86::X86_64));
}

Arch::Arm(arch) => {
defines.push(Define::bool("ARCH_ARM", arch == ArchArm::Arm32));
defines.push(Define::bool("ARCH_AARCH64", arch == ArchArm::Arm64));
}

Arch::RiscV(arch) => {
defines.push(Define::bool("ARCH_RISCV", true));
defines.push(Define::bool("ARCH_RV32", arch == ArchRiscV::RiscV32));
defines.push(Define::bool("ARCH_RV64", arch == ArchRiscV::RiscV64));
}
}

let config_dir = out_dir.join("include");
generate_config(&defines, "#", &config_dir, "config.h");

let rav1dtables = "rav1dtables";

cc::Build::new()
.file("src/tables.c")
.include("include")
.include(&config_dir)
.include(".")
.compile(rav1dtables);

println!("cargo:rustc-link-lib=static={rav1dtables}");

#[cfg(feature = "asm")]
{
asm::main();
asm::main(&out_dir, arch);
}

// NOTE: we rely on libraries that are only distributed for Windows so
Expand Down
6 changes: 3 additions & 3 deletions src/filmgrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::src::enum_map::DefaultValue;
use crate::src::ffi_safe::FFISafe;
use crate::src::internal::GrainLut;
use crate::src::strided::Strided as _;
use crate::src::tables::dav1d_gaussian_sequence;
use crate::src::tables::gaussian_sequence;
use crate::src::wrap_fn_ptr::wrap_fn_ptr;
use libc::intptr_t;
use libc::ptrdiff_t;
Expand Down Expand Up @@ -310,7 +310,7 @@ fn generate_grain_y_rust<BD: BitDepth>(
for row in &mut buf[..GRAIN_HEIGHT] {
row[..GRAIN_WIDTH].fill_with(|| {
let value = get_random_number(11, &mut seed);
round2(dav1d_gaussian_sequence[value as usize], shift).as_::<BD::Entry>()
round2(gaussian_sequence()[value as usize], shift).as_::<BD::Entry>()
});
}

Expand Down Expand Up @@ -424,7 +424,7 @@ fn generate_grain_uv_rust<BD: BitDepth>(
for row in &mut buf[..is_sub.chroma().0] {
row[..is_sub.chroma().1].fill_with(|| {
let value = get_random_number(11, &mut seed);
round2(dav1d_gaussian_sequence[value as usize], shift).as_::<BD::Entry>()
round2(gaussian_sequence()[value as usize], shift).as_::<BD::Entry>()
});
}

Expand Down
Loading
Loading