use crate::cpp_lib_builder::CMakeVar;
use crate::errors::{bail, Result};
use crate::target::{Condition, Target};
use serde_derive::{Deserialize, Serialize};
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CppBuildConfig {
items: Vec<CppBuildConfigItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct CppBuildConfigItem {
condition: Condition,
data: CppBuildConfigData,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CppLibraryType {
Shared,
Static,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CppBuildConfigData {
linked_libs: Vec<String>,
linked_frameworks: Vec<String>,
compiler_flags: Vec<String>,
library_type: Option<CppLibraryType>,
cmake_vars: Vec<CMakeVar>,
}
impl CppBuildConfigData {
pub fn new() -> Self {
Self::default()
}
pub fn add_linked_lib<P: Into<String>>(&mut self, lib: P) {
self.linked_libs.push(lib.into());
}
pub fn add_linked_framework<P: Into<String>>(&mut self, lib: P) {
self.linked_frameworks.push(lib.into());
}
pub fn add_compiler_flag<P: Into<String>>(&mut self, lib: P) {
self.compiler_flags.push(lib.into());
}
pub fn add_compiler_flags<Item, Iter>(&mut self, items: Iter)
where
Item: Into<String>,
Iter: IntoIterator<Item = Item>,
{
for item in items {
self.compiler_flags.push(item.into());
}
}
pub fn add_cmake_var(&mut self, var: CMakeVar) {
self.cmake_vars.push(var);
}
pub fn set_library_type(&mut self, t: CppLibraryType) {
self.library_type = Some(t);
}
pub fn linked_libs(&self) -> &[String] {
&self.linked_libs
}
pub fn linked_frameworks(&self) -> &[String] {
&self.linked_frameworks
}
pub fn compiler_flags(&self) -> &[String] {
&self.compiler_flags
}
pub fn library_type(&self) -> Option<CppLibraryType> {
self.library_type
}
fn add_from(&mut self, other: &CppBuildConfigData) -> Result<()> {
self.linked_libs.append(&mut other.linked_libs.clone());
self.linked_frameworks
.extend_from_slice(&other.linked_frameworks);
self.compiler_flags.extend_from_slice(&other.compiler_flags);
if self.library_type.is_some() {
if other.library_type.is_some() && other.library_type != self.library_type {
bail!("conflicting library types specified");
}
} else {
self.library_type = other.library_type;
}
self.cmake_vars.extend_from_slice(&other.cmake_vars);
Ok(())
}
pub fn cmake_vars(&self) -> &[CMakeVar] {
&self.cmake_vars
}
}
impl CppBuildConfig {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, condition: Condition, data: CppBuildConfigData) {
self.items.push(CppBuildConfigItem { condition, data });
}
pub fn eval(&self, target: &Target) -> Result<CppBuildConfigData> {
let mut data = CppBuildConfigData::default();
for item in &self.items {
if item.condition.eval(target) {
data.add_from(&item.data)?;
}
}
Ok(data)
}
}
use crate::env_var_names;
use std::path::PathBuf;
#[derive(Debug, Default, Clone)]
pub struct CppBuildPaths {
lib_paths: Vec<PathBuf>,
framework_paths: Vec<PathBuf>,
include_paths: Vec<PathBuf>,
}
impl CppBuildPaths {
pub fn new() -> Self {
Self::default()
}
pub fn add_lib_path<P: Into<PathBuf>>(&mut self, path: P) {
let path = path.into();
if !self.lib_paths.contains(&path) {
self.lib_paths.push(path);
}
}
pub fn add_framework_path<P: Into<PathBuf>>(&mut self, path: P) {
let path = path.into();
if !self.framework_paths.contains(&path) {
self.framework_paths.push(path);
}
}
pub fn add_include_path<P: Into<PathBuf>>(&mut self, path: P) {
let path = path.into();
if !self.include_paths.contains(&path) {
self.include_paths.push(path);
}
}
pub fn apply_env(&mut self) {
use std::env;
if let Ok(paths) = env::var(env_var_names::LIBRARY_PATH) {
self.lib_paths = env::split_paths(&paths)
.filter(|s| !s.as_os_str().is_empty())
.collect();
}
if let Ok(paths) = env::var(env_var_names::FRAMEWORK_PATH) {
self.framework_paths = env::split_paths(&paths)
.filter(|s| !s.as_os_str().is_empty())
.collect();
}
if let Ok(paths) = env::var(env_var_names::INCLUDE_PATH) {
self.include_paths = env::split_paths(&paths)
.filter(|s| !s.as_os_str().is_empty())
.collect();
}
}
pub fn lib_paths(&self) -> &[PathBuf] {
&self.lib_paths
}
pub fn framework_paths(&self) -> &[PathBuf] {
&self.framework_paths
}
pub fn include_paths(&self) -> &[PathBuf] {
&self.include_paths
}
}