1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
#pragma once
#include <source_location>
#include <string>
#include <vector>
#include <map>
#include <variant>
#include <cstddef>
#include <functional>
namespace ctor {
enum class target_type
{
automatic,
executable,
static_library,
dynamic_library,
object,
unit_test,
unit_test_library,
function,
unknown,
};
enum class language
{
automatic,
c,
cpp,
assembler,
};
enum class output_system
{
host,
build,
};
struct source
{
source(const char* file) : file(file) {}
source(const std::string& file) : file(file) {}
source(const char* file, ctor::language lang) : file(file), language(lang) {}
source(const std::string& file, ctor::language lang) : file(file), language(lang) {}
source(const char* file, const char* output) : file(file), output(output) {}
source(const std::string& file, const std::string& output) : file(file), output(output) {}
source(const char* file, ctor::language lang, const char* output) : file(file), language(lang), output(output) {}
source(const std::string& file, ctor::language lang, const std::string& output) : file(file), language(lang), output(output) {}
std::string file;
ctor::language language{ctor::language::automatic};
std::string output{};
};
enum class toolchain
{
any,
none,
gcc,
clang,
};
enum class cxx_opt
{
output,
debug,
warn_all,
warnings_as_errors,
generate_dep_tree,
no_link,
include_path,
cpp_std,
optimization,
position_independent_code,
position_independent_executable,
custom,
};
enum class c_opt
{
output,
debug,
warn_all,
warnings_as_errors,
generate_dep_tree,
no_link,
include_path,
c_std,
optimization,
position_independent_code,
position_independent_executable,
custom,
};
enum class ld_opt
{
output,
strip,
warn_all,
warnings_as_errors,
library_path,
link,
cpp_std,
build_shared,
threads,
position_independent_code,
position_independent_executable,
custom,
};
enum class ar_opt
{
replace,
add_index,
create,
output,
custom,
};
enum class asm_opt
{
custom,
};
template<typename T>
class flag
{
public:
flag(const std::string& str);
flag(const char* str);
flag(T opt) : opt(opt) {}
flag(T opt, const std::string& arg) : opt(opt), arg(arg) {}
flag(T opt, const char* arg) : opt(opt), arg(arg) {}
flag(ctor::toolchain toolchain, T opt) : toolchain(toolchain), opt(opt) {}
flag(ctor::toolchain toolchain, T opt, const char* arg) : toolchain(toolchain), opt(opt), arg(arg) {}
flag(ctor::toolchain toolchain, T opt, const std::string& arg) : toolchain(toolchain), opt(opt), arg(arg) {}
ctor::toolchain toolchain{ctor::toolchain::any};
T opt;
std::string arg;
};
using c_flag = ctor::flag<ctor::c_opt>;
using cxx_flag = ctor::flag<ctor::cxx_opt>;
using ld_flag = ctor::flag<ctor::ld_opt>;
using ar_flag = ctor::flag<ctor::ar_opt>;
using asm_flag = ctor::flag<ctor::asm_opt>;
using c_flags = std::vector<ctor::c_flag>;
using cxx_flags = std::vector<ctor::cxx_flag>;
using ld_flags= std::vector<ctor::ld_flag>;
using ar_flags = std::vector<ctor::ar_flag>;
using asm_flags = std::vector<ctor::asm_flag>;
struct flags
{
ctor::c_flags cflags;
ctor::cxx_flags cxxflags;
ctor::ld_flags ldflags;
ctor::ar_flags arflags;
ctor::asm_flags asmflags;
};
struct settings
{
std::string builddir{"build"};
std::size_t parallel_processes{1};
int verbose{0};
};
struct build_configuration;
using GeneratorCb = std::function<int(const std::string& input,
const std::string& output,
const build_configuration& config,
const ctor::settings& settings)>;
struct build_configuration
{
std::string name;
ctor::target_type type{ctor::target_type::automatic};
ctor::output_system system{ctor::output_system::host};
std::string target;
std::vector<ctor::source> sources;
std::vector<std::string> depends;
ctor::flags flags;
std::vector<std::string> externals;
GeneratorCb function;
};
using build_configurations = std::vector<build_configuration>;
int reg(ctor::build_configurations (*cb)(const ctor::settings&),
const std::source_location location = std::source_location::current());
struct external_manual
{
ctor::flags flags;
};
struct external_configuration
{
std::string name;
ctor::output_system system{ctor::output_system::host};
std::variant<ctor::external_manual> external;
};
using external_configurations = std::vector<ctor::external_configuration>;
int reg(ctor::external_configurations (*cb)(const ctor::settings&),
const std::source_location location = std::source_location::current());
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define CONCAT_INNER(a, b) a ## b
#define UNIQUE_NAME(base) CONCAT(base, __LINE__)
#define REG(cb) namespace { int UNIQUE_NAME(unique) = reg(cb); }
namespace cfg
{
constexpr auto builddir = "builddir";
constexpr auto host_cc = "host-cc";
constexpr auto host_cxx = "host-cpp";
constexpr auto host_ar = "host-ar";
constexpr auto host_ld = "host-ld";
constexpr auto build_cc = "build-cc";
constexpr auto build_cxx = "build-cpp";
constexpr auto build_ar = "build-ar";
constexpr auto build_ld = "build-ld";
constexpr auto ctor_includedir = "ctor-includedir";
constexpr auto ctor_libdir = "ctor-libdir";
}
struct configuration
{
bool has(const std::string& key) const;
const std::string& get(const std::string& key, const std::string& default_value = {}) const;
ctor::toolchain host_toolchain{ctor::toolchain::none};
ctor::toolchain build_toolchain{ctor::toolchain::none};
std::vector<std::string> args;
std::map<std::string, std::string> env;
std::map<std::string, std::string> tools;
std::map<std::string, ctor::flags> externals;
};
const ctor::configuration& get_configuration();
}
|