Skip to content

Commit

Permalink
Update the included bindings + add a buildtime_bindgen feature flag…
Browse files Browse the repository at this point in the history
… that allows to generate the bindings at compile time
  • Loading branch information
weiznich committed Dec 8, 2023
1 parent 411049d commit 8b84bfc
Show file tree
Hide file tree
Showing 6 changed files with 2,384 additions and 486 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-2019]
features: [default, bundled]
features: [default, bundled, buildtime_bindgen]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
Expand All @@ -33,6 +33,7 @@ jobs:
run: |
echo "RUSTFLAGS=-D warnings" >> $GITHUB_ENV
echo "RUSTDOCFLAGS=-D warnings" >> $GITHUB_ENV
echo "BINDGEN_EXTRA_CLANG_ARGS=-I./pq-src/source/src/interfaces/libpq/ -I./pq-src/source/src/include/" >> $GITHUB_ENV
- name: Install postgres (Linux)
if: runner.os == 'Linux' && matrix.features == 'default'
run: |
Expand Down
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ members = ["pq-src"]
name = "pq_sys"

[dependencies]
pq-src = { path = "pq-src", optional = true }
pq-src = { path = "pq-src", version = "0.1", optional = true }

[build-dependencies]
pkg-config = { version = "0.3.0", optional = true }
bindgen = { version = "0.69.1", optional = true }

[target.'cfg(target_env = "msvc")'.build-dependencies]
vcpkg = "0.2.6"

[features]
default = []
bundled = ["pq-src"]
buildtime_bindgen = ["dep:bindgen"]
90 changes: 60 additions & 30 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#[cfg(feature="pkg-config")]
#[cfg(feature = "pkg-config")]
extern crate pkg_config;

#[cfg(target_env = "msvc")]
extern crate vcpkg;

use std::process::Command;
use std::env;
use std::path::PathBuf;
use std::fmt::{self, Display};
use std::path::PathBuf;
use std::process::Command;

enum LinkType {
Static,
Dynamic
Dynamic,
}

