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