libpostal-sys 0.1.1

Low-level wrappers for libpostal address normalization (with locks to support thread-safe initialization)
Documentation
//! Build script which builds libpostal from source and links it.
//!
//! We're not currently interested in trying to link a pre-existing system
//! version, because this is a fairly obscure library and it's not availble even
//! as an Ubuntu PPE.

use std::env;

/// The main entry point to our build script.
fn main() {
    build_libpostal();
    //bindgen_libpostal();
}

/// Use `autotools` to compile `libpostal` as a static library.
fn build_libpostal() {
    // Build `libpostal` and install it in `$OUT_DIR`.
    let mut config = autotools::Config::new("libpostal");

    // Instead of doing this, we ran `./bootstrap.sh` in `libpostal` manually,
    // and committed the output. This helps guarantee our source tree never
    // changes during `cargo publish`.
    //
    // if !Path::new("libpostal/configure").exists() {
    //     // Build `./configure` if it doesn't exist.
    //     config.reconf("-fi");
    // }

    // Get our Rust target and host.
    let rust_target = env::var("TARGET").expect("cargo should always define TARGET");
    let rust_host = env::var("HOST").expect("cargo should always define HOST");

    // When cross-compiling for M1 Macs, set `--host` appropriately. Keep in
    // mind that:
    //
    // - Rust `TARGET` is `./configure --host=`.
    // - Rust `HOST` is `./configure --build=`.
    // - `./configure --target=` is only used when building a compiler on
    //   `--build` that will run on `--host` and generate code for `--target`.
    //   But Rust _always_ supports generating code for multiple targets, so it
    //   doesn't think like this.
    //
    // I'm not sure why we need to set this manually, but it seems to be
    // necessary. We might need to do this for other combinations, but let's add
    // them as we discover them.
    if rust_target == "aarch64-apple-darwin" && rust_host != "aarch64-apple-darwin" {
        config.config_option("host", Some(&rust_target));
    }

    // If we're not on Intel, don't try to use Intel processor extensions. We
    // need to disable this manually, apparently.
    if !rust_target.starts_with("x86_64-") {
        config.disable("sse2", None);
    }

    let dst = config
        // You'll need to edit any `-Wall` out of the source tree,
        // unfortunately.
        .cflag("-Wno-error")
        // You'll need to download this manually and stick it in
        // `/usr/local/shared` or wherever the library expects it.
        .disable("data-download", None)
        // Don't allow automake, etc., to re-run. If this is allowed, it will
        // cause the input source tree to change and cause `cargo` to abort
        // publishing process. This required us to add `AM_MAINTAINER_MODE` to
        // `libpostal/configure.ac`.
        .disable("maintainer-mode", None)
        .config_option("datadir", Some("/usr/local/share/libpostal"))
        .build();

    // Emit linker arguments for `cargo`.
    println!(
        "cargo:rustc-link-search=native={}",
        dst.join("lib").display(),
    );
    println!("cargo:rustc-link-lib=static=postal");
}

// We're doing this manually for now. See lib.rs.
//
// /// Use `bindgen` to generate a Rust version of `libpostal.h`. Note that this is
// /// very low-level, and it will require `unsafe` and the Rust C FFI to use. But
// /// at least we won't need to _declare_ the C header details.
// ///
// /// This is copied from https://rust-lang.github.io/rust-bindgen/tutorial-3.html
// /// and adapted only slightly.
// fn bindgen_libpostal() {
//     // Tell cargo to invalidate the built crate whenever the wrapper changes
//     println!("cargo:rerun-if-changed=wrapper.h");

//     // The bindgen::Builder is the main entry point
//     // to bindgen, and lets you build up options for
//     // the resulting bindings.
//     let bindings = bindgen::Builder::default()
//         // The input header we would like to generate
//         // bindings for.
//         .header("wrapper.h")
//         // Tell cargo to invalidate the built crate whenever any of the
//         // included header files changed.
//         .parse_callbacks(Box::new(bindgen::CargoCallbacks))
//         // Finish the builder and generate the bindings.
//         .generate()
//         // Unwrap the Result and panic on failure.
//         .expect("Unable to generate bindings");

//     // Write the bindings to the $OUT_DIR/bindings.rs file.
//     let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
//     bindings
//         .write_to_file(out_path.join("bindings.rs"))
//         .expect("Couldn't write bindings!");
// }