]> git.tdb.fi Git - builder.git/blob - source/buildinfo.cpp
Use default member initializers and constructor delegation
[builder.git] / source / buildinfo.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/strings/format.h>
3 #include "buildinfo.h"
4
5 using namespace std;
6 using namespace Msp;
7
8 namespace {
9
10 /** Removes any duplicate entries from a vector, leaving only the first one.
11 The order of other elements is preserved. */
12 template<typename T>
13 void unique(vector<T> &v)
14 {
15         vector<T> seen;
16         for(auto i=v.begin(); i!=v.end(); )
17         {
18                 auto j = lower_bound(seen, *i);
19                 if(j!=seen.end() && *j==*i)
20                         i = v.erase(i);
21                 else
22                         seen.insert(j, *i++);
23         }
24 }
25
26 }
27
28
29 BuildInfo::LibraryMode BuildInfo::get_libmode_for(const string &lib) const
30 {
31         auto i = libmodes.find(lib);
32         if(i!=libmodes.end())
33                 return i->second;
34         return libmode;
35 }
36
37 void BuildInfo::update_from(const BuildInfo &bi, UpdateLevel level)
38 {
39         for(const auto &kvp: bi.defines)
40                 defines[kvp.first] = kvp.second;
41         incpath.insert(incpath.begin(), bi.incpath.begin(), bi.incpath.end());
42         threads = bi.threads;
43
44         for(const auto &kvp: bi.standards)
45         {
46                 auto j = standards.find(kvp.first);
47                 if(j==standards.end())
48                         standards.insert(kvp);
49                 else if(kvp.second.type!=j->second.type || kvp.second.year!=j->second.year)
50                 {
51                         if(!kvp.second.type.compare(0, 3, "gnu"))
52                                 j->second.type = kvp.second.type;
53                         if(kvp.second.year>j->second.year)
54                                 j->second.year = kvp.second.year;
55                 }
56         }
57
58         if(level!=CHAINED)
59         {
60                 libpath.insert(libpath.begin(), bi.libpath.begin(), bi.libpath.end());
61                 libs.insert(libs.begin(), bi.libs.begin(), bi.libs.end());
62         }
63
64         if(level==LOCAL)
65         {
66                 sysroot = bi.sysroot;
67                 local_incpath.insert(local_incpath.begin(), bi.local_incpath.begin(), bi.local_incpath.end());
68                 libmode = bi.libmode;
69                 rpath_mode = bi.rpath_mode;
70                 for(const auto &kvp: bi.libmodes)
71                         libmodes[kvp.first] = kvp.second;
72                 keep_symbols.insert(keep_symbols.end(), bi.keep_symbols.begin(), bi.keep_symbols.end());
73                 debug = bi.debug;
74                 optimize = bi.optimize;
75                 strip = bi.strip;
76                 warning_level = bi.warning_level;
77                 fatal_warnings = bi.fatal_warnings;
78         }
79
80         unique(incpath);
81         unique(local_incpath);
82         unique(libpath);
83         unique(libs);
84         unique(keep_symbols);
85 }
86
87
88 BuildInfo::LanguageStandard::LanguageStandard(const string &std)
89 {
90         auto i = find_if(std, [](char c){ return isdigit(static_cast<unsigned char>(c)); });
91         string::size_type num = i-std.begin();
92         type = std.substr(0, num);
93         year = lexical_cast<unsigned>(std.substr(num));
94         year += (year<70 ? 2000 : 1900);
95 }
96
97 string BuildInfo::LanguageStandard::str() const
98 {
99         return format("%s%02d", type, year%100);
100 }
101
102
103 BuildInfo::Loader::Loader(BuildInfo &bi):
104         DataFile::ObjectLoader<BuildInfo>(bi)
105 {
106         add("debug",    &BuildInfo::debug);
107         add("define",   &Loader::define);
108         add("incpath",  &Loader::incpath);
109         add("keep_symbol", &Loader::keep_symbol);
110         add("libpath",  &Loader::libpath);
111         add("library",  &Loader::library);
112         add("libmode",  &BuildInfo::libmode);
113         add("libmode",  &Loader::libmode_for_lib);
114         add("local_incpath", &Loader::local_incpath);
115         add("optimize", &BuildInfo::optimize);
116         add("runtime_path_mode", &BuildInfo::rpath_mode);
117         add("standard", &Loader::standard);
118         add("strip",    &BuildInfo::strip);
119         add("sysroot",  &Loader::sysroot);
120         add("threads",  &BuildInfo::threads);
121         add("warning_level", &BuildInfo::warning_level);
122         add("fatal_warnings", &BuildInfo::fatal_warnings);
123 }
124
125 void BuildInfo::Loader::incpath(const string &s)
126 {
127         obj.incpath.push_back(s);
128 }
129
130 void BuildInfo::Loader::define(const string &d, const string &v)
131 {
132         obj.defines[d] = v;
133 }
134
135 void BuildInfo::Loader::keep_symbol(const string &s)
136 {
137         obj.keep_symbols.push_back(s);
138 }
139
140 void BuildInfo::Loader::libmode_for_lib(const string &l, LibraryMode m)
141 {
142         obj.libmodes[l] = m;
143 }
144
145 void BuildInfo::Loader::libpath(const string &s)
146 {
147         obj.libpath.push_back(s);
148 }
149
150 void BuildInfo::Loader::library(const string &s)
151 {
152         obj.libs.push_back(s);
153 }
154
155 void BuildInfo::Loader::local_incpath(const string &s)
156 {
157         obj.local_incpath.push_back(s);
158 }
159
160 void BuildInfo::Loader::standard(DataFile::Symbol tag, const string &std)
161 {
162         obj.standards[tag.name] = std;
163 }
164
165 void BuildInfo::Loader::sysroot(const string &s)
166 {
167         obj.sysroot = s;
168 }
169
170
171 void operator>>(const LexicalConverter &conv, BuildInfo::LibraryMode &libmode)
172 {
173         if(conv.get()=="FORCE_STATIC")
174                 libmode = BuildInfo::FORCE_STATIC;
175         else if(conv.get()=="STATIC")
176                 libmode = BuildInfo::STATIC;
177         else if(conv.get()=="DYNAMIC")
178                 libmode = BuildInfo::DYNAMIC;
179         else if(conv.get()=="FORCE_DYNAMIC")
180                 libmode = BuildInfo::FORCE_DYNAMIC;
181         else
182                 throw lexical_error(format("Conversion of '%s' to LibraryMode", conv.get()));
183 }
184
185
186 void operator>>(const LexicalConverter &conv, BuildInfo::RuntimePathMode &rpath_mode)
187 {
188         if(conv.get()=="NONE")
189                 rpath_mode = BuildInfo::NO_RPATH;
190         else if(conv.get()=="RELATIVE")
191                 rpath_mode = BuildInfo::RELATIVE;
192         else if(conv.get()=="ABSOLUTE")
193                 rpath_mode = BuildInfo::ABSOLUTE;
194         else
195                 throw lexical_error(format("Conversion of '%s' to RuntimePathMode", conv.get()));
196 }