Skip to content

Commit b9b37cb

Browse files
authored
Toolchain generic (#209)
1 parent d22c750 commit b9b37cb

File tree

30 files changed

+774
-555
lines changed

30 files changed

+774
-555
lines changed

bootstrap/main.buildcc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ int main(int argc, char **argv) {
4141
Reg::Init();
4242
Reg::Call(Args::Clean()).Func(clean_cb);
4343

44-
BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain();
44+
auto &toolchain = custom_toolchain_arg;
45+
toolchain.SetToolchainInfoFunc(GlobalToolchainInfo::Get(toolchain.id));
4546

4647
BuildBuildCC buildcc(
4748
toolchain, TargetEnv(Project::GetRootDir(), Project::GetBuildDir()));

bootstrap/src/build_buildcc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void buildcc_cb(BaseTarget &target, const BaseGenerator &schema_gen,
9090
target.GlobHeaders("lib/args/include/args");
9191

9292
// Specialized Toolchains
93+
target.GlobSources("toolchains/src");
9394
target.AddIncludeDir("toolchains/include");
9495
target.GlobHeaders("toolchains/include/toolchains");
9596

buildcc/buildcc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
#include "toolchains/toolchain_gcc.h"
4040
#include "toolchains/toolchain_msvc.h"
4141
#include "toolchains/toolchain_mingw.h"
42+
#include "toolchains/toolchain_generic.h"
43+
#include "toolchains/toolchain_custom.h"
44+
45+
#include "toolchains/toolchain_infos.h"
4246

4347
// TODO, Add more specialized toolchains here
4448

buildcc/lib/args/include/args/args.h

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,31 @@ struct ArgToolchainState {
4747
* command line
4848
* Bundled with Toolchain State
4949
*/
50-
struct ArgToolchain {
51-
ArgToolchain() = default;
50+
class ArgToolchain : public Toolchain {
51+
public:
52+
ArgToolchain()
53+
: Toolchain(ToolchainId::Undefined, "", ToolchainExecutables()){};
5254
ArgToolchain(ToolchainId initial_id, const std::string &initial_name,
5355
const ToolchainExecutables &initial_executables)
54-
: id(initial_id), name(initial_name), executables(initial_executables) {}
55-
ArgToolchain(ToolchainId initial_id, const std::string &initial_name,
56-
const std::string &initial_assembler,
57-
const std::string &initial_c_compiler,
58-
const std::string &initial_cpp_compiler,
59-
const std::string &initial_archiver,
60-
const std::string &initial_linker)
61-
: ArgToolchain(initial_id, initial_name,
62-
ToolchainExecutables(initial_assembler, initial_c_compiler,
63-
initial_cpp_compiler,
64-
initial_archiver, initial_linker)) {}
65-
66-
/**
67-
* @brief Construct a BaseToolchain from the arguments supplied through the
68-
* command line information
69-
*/
70-
// TODO, Update this for lock and ToolchainConfig
71-
BaseToolchain ConstructToolchain() const {
72-
return BaseToolchain(id, name, executables);
73-
}
56+
: Toolchain(initial_id, initial_name, initial_executables) {}
57+
[[deprecated]] ArgToolchain(ToolchainId initial_id,
58+
const std::string &initial_name,
59+
const std::string &initial_assembler,
60+
const std::string &initial_c_compiler,
61+
const std::string &initial_cpp_compiler,
62+
const std::string &initial_archiver,
63+
const std::string &initial_linker)
64+
: Toolchain(initial_id, initial_name,
65+
ToolchainExecutables(initial_assembler, initial_c_compiler,
66+
initial_cpp_compiler, initial_archiver,
67+
initial_linker)) {}
7468

69+
public:
7570
ArgToolchainState state;
76-
ToolchainId id{ToolchainId::Undefined};
77-
std::string name{""};
78-
ToolchainExecutables executables;
71+
ToolchainId &id = RefId();
72+
std::string &name = RefName();
73+
ToolchainExecutables &executables = RefExecutables();
74+
ToolchainConfig &config = RefConfig();
7975
};
8076

8177
// NOTE, Incomplete without pch_compile_command

buildcc/lib/args/src/register.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "env/assert_fatal.h"
2525
#include "env/env.h"
26+
#include "env/storage.h"
2627

2728
namespace fs = std::filesystem;
2829

@@ -67,13 +68,28 @@ namespace buildcc {
6768

6869
std::unique_ptr<Reg::Instance> Reg::instance_;
6970

71+
void SystemInit() {
72+
Project::Init(fs::current_path() / Args::GetProjectRootDir(),
73+
fs::current_path() / Args::GetProjectBuildDir());
74+
env::set_log_level(Args::GetLogLevel());
75+
76+
// Top down (what is init first gets deinit last)
77+
std::atexit([]() {
78+
Project::Deinit();
79+
Reg::Deinit();
80+
Args::Deinit();
81+
Storage::Clear();
82+
});
83+
}
84+
7085
void Reg::Init() {
7186
if (!instance_) {
7287
instance_ = std::make_unique<Instance>();
88+
env::assert_fatal(static_cast<bool>(instance_), "Reg::Init failed");
7389
env::assert_fatal(Args::IsParsed(), "Setup your Args");
74-
Project::Init(fs::current_path() / Args::GetProjectRootDir(),
75-
fs::current_path() / Args::GetProjectBuildDir());
76-
env::set_log_level(Args::GetLogLevel());
90+
91+
// Initialize everything else here
92+
SystemInit();
7793
}
7894
}
7995

buildcc/lib/env/include/env/storage.h

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,7 @@ namespace buildcc {
3232
class ScopedStorage {
3333
public:
3434
ScopedStorage() {}
35-
~ScopedStorage() {
36-
for (const auto &ptr_iter : ptrs_) {
37-
ptr_iter.second.destructor();
38-
}
39-
ptrs_.clear();
40-
env::assert_fatal(ptrs_.empty(), "Memory not deallocated");
41-
}
35+
~ScopedStorage() { Clear(); }
4236

4337
ScopedStorage(const ScopedStorage &) = delete;
4438

@@ -58,10 +52,15 @@ class ScopedStorage {
5852
return *ptr;
5953
}
6054

61-
template <typename T> void Remove(T *ptr) { delete ptr; }
55+
void Clear() {
56+
for (const auto &ptr_iter : ptrs_) {
57+
ptr_iter.second.destructor();
58+
}
59+
ptrs_.clear();
60+
}
6261

6362
template <typename T> const T &ConstRef(const std::string &identifier) const {
64-
env::assert_fatal(ptrs_.find(identifier) != ptrs_.end(),
63+
env::assert_fatal(Contains(identifier),
6564
fmt::format("Could not find '{}'", identifier));
6665
const PtrMetadata &metadata = ptrs_.at(identifier);
6766
env::assert_fatal(
@@ -77,12 +76,30 @@ class ScopedStorage {
7776
static_cast<const ScopedStorage &>(*this).ConstRef<T>(identifier));
7877
}
7978

79+
bool Contains(const std::string &identifier) const {
80+
return (ptrs_.find(identifier) != ptrs_.end());
81+
}
82+
83+
template <typename T> bool Valid(const std::string &identifier) const {
84+
if (!Contains(identifier)) {
85+
return false;
86+
}
87+
const PtrMetadata &metadata = ptrs_.at(identifier);
88+
if (typeid(T).name() != metadata.typeid_name) {
89+
return false;
90+
}
91+
return true;
92+
}
93+
94+
protected:
95+
template <typename T> void Remove(T *ptr) { delete ptr; }
96+
8097
private:
8198
/**
8299
* @brief
83100
* @param ptr Can hold data of any type
84-
* @param typeid_name We cannot store a template type so this is the next best
85-
* thing
101+
* @param typeid_name We cannot store a template type so this is the next
102+
* best thing
86103
* @param desstructor Destructor callback to delete ptr
87104
*/
88105
struct PtrMetadata {
@@ -101,14 +118,13 @@ class Storage {
101118
Storage(const Storage &) = delete;
102119
Storage(Storage &&) = delete;
103120

104-
static void Init() { internal_ = std::make_unique<ScopedStorage>(); }
105-
static void Deinit() { internal_.reset(nullptr); }
106-
107121
template <typename T, typename... Params>
108122
static T &Add(const std::string &identifier, Params &&...params) {
109123
return Ref().Add<T, Params...>(identifier, std::forward<Params>(params)...);
110124
}
111125

126+
static void Clear() { Ref().Clear(); }
127+
112128
template <typename T>
113129
static const T &ConstRef(const std::string &identifier) {
114130
return Ref().ConstRef<T>(identifier);
@@ -118,11 +134,19 @@ class Storage {
118134
return Ref().Ref<T>(identifier);
119135
}
120136

137+
static bool Contains(const std::string &identifier) {
138+
return Ref().Contains(identifier);
139+
}
140+
141+
template <typename T> static bool Valid(const std::string &identifier) {
142+
return Ref().Valid<T>(identifier);
143+
}
144+
121145
private:
122146
static ScopedStorage &Ref();
123147

124148
private:
125-
static std::unique_ptr<ScopedStorage> internal_;
149+
static ScopedStorage internal_;
126150
};
127151

128152
} // namespace buildcc

buildcc/lib/env/src/storage.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,8 @@
1818

1919
namespace buildcc {
2020

21-
std::unique_ptr<ScopedStorage> Storage::internal_;
21+
ScopedStorage Storage::internal_;
2222

23-
ScopedStorage &Storage::Ref() {
24-
env::assert_fatal(internal_ != nullptr,
25-
"Initialize Storage using the Storage::Init API");
26-
return *internal_;
27-
}
23+
ScopedStorage &Storage::Ref() { return internal_; }
2824

2925
} // namespace buildcc

buildcc/lib/env/test/test_storage.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,23 @@ TEST_GROUP(ScopedStorageTestGroup)
1515
TEST_GROUP(StorageTestGroup)
1616
{
1717
void setup() {
18-
buildcc::Storage::Init();
18+
MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads();
1919
}
2020
void teardown() {
21-
buildcc::Storage::Deinit();
21+
buildcc::Storage::Clear();
22+
MemoryLeakWarningPlugin::restoreNewDeleteOverloads();
2223
}
2324
};
2425
// clang-format on
2526

27+
class MyScopedStorage : public buildcc::ScopedStorage {
28+
public:
29+
// We want to unit test this
30+
template <typename T> void Remove(T *ptr) {
31+
this->ScopedStorage::Remove<T>(ptr);
32+
}
33+
};
34+
2635
class BigObj {};
2736

2837
class BigObjWithParameters {
@@ -42,19 +51,29 @@ class BigObjWithParameters {
4251
static BigObj obj;
4352

4453
TEST(ScopedStorageTestGroup, BasicUsage) {
45-
buildcc::ScopedStorage storage;
54+
MyScopedStorage storage;
4655
storage.Add<BigObjWithParameters>("identifier", "name", 10, obj);
4756
storage.Add<BigObjWithParameters>("identifier2", "name2", 12, obj);
4857

4958
// Usage
5059
storage.ConstRef<BigObjWithParameters>("identifier").GetName();
5160
storage.Ref<BigObjWithParameters>("identifier2").GetName();
5261

62+
CHECK_TRUE(storage.Contains("identifier"));
63+
CHECK_FALSE(storage.Contains("identifier_does_not_exist"));
64+
65+
CHECK_TRUE(storage.Valid<BigObjWithParameters>("identifier"));
66+
CHECK_FALSE(storage.Valid<BigObjWithParameters>("wrong_identifier"));
67+
CHECK_FALSE(storage.Valid<int>("identifier"));
68+
69+
storage.Clear();
70+
CHECK_FALSE(storage.Contains("identifier"));
71+
5372
// Automatic cleanup here
5473
}
5574

5675
TEST(ScopedStorageTestGroup, IncorrectUsage) {
57-
buildcc::ScopedStorage storage;
76+
MyScopedStorage storage;
5877
storage.Add<BigObjWithParameters>("identifier", "name", 10, obj);
5978

6079
// We try to cast to a different type!
@@ -65,13 +84,13 @@ TEST(ScopedStorageTestGroup, IncorrectUsage) {
6584
storage.Ref<BigObjWithParameters>("identifier2"));
6685
}
6786

68-
std::string &toReference(std::string *pointer) { return *pointer; }
69-
7087
TEST(ScopedStorageTestGroup, NullptrDelete) {
71-
buildcc::ScopedStorage storage;
88+
MyScopedStorage storage;
7289
storage.Remove<std::string>(nullptr);
7390
}
7491

92+
//
93+
7594
TEST(StorageTestGroup, BasicUsage) {
7695
buildcc::Storage::Add<BigObjWithParameters>("identifier", "name", 10, obj);
7796
buildcc::Storage::Add<BigObjWithParameters>("identifier2", "name2", 12, obj);
@@ -84,14 +103,14 @@ TEST(StorageTestGroup, BasicUsage) {
84103

85104
STRCMP_EQUAL(bigobj.c_str(), "name");
86105
STRCMP_EQUAL(bigobj2.c_str(), "name2");
87-
}
88106

89-
TEST(StorageTestGroup, UsageWithoutInit) {
90-
buildcc::Storage::Deinit();
107+
CHECK_TRUE(buildcc::Storage::Contains("identifier"));
108+
CHECK_FALSE(buildcc::Storage::Contains("identifier_does_not_exist"));
91109

92-
CHECK_THROWS(std::exception, buildcc::Storage::Add<int>("integer"));
93-
CHECK_THROWS(std::exception, buildcc::Storage::Ref<int>("integer"));
94-
CHECK_THROWS(std::exception, buildcc::Storage::ConstRef<int>("integer"));
110+
CHECK_TRUE(buildcc::Storage::Valid<BigObjWithParameters>("identifier"));
111+
CHECK_FALSE(
112+
buildcc::Storage::Valid<BigObjWithParameters>("wrong_identifier"));
113+
CHECK_FALSE(buildcc::Storage::Valid<BigObj>("identifier"));
95114
}
96115

97116
int main(int ac, char **av) {

buildcc/lib/target/src/target_info/target_info.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ namespace buildcc {
2121
// PRIVATE
2222

2323
void TargetInfo::Initialize() {
24-
toolchain_.GetLockInfo().ExpectsLock(
25-
"Toolchain should be locked before usage through `Toolchain::Lock`");
24+
// TODO, Update this later
25+
// toolchain_.GetLockInfo().ExpectsLock(
26+
// "Toolchain should be locked before usage through `Toolchain::Lock`");
2627

2728
std::for_each(toolchain_.GetPreprocessorFlags().begin(),
2829
toolchain_.GetPreprocessorFlags().end(),

buildcc/lib/target/test/target/test_toolchain_flag_api.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ TEST_GROUP(ToolchainFlagApiTestGroup)
1717
TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Lock) {
1818
buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc",
1919
"g++", "ar", "ld");
20+
toolchain.Lock();
2021
CHECK_THROWS(std::exception, toolchain.AddPreprocessorFlag("-preprocessor"));
2122
CHECK_THROWS(std::exception, toolchain.AddAsmCompileFlag("-asm"));
2223
CHECK_THROWS(std::exception, toolchain.AddPchCompileFlag("-pchcompile"));
@@ -29,7 +30,7 @@ TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Lock) {
2930

3031
TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Unlock) {
3132
buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc",
32-
"g++", "ar", "ld", false);
33+
"g++", "ar", "ld");
3334
toolchain.AddPreprocessorFlag("-preprocessor");
3435
toolchain.AddAsmCompileFlag("-asm");
3536
toolchain.AddPchCompileFlag("-pchcompile");
@@ -55,7 +56,7 @@ TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Unlock) {
5556

5657
TEST(ToolchainFlagApiTestGroup, BasicTargetTest) {
5758
buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc",
58-
"g++", "ar", "ld", false);
59+
"g++", "ar", "ld");
5960

6061
toolchain.AddPreprocessorFlag("-preprocessor");
6162
toolchain.AddAsmCompileFlag("-asm");
@@ -67,7 +68,9 @@ TEST(ToolchainFlagApiTestGroup, BasicTargetTest) {
6768
toolchain.AddLinkFlag("-link");
6869

6970
CHECK_FALSE(toolchain.GetLockInfo().IsLocked());
70-
{ CHECK_THROWS(std::exception, (buildcc::TargetInfo(toolchain, ""))); }
71+
// TODO, Add this in later
72+
// * We should lock our toolchain before using it
73+
// { CHECK_THROWS(std::exception, (buildcc::TargetInfo(toolchain, ""))); }
7174

7275
toolchain.Lock();
7376
CHECK_TRUE(toolchain.GetLockInfo().IsLocked());

0 commit comments

Comments
 (0)