Skip to main content

libperl_config/
perl_config.rs

1use super::process_util::*;
2
3use super::PerlCommand;
4
5use std::collections::HashMap;
6
7type ConfigDict = HashMap<String, String>;
8
9use chrono::prelude::*;
10
11pub struct PerlConfig {
12    command: PerlCommand,
13    pub dict: ConfigDict,
14}
15
16impl Default for PerlConfig {
17     fn default() -> Self {
18        let cmd = PerlCommand::default();
19        let dict = read_config(&cmd, &[]).expect("Failed to read Config.pm");
20        Self {
21            command: cmd,
22            dict: dict,
23        }
24    }
25}
26
27impl PerlConfig {
28
29    pub fn new(perl: &str) -> Self {
30        let cmd = PerlCommand::new(perl);
31        let dict = read_config(&cmd, &[]).expect("Failed to read Config.pm");
32        Self {
33            command: cmd,
34            dict: dict,
35        }
36    }
37
38    pub fn command(&self, args: &[&str]) -> Command {
39        self.command.command(args)
40    }
41
42    pub fn read_ccopts(&self) -> Result<Vec<String>, Error> {
43        self.command.read_ccopts()
44    }
45
46    pub fn read_ldopts(&self) -> Result<Vec<String>, Error> {
47        self.command.read_ldopts()
48    }
49
50    pub fn is_defined(&self, name: &str) -> Result<bool, Error> {
51        if let Some(value) = self.dict.get(name) {
52            Ok(value == "define")
53        } else {
54            Err(other_error("No such entry".to_string()))
55        }
56    }
57
58    pub fn emit_cargo_ldopts(&self) {
59        self.command.emit_cargo_ldopts()
60    }
61
62    pub fn perl_api_version(&self) -> i32 {
63        let config = &self.dict["PERL_API_VERSION"];
64        let config = config.trim();
65        i32::from_str_radix(String::from(config).trim(), 10).unwrap()
66    }
67
68    pub fn emit_all_perlapi_versions(&self, min: i32) {
69        let local_time = Local::now();
70        let current_year = local_time.year();
71        println!("# curyear = {}", current_year);
72        let yearly_perl_ver = self.yearly_perl_version(current_year);
73        println!("# yearly perl = {}", yearly_perl_ver);
74        self.emit_perlapi_vers(min, yearly_perl_ver)
75    }
76
77    pub fn yearly_perl_version(&self, year: i32) -> i32 {
78        (year - 2004) * 2
79    }
80
81    pub fn emit_perlapi_vers(&self, min: i32, max: i32) {
82        let ver = self.perl_api_version();
83        for v in min..=max {
84            if v % 2 == 1 {
85                continue;
86            }
87            // Emit check-cfg for all possible versions (Rust 1.80+)
88            println!("cargo::rustc-check-cfg=cfg(perlapi_ver{})", v);
89            if ver >= v {
90                println!("cargo:rustc-cfg=perlapi_ver{}", v);
91            }
92        }
93    }
94
95    pub fn emit_features(&self, configs: &[&str]) {
96        for &cfg in configs.iter() {
97            println!("# perl config {} = {:?}", cfg, self.dict.get(&String::from(cfg)));
98            // Emit check-cfg for all features (Rust 1.80+)
99            println!("cargo::rustc-check-cfg=cfg(perl_{})", cfg);
100            if self.is_defined(cfg).unwrap() {
101                println!("cargo:rustc-cfg=perl_{}", cfg);
102            }
103        }
104    }
105}
106
107fn read_config(cmd: &PerlCommand, configs: &[&str]) -> Result<ConfigDict, Error> {
108    let config = cmd.read_raw_config(configs)?;
109    let lines = config.lines().map(String::from).collect();
110    Ok(lines_to_hashmap(lines))
111}
112
113fn lines_to_hashmap(lines: Vec<String>) -> ConfigDict {
114    let mut dict = HashMap::new();
115    for line in lines.iter() {
116        let kv: Vec<String> = line.splitn(2, '\t').map(String::from).collect();
117        if kv.len() == 2 {
118            dict.insert(kv[0].clone(), kv[1].clone());
119        }
120    }
121    dict
122}