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
|
// -*- c++ -*-
// Distributed under the BSD 2-Clause License.
// See accompanying file LICENSE for details.
#pragma once
#include <source_location>
#include <string>
#include <vector>
#include <map>
#include <variant>
#include <cstddef>
enum class TargetType
{
Auto, // Default - deduce from target name and sources extensions
Executable,
StaticLibrary,
DynamicLibrary,
Object,
UnitTest,
UnitTestLib,
};
enum class Language
{
Auto, // Default - deduce language from source extensions
C,
Cpp,
Asm,
};
enum class OutputSystem
{
Host, // Output for the target system
Build, // Internal tool during cross-compilation
};
struct Source
{
Source(const char* file) : file(file) {}
Source(const std::string& file) : file(file) {}
Source(const char* file, Language lang) : file(file), language(lang) {}
Source(const std::string& file, Language lang) : file(file), language(lang) {}
std::string file;
Language language{Language::Auto};
};
struct Flags
{
std::vector<std::string> cxxflags; // flags for c++ compiler
std::vector<std::string> cflags; // flags for c compiler
std::vector<std::string> ldflags; // flags for linker
std::vector<std::string> asmflags; // flags for asm translator
};
struct Settings
{
std::string builddir{"build"};
std::size_t parallel_processes{1};
int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ...
};
struct BuildConfiguration
{
std::string name; // Name - used for referring in other configurations.
TargetType type{TargetType::Auto};
OutputSystem system{OutputSystem::Host};
std::string target; // Output target file for this configuration
std::vector<Source> sources; // source list
std::vector<std::string> depends; // internal target dependencies
Flags flags;
std::vector<std::string> externals; // externals used by this configuration
};
using BuildConfigurations = std::vector<BuildConfiguration>;
int reg(BuildConfigurations (*cb)(const Settings&),
const std::source_location location = std::source_location::current());
// This type will use flags verbatim
struct ExternalManual
{
Flags flags;
};
struct ExternalConfiguration
{
std::string name; // Name for configuration
std::variant<ExternalManual> external;
};
using ExternalConfigurations = std::vector<ExternalConfiguration>;
int reg(ExternalConfigurations (*cb)(const Settings&),
const std::source_location location = std::source_location::current());
// Convenience macro - ugly but keeps things simple(r)
#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); }
// Predefined configuration keys
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
{
std::vector<std::string> args; // vector of arguments used when last calling configure
std::map<std::string, std::string> env; // env used when last calling configure
std::map<std::string, std::string> tools; // tools
std::map<std::string, Flags> externals;
};
const Configuration& configuration();
bool hasConfiguration(const std::string& key);
const std::string& getConfiguration(const std::string& key,
const std::string& defaultValue = {});
|