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