From 0657a80ed6b698158d8173679a5e853ccdaedff6 Mon Sep 17 00:00:00 2001 From: vinx Date: Sun, 10 Nov 2024 00:29:48 +0800 Subject: [PATCH] add support for msys2 --- .github/workflows/CI.yml | 23 ++++ mupdf-sys/build.rs | 222 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 244 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 13d8040..9cd284c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -53,6 +53,29 @@ jobs: if: matrix.os == 'ubuntu-latest' run: cargo package --manifest-path mupdf-sys/Cargo.toml + test-msys: + name: Test Suite (MSYS2) + runs-on: windows-2019 + strategy: + matrix: + include: + - { sys: ucrt64, env: ucrt-x86_64 } + - { sys: mingw64, env: x86_64 } + # - { sys: mingw32, env: i686 } + - { sys: clang64, env: clang-x86_64 } + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + install: mingw-w64-${{matrix.env}}-rust base base-devel unzip git + + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + fetch-depth: 500 + - run: cargo test + + asan: name: Address Sanitizer runs-on: ubuntu-latest diff --git a/mupdf-sys/build.rs b/mupdf-sys/build.rs index 5b05c6e..4d1cd07 100644 --- a/mupdf-sys/build.rs +++ b/mupdf-sys/build.rs @@ -47,7 +47,7 @@ fn cp_r(dir: &Path, dest: &Path) { } } -#[cfg(not(target_env = "msvc"))] +#[cfg(not(windows))] fn build_libmupdf() { use std::process::Command; @@ -355,6 +355,226 @@ fn build_libmupdf() { } } +#[cfg(all(windows, target_env = "gnu"))] +fn build_libmupdf() { + use std::process::Command; + + let profile = match &*env::var("PROFILE").unwrap_or("debug".to_owned()) { + "bench" | "release" => "release", + _ => "debug", + }; + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let build_dir = out_dir.join("build"); + + let build_dir_str = build_dir.to_string_lossy().replace("\\", "/"); + t!(fs::create_dir_all(&build_dir)); + + let current_dir = env::current_dir().unwrap(); + let mupdf_src_dir = current_dir.join("mupdf"); + cp_r(&mupdf_src_dir, &build_dir); + + let mut build = cc::Build::new(); + #[cfg(not(feature = "xps"))] + build.define("FZ_ENABLE_XPS", Some("0")); + #[cfg(not(feature = "svg"))] + build.define("FZ_ENABLE_SVG", Some("0")); + #[cfg(not(feature = "cbz"))] + build.define("FZ_ENABLE_CBZ", Some("0")); + #[cfg(not(feature = "img"))] + build.define("FZ_ENABLE_IMG", Some("0")); + #[cfg(not(feature = "html"))] + build.define("FZ_ENABLE_HTML", Some("0")); + #[cfg(not(feature = "epub"))] + build.define("FZ_ENABLE_EPUB", Some("0")); + #[cfg(not(feature = "js"))] + build.define("FZ_ENABLE_JS", Some("0")); + + if !cfg!(feature = "all-fonts") { + SKIP_FONTS.iter().for_each(|font| { + build.define(font, None); + }); + } + + let mut make_flags = vec![ + "libs".to_owned(), + format!("build={}", profile), + format!("OUT={}", &build_dir_str), + #[cfg(feature = "sys-lib-freetype")] + "USE_SYSTEM_FREETYPE=yes".to_owned(), + #[cfg(feature = "sys-lib-gumbo")] + "USE_SYSTEM_GUMBO=yes".to_owned(), + #[cfg(feature = "sys-lib-harfbuzz")] + "USE_SYSTEM_HARFBUZZ=yes".to_owned(), + #[cfg(feature = "sys-lib-jbig2dec")] + "USE_SYSTEM_JBIG2DEC=yes".to_owned(), + #[cfg(feature = "sys-lib-libjpeg")] + "USE_SYSTEM_LIBJPEG=yes".to_owned(), + #[cfg(feature = "sys-lib-openjpeg")] + "USE_SYSTEM_OPENJPEG=yes".to_owned(), + #[cfg(feature = "sys-lib-zlib")] + "USE_SYSTEM_ZLIB=yes".to_owned(), + #[cfg(feature = "sys-lib-leptonica")] + "USE_SYSTEM_LEPTONICA=yes".to_owned(), + #[cfg(not(feature = "tesseract"))] + "USE_TESSERACT=no".to_owned(), + #[cfg(feature = "sys-lib-tesseract")] + "USE_SYSTEM_TESSERACT=yes".to_owned(), + #[cfg(feature = "sys-lib")] + "USE_SYSTEM_LIBS=yes".to_owned(), + "HAVE_X11=no".to_owned(), + "HAVE_GLUT=no".to_owned(), + "HAVE_CURL=no".to_owned(), + "verbose=yes".to_owned(), + ]; + + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-freetype") { + let lib = pkg_config::probe_library("freetype2").unwrap(); + make_flags.push(format!( + "SYS_FREETYPE_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-gumbo") { + let lib = pkg_config::probe_library("gumbo").unwrap(); + make_flags.push(format!( + "SYS_GUMBO_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-harfbuzz") { + let lib = pkg_config::probe_library("harfbuzz").unwrap(); + make_flags.push(format!( + "SYS_HARFBUZZ_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-jbig2dec") { + let lib = pkg_config::probe_library("jbig2dec").unwrap(); + make_flags.push(format!( + "SYS_JBIG2DEC_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-libjpeg") { + let lib = pkg_config::probe_library("libjpeg").unwrap(); + make_flags.push(format!( + "SYS_LIBJPEG_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-openjpeg") { + let lib = pkg_config::probe_library("libopenjp2").unwrap(); + make_flags.push(format!( + "SYS_OPENJPEG_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib") || cfg!(feature = "sys-lib-zlib") { + let lib = pkg_config::probe_library("zlib").unwrap(); + make_flags.push(format!( + "SYS_ZLIB_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + + // leptonica and tesseract excluded from sys-lib feature + if cfg!(feature = "sys-lib-leptonica") { + let lib = pkg_config::probe_library("lept").unwrap(); + make_flags.push(format!( + "SYS_LEPTONICA_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + if cfg!(feature = "sys-lib-tesseract") { + let lib = pkg_config::probe_library("tesseract").unwrap(); + make_flags.push(format!( + "SYS_TESSERACT_CFLAGS={}", + lib.include_paths + .iter() + .map(|p| format!("-I{}", p.display())) + .collect::>() + .join(" ") + )); + } + // + // The mupdf Makefile does not do a very good job of detecting + // and acting on cross-compilation, so we'll let the `cc` crate do it. + let c_compiler = build.get_compiler(); + let cc = c_compiler.path().to_string_lossy(); + let c_flags = c_compiler.cflags_env(); + + let cxx_compiler = build.cpp(true).get_compiler(); + let cxx = cxx_compiler.path().to_string_lossy(); + let cxx_flags = cxx_compiler.cflags_env(); + + make_flags.push(format!("CC={}", cc)); + make_flags.push(format!("CXX={}", cxx)); + make_flags.push(format!("XCFLAGS={}", c_flags.to_string_lossy())); + make_flags.push(format!("XCXXFLAGS={}", cxx_flags.to_string_lossy())); + + // Enable parallel compilation + if let Ok(n) = std::thread::available_parallelism() { + make_flags.push(format!("-j{}", n)); + } + + let make = if cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd" + )) { + "gmake" + } else { + "make" + }; + let output = Command::new(make) + .args(&make_flags) + .current_dir(&build_dir_str) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .output() + .expect("make failed"); + if !output.status.success() { + panic!("Build error, exit code {}", output.status.code().unwrap()); + } + println!("cargo:rustc-link-search=native={}", &build_dir_str); + println!("cargo:rustc-link-lib=static=mupdf"); + // println!("cargo:rustc-link-lib=static=mupdf-pkcs7"); + println!("cargo:rustc-link-lib=static=mupdf-third"); + // println!("cargo:rustc-link-lib=static=mupdf-threads"); +} + fn main() { fail_on_empty_directory("mupdf"); println!("cargo:rerun-if-changed=wrapper.h");