use std::{
env,
path::{Path, PathBuf},
};
use tectonic_cfg_support::target_cfg;
use tectonic_dep_support::{Backend, Configuration, Dependency, Spec};
struct FontconfigSpec;
impl Spec for FontconfigSpec {
fn get_pkgconfig_spec(&self) -> &str {
"fontconfig"
}
fn get_vcpkg_spec(&self) -> &[&str] {
&["fontconfig"]
}
}
struct PlatformLayoutDeps<'a> {
fontconfig: Option<Dependency<'a, FontconfigSpec>>,
}
impl<'a> PlatformLayoutDeps<'a> {
pub fn new(dep_cfg: &'a Configuration, is_mac_os: bool) -> Self {
let fontconfig = if is_mac_os {
None
} else {
Some(Dependency::probe(FontconfigSpec, dep_cfg))
};
PlatformLayoutDeps { fontconfig }
}
pub fn foreach_include_path<F>(&self, f: F)
where
F: FnMut(&Path),
{
if let Some(ref fc) = self.fontconfig {
fc.foreach_include_path(f);
}
}
pub fn emit(&self) {
if let Some(ref fc) = self.fontconfig {
fc.emit();
}
}
}
fn main() {
let target = env::var("TARGET").unwrap();
let out_dir = env::var("OUT_DIR").unwrap();
let manifest_dir: PathBuf = env::var("CARGO_MANIFEST_DIR").unwrap().into();
let is_mac_os = target_cfg!(target_os = "macos");
let dep_cfg = Configuration::default();
let deps = PlatformLayoutDeps::new(&dep_cfg, is_mac_os);
let core_include_dir = env::var("DEP_TECTONIC_BRIDGE_CORE_INCLUDE").unwrap();
let freetype2_include_path = env::var("DEP_FREETYPE2_INCLUDE_PATH").unwrap();
let graphite2_include_path = env::var("DEP_GRAPHITE2_INCLUDE_PATH").unwrap();
let graphite2_static = !env::var("DEP_GRAPHITE2_DEFINE_STATIC").unwrap().is_empty();
let harfbuzz_include_path = env::var("DEP_HARFBUZZ_INCLUDE_PATH").unwrap();
let icu_include_path = env::var("DEP_ICUUC_INCLUDE_PATH").unwrap();
let mut cppcfg = cc::Build::new();
let cppflags = [
"-std=c++14",
"-Wall",
"-Wdate-time",
"-Wendif-labels",
"-Wextra",
"-Wformat=2",
"-Wlogical-op",
"-Wmissing-declarations",
"-Wmissing-include-dirs",
"-Wpointer-arith",
"-Wredundant-decls",
"-Wsuggest-attribute=noreturn",
"-Wsuggest-attribute=format",
"-Wshadow",
"-Wswitch-bool",
"-Wundef",
"-Wextra-semi",
"-Wno-unused-parameter",
"-Wno-implicit-fallthrough",
"-fno-exceptions",
"-fno-rtti",
];
for flag in &cppflags {
cppcfg.flag_if_supported(flag);
}
fn compile(cfg: &mut cc::Build, s: &str) {
cfg.file(s);
println!("cargo:rerun-if-changed={s}");
}
cppcfg
.cpp(true)
.flag("-Wall")
.include("layout")
.include(&core_include_dir);
deps.foreach_include_path(|p| {
cppcfg.include(p);
});
for item in harfbuzz_include_path.split(';') {
cppcfg.include(item);
}
for item in freetype2_include_path.split(';') {
cppcfg.include(item);
}
for item in graphite2_include_path.split(';') {
cppcfg.include(item);
}
for item in icu_include_path.split(';') {
cppcfg.include(item);
}
compile(&mut cppcfg, "layout/xetex-XeTeXFontInst.cpp");
compile(&mut cppcfg, "layout/xetex-XeTeXFontMgr.cpp");
compile(&mut cppcfg, "layout/xetex-XeTeXLayoutInterface.cpp");
if graphite2_static {
cppcfg.define("GRAPHITE2_STATIC", "1");
}
if is_mac_os {
cppcfg.define("XETEX_MAC", Some("1"));
compile(&mut cppcfg, "layout/xetex-XeTeXFontInst_Mac.cpp");
compile(&mut cppcfg, "layout/xetex-XeTeXFontMgr_Mac.mm");
println!("cargo:rustc-link-lib=framework=Foundation");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=CoreGraphics");
println!("cargo:rustc-link-lib=framework=CoreText");
println!("cargo:rustc-link-lib=framework=AppKit");
}
if !is_mac_os {
compile(&mut cppcfg, "layout/xetex-XeTeXFontMgr_FC.cpp");
}
if target.contains("-msvc") {
cppcfg.flag("/EHsc");
}
cppcfg.compile("libtectonic_xetex_layout.a");
deps.emit();
if dep_cfg.backend == Backend::Vcpkg && target.contains("-linux-") {
println!("cargo:rustc-link-lib=icudata");
}
let mut main_header_src = manifest_dir;
main_header_src.push("layout");
main_header_src.push("tectonic_xetex_layout.h");
let mut main_header_dest = PathBuf::from(out_dir.clone());
main_header_dest.push("tectonic_xetex_layout.h");
std::fs::copy(&main_header_src, &main_header_dest).expect("failed to copy main header");
print!("cargo:include-path={out_dir}");
for item in harfbuzz_include_path.split(';') {
print!(";{item}");
}
for item in freetype2_include_path.split(';') {
print!(";{item}");
}
for item in graphite2_include_path.split(';') {
print!(";{item}");
}
for item in icu_include_path.split(';') {
print!(";{item}");
}
println!();
}