1use eyre::eyre;
11use pgrx_pg_config::{
12 PgConfig, PgConfigSelector, Pgrx, SUPPORTED_VERSIONS, is_supported_major_version,
13};
14
15pub mod build;
16
17fn is_for_release() -> bool {
18 env_tracked("PGRX_PG_SYS_GENERATE_BINDINGS_FOR_RELEASE").as_deref() == Some("1")
19}
20
21pub fn detect_pg_config() -> eyre::Result<Vec<(u16, PgConfig)>> {
24 let pg_configs: Vec<(u16, PgConfig)> = if is_for_release() {
25 Pgrx::from_config()?.iter(PgConfigSelector::All)
27 .map(|r| r.expect("invalid pg_config"))
28 .map(|c| (c.major_version().expect("invalid major version"), c))
29 .filter_map(|t| {
30 if is_supported_major_version(t.0) {
31 Some(t)
32 } else {
33 println!(
34 "cargo:warning={} contains a configuration for pg{}, which pgrx does not support.",
35 Pgrx::config_toml()
36 .expect("Could not get PGRX configuration TOML")
37 .to_string_lossy(),
38 t.0
39 );
40 None
41 }
42 })
43 .collect()
44 } else {
45 let mut found = Vec::new();
46 for pgver in SUPPORTED_VERSIONS() {
47 if env_tracked(&format!("CARGO_FEATURE_PG{}", pgver.major)).is_some() {
48 found.push(pgver);
49 }
50 }
51 let found_ver = match &found[..] {
52 [ver] => ver,
53 [] => {
54 return Err(eyre!(
55 "Did not find `pg$VERSION` feature. `pgrx-pg-sys` requires one of {} to be set",
56 SUPPORTED_VERSIONS()
57 .iter()
58 .map(|pgver| format!("`pg{}`", pgver.major))
59 .collect::<Vec<_>>()
60 .join(", ")
61 ));
62 }
63 versions => {
64 return Err(eyre!(
65 "Multiple `pg$VERSION` features found.\n`--no-default-features` may be required.\nFound: {}",
66 versions
67 .iter()
68 .map(|version| format!("pg{}", version.major))
69 .collect::<Vec<String>>()
70 .join(", ")
71 ));
72 }
73 };
74
75 let found_major = found_ver.major;
76 if let Ok(pg_config) = PgConfig::from_env() {
77 let major_version = pg_config.major_version()?;
78
79 if major_version != found_major {
80 panic!(
81 "Feature flag `pg{found_major}` does not match version from the environment-described PgConfig (`{major_version}`)"
82 )
83 }
84 vec![(major_version, pg_config)]
85 } else {
86 let specific = Pgrx::from_config()?.get(&format!("pg{}", found_ver.major))?;
87 vec![(found_ver.major, specific)]
88 }
89 };
90 Ok(pg_configs)
91}
92
93fn env_tracked(s: &str) -> Option<String> {
94 const CARGO_KEYS: &[&str] = &[
97 "BROWSER",
98 "DEBUG",
99 "DOCS_RS",
100 "HOST",
101 "HTTP_PROXY",
102 "HTTP_TIMEOUT",
103 "NUM_JOBS",
104 "OPT_LEVEL",
105 "OUT_DIR",
106 "PATH",
107 "PROFILE",
108 "TARGET",
109 "TERM",
110 ];
111
112 let is_cargo_key =
113 s.starts_with("CARGO") || s.starts_with("RUST") || CARGO_KEYS.binary_search(&s).is_ok();
114
115 if !is_cargo_key {
116 println!("cargo:rerun-if-env-changed={s}");
120 }
121 std::env::var(s).ok()
122}