Skip to content

Commit d41c6cb

Browse files
authored
Toolchain verify configs (#180)
1 parent 1215e56 commit d41c6cb

File tree

4 files changed

+196
-2
lines changed

4 files changed

+196
-2
lines changed

buildcc/lib/toolchain/include/toolchain/api/toolchain_verify.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define TOOLCHAIN_TOOLCHAIN_VERIFY_H_
1919

2020
#include <filesystem>
21+
#include <optional>
2122
#include <vector>
2223

2324
#include "env/logging.h"
@@ -42,6 +43,13 @@ namespace buildcc::base {
4243
struct VerifyToolchainConfig {
4344
std::vector<std::string> absolute_search_paths;
4445
std::vector<std::string> env_vars{"PATH"};
46+
47+
std::optional<std::string> compiler_version;
48+
std::optional<std::string> target_arch;
49+
50+
// Updates the toolchain with absolute paths once verified
51+
// If multiple toolchains are found, uses the first in the list
52+
bool update{true};
4553
};
4654

4755
/**
@@ -60,8 +68,21 @@ struct VerifiedToolchain {
6068

6169
template <typename T> class ToolchainVerify {
6270
public:
71+
/**
72+
* @brief Verify your toolchain executables by searching your operating system
73+
* paths
74+
* Only add the verified path IF all toolchain executables are matched
75+
*
76+
* @param config Search paths to find toolchains
77+
* @return std::vector<VerifiedToolchain> Operating system can contain
78+
* multiple toolchains of similar names with different versions. Collect all
79+
* of them
80+
*/
6381
std::vector<VerifiedToolchain>
6482
Verify(const VerifyToolchainConfig &config = VerifyToolchainConfig());
83+
84+
protected:
85+
VerifiedToolchain verified_toolchain_;
6586
};
6687

6788
} // namespace buildcc::base

buildcc/lib/toolchain/include/toolchain/toolchain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class Toolchain : public ToolchainVerify<Toolchain> {
5858
const std::string &GetArchiver() const { return archiver_; }
5959
const std::string &GetLinker() const { return linker_; }
6060

61+
private:
62+
friend class ToolchainVerify<Toolchain>;
63+
6164
private:
6265
Id id_;
6366
std::string name_;

buildcc/lib/toolchain/src/api/toolchain_verify.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ ToolchainVerify<T>::Verify(const VerifyToolchainConfig &config) {
197197
}
198198

199199
std::vector<VerifiedToolchain> verified_toolchains;
200-
const T &t = static_cast<const T &>(*this);
200+
T &t = static_cast<T &>(*this);
201201

202202
ToolchainMatcher matcher(t);
203203
matcher.FillWithToolchainFilenames();
@@ -233,13 +233,53 @@ ToolchainVerify<T>::Verify(const VerifyToolchainConfig &config) {
233233
vt.path = p;
234234
vt.compiler_version = env::trim(GetCompilerVersion(p, t).value_or(""));
235235
vt.target_arch = env::trim(GetCompilerArchitecture(p, t).value_or(""));
236-
verified_toolchains.push_back(vt);
236+
237+
// Check add
238+
bool add{true};
239+
if (config.compiler_version.has_value()) {
240+
add = add && (config.compiler_version.value() == vt.compiler_version);
241+
}
242+
if (config.target_arch.has_value()) {
243+
add = add && (config.target_arch.value() == vt.target_arch);
244+
}
245+
if (add) {
246+
verified_toolchains.push_back(vt);
247+
}
237248
}
238249

239250
// Reset
240251
matcher.FillWithToolchainFilenames();
241252
}
242253

254+
if (config.update && !verified_toolchains.empty()) {
255+
constexpr const char *os_executable_ext =
256+
buildcc::env::get_os_executable_extension();
257+
buildcc::env::assert_fatal<os_executable_ext != nullptr>(
258+
"OS not supported");
259+
260+
verified_toolchain_ = verified_toolchains[0];
261+
t.asm_compiler_ = (verified_toolchain_.path /
262+
fmt::format("{}{}", t.asm_compiler_, os_executable_ext))
263+
.make_preferred()
264+
.string();
265+
t.c_compiler_ = (verified_toolchain_.path /
266+
fmt::format("{}{}", t.c_compiler_, os_executable_ext))
267+
.make_preferred()
268+
.string();
269+
t.cpp_compiler_ = (verified_toolchain_.path /
270+
fmt::format("{}{}", t.cpp_compiler_, os_executable_ext))
271+
.make_preferred()
272+
.string();
273+
t.archiver_ = (verified_toolchain_.path /
274+
fmt::format("{}{}", t.archiver_, os_executable_ext))
275+
.make_preferred()
276+
.string();
277+
t.linker_ = (verified_toolchain_.path /
278+
fmt::format("{}{}", t.linker_, os_executable_ext))
279+
.make_preferred()
280+
.string();
281+
}
282+
243283
return verified_toolchains;
244284
}
245285

buildcc/lib/toolchain/test/test_toolchain_verify.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,136 @@ TEST(ToolchainTestGroup, VerifyToolchain_LockedFolder) {
204204
}
205205
}
206206