impl Display for LinkType {
Expand All @@ -32,19 +32,19 @@ impl LinkingOptions {
fn from_name_and_type(lib_name: &'static str, tpe: LinkType) -> Self {
LinkingOptions {
linking_type: Some(tpe),
lib_name
lib_name,
}
}
fn from_name(lib_name: &'static str) -> Self {
LinkingOptions {
linking_type: None,
lib_name
lib_name,
}
}

fn from_env() -> Self {
// On Windows-MSVC, always link dynamically
if cfg!(all(windows, target_env="msvc")) {
if cfg!(all(windows, target_env = "msvc")) {
return LinkingOptions::from_name_and_type("libpq", LinkType::Dynamic);
}

Expand All @@ -55,7 +55,10 @@ impl LinkingOptions {

// Examine the per-target env vars
if let Ok(target) = env::var("TARGET") {
let pg_config_for_target = format!("PQ_LIB_STATIC_{}", target.to_ascii_uppercase().replace("-", "_"));
let pg_config_for_target = format!(
"PQ_LIB_STATIC_{}",
target.to_ascii_uppercase().replace("-", "_")
);
println!("cargo:rerun-if-env-changed={}", pg_config_for_target);
if env::var_os(&pg_config_for_target).is_some() {
return LinkingOptions::from_name_and_type("pq", LinkType::Static);
Expand All @@ -77,11 +80,28 @@ impl Display for LinkingOptions {
}

fn main() {
if cfg!(feature = "bundled") && cfg!(feature = "buildtime_bindgen") {
panic!("Combining the `bundled` and `builtime_bindgen` feature is not supported");
}
if cfg!(feature = "bundled") {
// everything else is handled
// everything else is handled
// by pq-src
return;
}
#[cfg(feature = "buildtime_bindgen")]
{
let bindings = bindgen::Builder::default()
.rustified_enum(".*")
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");

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

#[cfg(target_os = "windows")]
println!("cargo:rustc-link-lib=libpq");
Expand All @@ -92,19 +112,22 @@ fn main() {

// if target is specified the more concrete pq_lib_dir overwrites a more general one
let lib_dir = if let Ok(target) = env::var("TARGET") {
let pq_lib_dir_for_target = format!("PQ_LIB_DIR_{}", target.to_ascii_uppercase().replace("-", "_"));
check_and_use_lib_dir(&pq_lib_dir_for_target).or_else(|_| check_and_use_lib_dir("PQ_LIB_DIR"))
}
else{
let pq_lib_dir_for_target = format!(
"PQ_LIB_DIR_{}",
target.to_ascii_uppercase().replace("-", "_")
);
check_and_use_lib_dir(&pq_lib_dir_for_target)
.or_else(|_| check_and_use_lib_dir("PQ_LIB_DIR"))
} else {
check_and_use_lib_dir("PQ_LIB_DIR")
};

if let Ok(lib_dir) = lib_dir {
println!("cargo:rustc-link-search=native={}", lib_dir);
} else if configured_by_pkg_config() {
return // pkg_config does everything for us, including output for cargo
return; // pkg_config does everything for us, including output for cargo
} else if configured_by_vcpkg() {
return // vcpkg does everything for us, including output for cargo
return; // vcpkg does everything for us, including output for cargo
} else if let Some(path) = pg_config_output("--libdir") {
let path = replace_homebrew_path_on_mac(path);
println!("cargo:rustc-link-search=native={}", path);
Expand All @@ -124,42 +147,49 @@ fn configured_by_pkg_config() -> bool {

#[cfg(target_env = "msvc")]
fn configured_by_vcpkg() -> bool {
vcpkg::find_package("libpq").map(|_| {
println!("cargo:rustc-link-lib=crypt32");
println!("cargo:rustc-link-lib=gdi32");
println!("cargo:rustc-link-lib=user32");
println!("cargo:rustc-link-lib=secur32");
println!("cargo:rustc-link-lib=shell32");
println!("cargo:rustc-link-lib=wldap32");
}).is_ok()
vcpkg::find_package("libpq")
.map(|_| {
println!("cargo:rustc-link-lib=crypt32");
println!("cargo:rustc-link-lib=gdi32");
println!("cargo:rustc-link-lib=user32");
println!("cargo:rustc-link-lib=secur32");
println!("cargo:rustc-link-lib=shell32");
println!("cargo:rustc-link-lib=wldap32");
})
.is_ok()
}

#[cfg(not(target_env = "msvc"))]
fn configured_by_vcpkg() -> bool {
false
}

fn check_and_use_lib_dir(var_name: &str) -> Result<String, env::VarError>{
fn check_and_use_lib_dir(var_name: &str) -> Result<String, env::VarError> {
println!("cargo:rerun-if-env-changed={:?}", var_name);
println!("{:?} = {:?}", var_name , env::var(var_name));
println!("{:?} = {:?}", var_name, env::var(var_name));

let pq_lib_dir = env::var(var_name);
if let Ok(pg_lib_path) = pq_lib_dir.clone() {
let path = PathBuf::from(&pg_lib_path);
let path = PathBuf::from(&pg_lib_path);
if !path.exists() {
panic!("Folder {:?} doesn't exist in the configured path: {:?}", var_name, path);
panic!(
"Folder {:?} doesn't exist in the configured path: {:?}",
var_name, path
);
}
}
pq_lib_dir
}

fn pg_config_path() -> PathBuf {
if let Ok(target) = env::var("TARGET") {
let pg_config_for_target = &format!("PG_CONFIG_{}", target.to_ascii_uppercase().replace("-", "_"));
let pg_config_for_target = &format!(
"PG_CONFIG_{}",
target.to_ascii_uppercase().replace("-", "_")
);
println!("cargo:rerun-if-env-changed={}", pg_config_for_target);
if let Some(pg_config_path) = env::var_os(pg_config_for_target) {

let path = PathBuf::from(&pg_config_path);
let path = PathBuf::from(&pg_config_path);

if !path.exists() {
panic!("pg_config doesn't exist in the configured path: {:?}", path);
Expand Down
Loading

0 comments on commit 8b84bfc

Please sign in to comment.