1use std::path::{Path, PathBuf};
2
3use anyhow::{bail, ensure, Result};
4
5#[derive(Debug, Clone)]
6pub struct Probe {
7 pub prefix: PathBuf,
8 pub include_dirs: IncludeDirs,
9 pub lib_dirs: LibDirs,
10}
11
12#[derive(Debug, Clone)]
13pub struct IncludeDirs {
14 pub carla_source: PathBuf,
15 pub carla_third_party: PathBuf,
16 pub recast: PathBuf,
17 pub rpclib: PathBuf,
18 pub boost: PathBuf,
19 pub libpng: PathBuf,
20}
21
22#[derive(Debug, Clone)]
23pub struct LibDirs {
24 pub recast: PathBuf,
25 pub rpclib: PathBuf,
26 pub boost: PathBuf,
27 pub libpng: PathBuf,
28 pub libcarla_client: PathBuf,
29}
30
31impl IncludeDirs {
32 pub fn into_vec(self) -> Vec<PathBuf> {
33 let Self {
34 recast,
35 rpclib,
36 boost,
37 libpng,
38 carla_source,
39 carla_third_party,
40 } = self;
41 vec![
42 recast,
43 rpclib,
44 libpng,
45 boost,
46 carla_source,
47 carla_third_party,
48 ]
49 }
50}
51
52impl LibDirs {
53 pub fn into_vec(self) -> Vec<PathBuf> {
54 let Self {
55 recast,
56 rpclib,
57 boost,
58 libpng,
59 libcarla_client,
60 } = self;
61 vec![recast, rpclib, libpng, boost, libcarla_client]
62 }
63}
64
65pub fn probe<P>(carla_src_dir: P) -> Result<Probe>
66where
67 P: AsRef<Path>,
68{
69 let find_match = |pattern: &str| -> Result<_> {
70 let mut iter = glob::glob(pattern)?;
71
72 let path = match iter.next() {
73 Some(Ok(path)) => path,
74 Some(Err(err)) => return Err(err.into()),
75 None => bail!("Unable to match '{pattern}'"),
76 };
77 ensure!(
78 iter.next().is_none(),
79 "'{pattern}' matches more than one file"
80 );
81 Ok(path)
82 };
83
84 let carla_src_dir = carla_src_dir.as_ref();
85 let carla_source_dir = carla_src_dir.join("LibCarla").join("source");
86 let carla_third_party_dir = carla_source_dir.join("third-party");
87 let build_dir = carla_src_dir.join("Build");
88
89 let carla_version = std::env::var("CARLA_VERSION").unwrap_or_else(|_| "0.9.16".to_string());
91 let (boost_pattern, recast_pattern, rpclib_pattern) = match carla_version.as_str() {
92 "0.9.14" => (
93 "boost-1.80.0-c*-install",
94 "recast-0b13b0-c*-install",
95 "rpclib-v2.2.1_c5-c*-libstdcxx-install",
96 ),
97 "0.9.15" => (
98 "boost-1.80.0-c*-install",
99 "recast-c*-install",
100 "rpclib-v2.2.1_c5-c*-libstdcxx-install",
101 ),
102 "0.9.16" => (
103 "boost-1.84.0-c*-install",
104 "recast-c*-install",
105 "rpclib-v2.2.1_c5-c*-libstdcxx-install",
106 ),
107 _ => bail!(
108 "Unsupported CARLA version: {}. Supported versions: 0.9.14, 0.9.15, 0.9.16",
109 carla_version
110 ),
111 };
112
113 let recast_dir = find_match(build_dir.join(recast_pattern).to_str().unwrap())?;
114 let rpclib_dir = find_match(build_dir.join(rpclib_pattern).to_str().unwrap())?;
115 let boost_dir = find_match(build_dir.join(boost_pattern).to_str().unwrap())?;
116
117 let libpng_dir = build_dir.join("libpng-1.6.37-install");
118 ensure!(
119 libpng_dir.exists(),
120 "Unable to find '{}'",
121 libpng_dir.display()
122 );
123
124 let libcarla_client_lib_dir = build_dir
125 .join("libcarla-client-build.release")
126 .join("LibCarla")
127 .join("cmake")
128 .join("client");
129 ensure!(
130 libpng_dir.exists(),
131 "Unable to find '{}'",
132 libcarla_client_lib_dir.display()
133 );
134
135 let include_dirs = IncludeDirs {
136 carla_source: carla_source_dir,
137 carla_third_party: carla_third_party_dir,
138 recast: recast_dir.join("include"),
139 rpclib: rpclib_dir.join("include"),
140 boost: boost_dir.join("include"),
141 libpng: libpng_dir.join("include"),
142 };
143 let lib_dirs = LibDirs {
144 recast: recast_dir.join("lib"),
145 rpclib: rpclib_dir.join("lib"),
146 boost: boost_dir.join("lib"),
147 libpng: libpng_dir.join("lib"),
148 libcarla_client: libcarla_client_lib_dir,
149 };
150
151 Ok(Probe {
152 prefix: carla_src_dir.to_path_buf(),
153 include_dirs,
154 lib_dirs,
155 })
156}