view libpam-sys/libpam-sys-impls/build.rs @ 108:e97534be35e3

Make some proc macros for doing cfg-like stuff for PAM impls.
author Paul Fisher <paul@pfish.zone>
date Sat, 28 Jun 2025 00:34:45 -0400
parents
children bb465393621f
line wrap: on
line source

use strum::EnumString;

fn main() {
    let pam_impl = match option_env!("LIBPAMSYS_IMPL") {
        // The default option: Guess what PAM impl we're using based on OS.
        None => {
            // Otherwise, guess what PAM impl we're using based on the OS.
            if cfg!(target_os = "linux") {
                PamImpl::LinuxPam
            } else if cfg!(any(
                target_os = "macos",
                target_os = "freebsd",
                target_os = "netbsd",
                target_os = "dragonfly",
                target_os = "openbsd"
            )) {
                PamImpl::OpenPam
            } else if cfg!(any()) {
                PamImpl::Illumos
            } else {
                PamImpl::MinimalOpenPam
            }
        }
        Some("_detect") => {
            // Detect which impl it is from system headers.
            if header_exists("security/_pam_types.h") {
                PamImpl::LinuxPam
            } else if header_exists("security/openpam.h") {
                PamImpl::OpenPam
            } else if header_exists("security/pam_appl.h") {
                // We figure we're *probably* on Illumos or something like that.
                PamImpl::Illumos
            } else {
                // If all else fails, assume the bare minimum.
                PamImpl::MinimalOpenPam
            }
        }
        Some(other) => match PamImpl::try_from(other) {
            Ok(i) => i,
            Err(_) => panic!("unknown PAM implementation {other:?}")
        }
    };
    println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}");
}

#[derive(Debug, EnumString)]
enum PamImpl {
    Illumos,
    LinuxPam,
    OpenPam,
    MinimalOpenPam,
}

fn header_exists(header: &str) -> bool {
    bindgen::Builder::default()
        .blocklist_item(".*")
        .header_contents("header.h", &format!("#include <{header}>"))
        .generate()
        .is_ok()
}