207+
TEST(ToolchainTestGroup, VerifyToolchain_ConditionalAdd_CompilerVersion) {
208+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
209+
"gcc", "g++", "ar", "ld");
210+
211+
buildcc::base::VerifyToolchainConfig config;
212+
config.env_vars.clear();
213+
config.absolute_search_paths.push_back(
214+
(fs::current_path() / "toolchains" / "gcc").string());
215+
config.compiler_version = "10.2.1";
216+
217+
std::vector<std::string> compiler_version{"10.2.1"};
218+
std::vector<std::string> arch{"none"};
219+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
220+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
221+
222+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
223+
gcc.Verify(config);
224+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
225+
CHECK_EQUAL(verified_toolchains.size(), 1);
226+
}
227+
228+
TEST(ToolchainTestGroup,
229+
VerifyToolchain_ConditionalAdd_CompilerVersionFailure) {
230+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
231+
"gcc", "g++", "ar", "ld");
232+
233+
buildcc::base::VerifyToolchainConfig config;
234+
config.env_vars.clear();
235+
config.absolute_search_paths.push_back(
236+
(fs::current_path() / "toolchains" / "gcc").string());
237+
config.compiler_version = "11.0.0";
238+
239+
std::vector<std::string> compiler_version{"10.2.1"};
240+
std::vector<std::string> arch{"none"};
241+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
242+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
243+
244+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
245+
gcc.Verify(config);
246+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
247+
CHECK_EQUAL(verified_toolchains.size(), 0);
248+
}
249+
250+
TEST(ToolchainTestGroup, VerifyToolchain_ConditionalAdd_TargetArch) {
251+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
252+
"gcc", "g++", "ar", "ld");
253+
254+
buildcc::base::VerifyToolchainConfig config;
255+
config.env_vars.clear();
256+
config.absolute_search_paths.push_back(
257+
(fs::current_path() / "toolchains" / "gcc").string());
258+
config.target_arch = "arm-none-eabi";
259+
260+
std::vector<std::string> compiler_version{"10.2.1"};
261+
std::vector<std::string> arch{"arm-none-eabi"};
262+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
263+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
264+
265+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
266+
gcc.Verify(config);
267+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
268+
CHECK_EQUAL(verified_toolchains.size(), 1);
269+
}
270+
271+
TEST(ToolchainTestGroup, VerifyToolchain_ConditionalAdd_TargetArchFailure) {
272+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
273+
"gcc", "g++", "ar", "ld");
274+
275+
buildcc::base::VerifyToolchainConfig config;
276+
config.env_vars.clear();
277+
config.absolute_search_paths.push_back(
278+
(fs::current_path() / "toolchains" / "gcc").string());
279+
config.target_arch = "none";
280+
281+
std::vector<std::string> compiler_version{"10.2.1"};
282+
std::vector<std::string> arch{"arm-none-eabi"};
283+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
284+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
285+
286+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
287+
gcc.Verify(config);
288+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
289+
CHECK_EQUAL(verified_toolchains.size(), 0);
290+
}
291+
292+
TEST(ToolchainTestGroup, VerifyToolchain_ConditionalAdd_BothFailure) {
293+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
294+
"gcc", "g++", "ar", "ld");
295+
296+
buildcc::base::VerifyToolchainConfig config;
297+
config.env_vars.clear();
298+
config.absolute_search_paths.push_back(
299+
(fs::current_path() / "toolchains" / "gcc").string());
300+
config.compiler_version = "none";
301+
config.target_arch = "none";
302+
303+
std::vector<std::string> compiler_version{"10.2.1"};
304+
std::vector<std::string> arch{"arm-none-eabi"};
305+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
306+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
307+
308+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
309+
gcc.Verify(config);
310+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
311+
CHECK_EQUAL(verified_toolchains.size(), 0);
312+
}
313+
314+
TEST(ToolchainTestGroup, VerifyToolchain_UpdateFalse) {
315+
buildcc::base::Toolchain gcc(buildcc::base::Toolchain::Id::Gcc, "gcc", "as",
316+
"gcc", "g++", "ar", "ld");
317+
318+
buildcc::base::VerifyToolchainConfig config;
319+
config.env_vars.clear();
320+
config.absolute_search_paths.push_back(
321+
(fs::current_path() / "toolchains" / "gcc").string());
322+
// config.compiler_version = "none";
323+
// config.target_arch = "none";
324+
config.update = false;
325+
326+
std::vector<std::string> compiler_version{"10.2.1"};
327+
std::vector<std::string> arch{"arm-none-eabi"};
328+
buildcc::env::m::CommandExpect_Execute(1, true, &compiler_version, nullptr);
329+
buildcc::env::m::CommandExpect_Execute(1, true, &arch, nullptr);
330+
331+
std::vector<buildcc::base::VerifiedToolchain> verified_toolchains =
332+
gcc.Verify(config);
333+
UT_PRINT(std::to_string(verified_toolchains.size()).c_str());
334+
CHECK_EQUAL(verified_toolchains.size(), 1);
335+
}
336+
207337
int main(int ac, char **av) {
208338
buildcc::env::m::VectorStringCopier copier;
209339
mock().installCopier(TEST_VECTOR_STRING_TYPE, copier);

0 commit comments

Comments
 (0)