// The build for pcre2-sys currently does roughly the following:
//
//   1. Use the PCRE2 system library as reported by pkg-config if it exists
//      and only if we don't explicitly want a static build.
//   2. Otherwise, statically build PCRE2 by hand.
//
// For step 1, we permit opting out of using the system library via either
// explicitly setting the PCRE2_SYS_STATIC environment variable or if we
// otherwise believe we want a static build (e.g., when building with MUSL).
//
// For step 2, we roughly follow the directions as laid out in
// pcre2/NON-AUTOTOOLS-BUILD. It's pretty straight-forward: copy a few files,
// set a few defines and then build it. We can get away with a pretty stripped
// down setup here since the PCRE2 build setup also handles various command
// line tools (like pcre2grep) and its test infrastructure, and we needn't
// concern ourselves with that.
//
// It is plausible that this build script will need to evolve to do better
// platform detection for the various PCRE2 settings, but this should work
// as-is on Windows, Linux and macOS.

extern crate cc;
extern crate pkg_config;

use std::process::Command;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

// Files that PCRE2 needs to compile.
const FILES: &'static [&'static str] = &[
   "pcre2_auto_possess.c",
   "pcre2_compile.c",
   "pcre2_config.c",
   "pcre2_context.c",
   "pcre2_convert.c",
   "pcre2_dfa_match.c",
   "pcre2_error.c",
   "pcre2_extuni.c",
   "pcre2_find_bracket.c",
   "pcre2_jit_compile.c",
   "pcre2_maketables.c",
   "pcre2_match.c",
   "pcre2_match_data.c",
   "pcre2_newline.c",
   "pcre2_ord2utf.c",
   "pcre2_pattern_info.c",
   "pcre2_serialize.c",
   "pcre2_string_utils.c",
   "pcre2_study.c",
   "pcre2_substitute.c",
   "pcre2_substring.c",
   "pcre2_tables.c",
   "pcre2_ucd.c",
   "pcre2_valid_utf.c",
   "pcre2_xclass.c",
];

fn main() {
    println!("cargo:rerun-if-env-changed=PCRE2_SYS_STATIC");

    let target = env::var("TARGET").unwrap();
    let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());

    // Don't link to a system library if we want a static build.
    let want_static = pcre2_sys_static().unwrap_or(target.contains("musl"));
    if !want_static && pkg_config::probe_library("libpcre2-8").is_ok() {
        return;
    }

    // For a static build, make sure our PCRE2 submodule has been loaded.
    if has_git() && !Path::new("pcre2/.git").exists() {
        Command::new("git")
            .args(&["submodule", "update", "--init"])
            .status()
            .unwrap();
    }

    // Set some config options. We mostly just use the default values. We do
    // this in lieu of patching config.h since it's easier.
    let mut builder = cc::Build::new();
    builder
        .define("PCRE2_CODE_UNIT_WIDTH", "8")
        .define("HAVE_STDLIB_H", "1")
        .define("HAVE_MEMMOVE", "1")
        .define("HEAP_LIMIT", "20000000")
        .define("LINK_SIZE", "2")
        .define("MATCH_LIMIT", "10000000")
        .define("MATCH_LIMIT_DEPTH", "10000000")
        .define("MAX_NAME_COUNT", "10000")
        .define("MAX_NAME_SIZE", "32")
        .define("NEWLINE_DEFAULT", "2")
        .define("PARENS_NEST_LIMIT", "250")
        .define("PCRE2_STATIC", "1")
        .define("STDC_HEADERS", "1")
        .define("SUPPORT_PCRE2_8", "1")
        .define("SUPPORT_UNICODE", "1");
    if target.contains("windows") {
        builder.define("HAVE_WINDOWS_H", "1");
    }

    enable_jit(&target, &mut builder);

    // Copy PCRE2 headers. Typically, `./configure` would do this for us
    // automatically, but since we're compiling by hand, we do it ourselves.
    let include = out.join("include");
    fs::create_dir_all(&include).unwrap();
    fs::copy("pcre2/src/config.h.generic", include.join("config.h")).unwrap();
    fs::copy("pcre2/src/pcre2.h.generic", include.join("pcre2.h")).unwrap();

    // Same deal for chartables. Just use the default.
    let src = out.join("src");
    fs::create_dir_all(&src).unwrap();
    fs::copy(
        "pcre2/src/pcre2_chartables.c.dist",
        src.join("pcre2_chartables.c"),
    ).unwrap();

    // Build everything.
    builder
        .include("pcre2/src")
        .include(&include)
        .file(src.join("pcre2_chartables.c"));
    for file in FILES {
        builder.file(Path::new("pcre2/src").join(file));
    }

    if env::var("PCRE2_SYS_DEBUG").unwrap_or(String::new()) == "1" {
        builder.debug(true);
    }
    builder.compile("libpcre2.a");
}

fn has_git() -> bool {
    Command::new("git").arg("--help")
        .status()
        .map(|s| s.success())
        .unwrap_or(false)
}

fn pcre2_sys_static() -> Option<bool> {
    match env::var("PCRE2_SYS_STATIC") {
        Err(_) => None,
        Ok(s) => {
            if s == "1" {
                Some(true)
            } else if s == "0" {
                Some(false)
            } else {
                None
            }
        }
    }
}

// On `aarch64-apple-ios` clang fails with the following error.
//
//     Undefined symbols for architecture arm64:
//       "___clear_cache", referenced from:
//           _sljit_generate_code in libforeign.a(pcre2_jit_compile.o)
//     ld: symbol(s) not found for architecture arm64
//
// aarch64-apple-tvos         https://bugreports.qt.io/browse/QTBUG-62993?gerritReviewStatus=All
// aarch64-apple-darwin       https://github.com/Homebrew/homebrew-core/pull/57419
// x86_64-apple-ios           disabled for device–simulator consistency (not tested)
// x86_64-apple-tvos          disabled for device–simulator consistency (not tested)
// armv7-apple-ios            assumed equivalent to aarch64-apple-ios (not tested)
// armv7s-apple-ios           assumed equivalent to aarch64-apple-ios (not tested)
// i386-apple-ios             assumed equivalent to aarch64-apple-ios (not tested)
// x86_64-apple-ios-macabi    disabled out of caution (not tested) (needs attention)
//
// We may want to monitor developments on the `aarch64-apple-darwin` front as they may end up
// propagating to all `aarch64`-based targets and the `x86_64` equivalents.
fn enable_jit(target: &str, builder: &mut cc::Build) {
    if !target.starts_with("aarch64-apple") &&
        !target.contains("apple-ios") &&
        !target.contains("apple-tvos") {
        builder.define("SUPPORT_JIT", "1");
    }
}
