1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
19
20use core::panic;
21use std::{
22 env,
23 path::{Path, PathBuf},
24};
25
26fn source_dir() -> PathBuf {
27 env::var("DEP_JXL_PATH").map_or_else(
28 |_| Path::new(env!("CARGO_MANIFEST_DIR")).join("libjxl"),
29 PathBuf::from,
30 )
31}
32
33#[cfg_attr(coverage_nightly, coverage(off))]
34pub fn build() {
40 let source = source_dir();
41 assert!(
42 source.exists() && source.is_dir(),
43 "Source directory {} does not exist",
44 source.display()
45 );
46
47 let mut config = cmake::Config::new(source);
48 config
49 .define("BUILD_TESTING", "OFF")
50 .define("BUILD_SHARED_LIBS", "OFF")
51 .define("JPEGXL_ENABLE_TOOLS", "OFF")
52 .define("JPEGXL_ENABLE_DOXYGEN", "OFF")
53 .define("JPEGXL_ENABLE_MANPAGES", "OFF")
54 .define("JPEGXL_ENABLE_BENCHMARK", "OFF")
55 .define("JPEGXL_ENABLE_EXAMPLES", "OFF")
56 .define("JPEGXL_ENABLE_JNI", "OFF")
57 .define("JPEGXL_ENABLE_SJPEG", "OFF")
58 .define("JPEGXL_ENABLE_OPENEXR", "OFF")
59 .define("JPEGXL_ENABLE_JPEGLI", "OFF")
60 .define("JPEGXL_BUNDLE_LIBPNG", "OFF");
61
62 if let Ok(p) = std::thread::available_parallelism() {
63 config.env("CMAKE_BUILD_PARALLEL_LEVEL", format!("{p}"));
64 }
65
66 if cfg!(asan) {
67 config
68 .env("SANITIZER", "asan")
69 .cflag("-g -DADDRESS_SANITIZER -fsanitize=address")
70 .cxxflag("-g -DADDRESS_SANITIZER -fsanitize=address")
71 .define("JPEGXL_ENABLE_TCMALLOC", "OFF");
72 } else if cfg!(tsan) {
73 config
74 .env("SANITIZER", "tsan")
75 .cflag("-g -DTHREAD_SANITIZER -fsanitize=thread")
76 .cxxflag("-g -DTHREAD_SANITIZER -fsanitize=thread")
77 .define("JPEGXL_ENABLE_TCMALLOC", "OFF");
78 }
79
80 if cfg!(windows) {
81 assert!(!cfg!(tsan), "Thread sanitizer is not supported on Windows");
82
83 let exeflags = "MSVCRTD.lib".to_string();
85
86 config
87 .define(
88 "CMAKE_VS_GLOBALS",
89 "UseMultiToolTask=true;EnforceProcessCountAcrossBuilds=true",
90 ) .define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded")
92 .define("CMAKE_EXE_LINKER_FLAGS", exeflags)
93 .cflag("/Zl");
94 }
95
96 let prefix = config.build();
97
98 let lib_dir = {
99 let mut lib_dir = prefix.join("lib");
100 if lib_dir.exists() {
101 lib_dir
102 } else {
103 lib_dir.pop();
104 lib_dir.push("lib64");
105 if lib_dir.exists() {
106 lib_dir
107 } else {
108 panic!(
109 "Could not find the library directory, please check the files in {prefix:?}"
110 );
111 }
112 }
113 };
114 println!("cargo:rustc-link-search=native={}", lib_dir.display());
115
116 println!("cargo:rustc-link-lib=static=jxl");
117 println!("cargo:rustc-link-lib=static=jxl_cms");
118 println!("cargo:rustc-link-lib=static=jxl_threads");
119
120 println!("cargo:rustc-link-lib=static=hwy");
121 println!("cargo:rustc-link-lib=static=brotlidec");
122 println!("cargo:rustc-link-lib=static=brotlienc");
123 println!("cargo:rustc-link-lib=static=brotlicommon");
124
125 if cfg!(any(target_vendor = "apple", target_os = "freebsd")) {
126 println!("cargo:rustc-link-lib=c++");
127 } else if cfg!(target_os = "linux") {
128 println!("cargo:rustc-link-lib=stdc++");
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 #[cfg_attr(coverage_nightly, coverage(off))]
138 fn test_source_dir() {
139 let mut path = source_dir();
140 assert!(path.is_dir());
141
142 path.push("lib/include/jxl/codestream_header.h");
143 assert!(path.exists());
144 }
145}