]> git.tdb.fi Git - builder.git/blob - source/architecture.cpp
Add a generic internal alias system to Architecture
[builder.git] / source / architecture.cpp
1 /* $Id$
2
3 This file is part of builder
4 Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <limits>
9 #ifndef WIN32
10 #include <sys/utsname.h>
11 #endif
12 #include <msp/strings/formatter.h>
13 #include <msp/strings/utils.h>
14 #include "architecture.h"
15 #include "builder.h"
16
17 using namespace std;
18 using namespace Msp;
19
20 namespace {
21
22 const char *types[] =
23 {
24         "pc",
25         "arm",
26         0
27 };
28
29 const char *cpus[] =
30 {
31         "i386",       "pc",
32         "i486",       "pc",
33         "pentium",    "pc",
34         "pentiumpro", "pc",
35         "pentium2",   "pc",
36         "pentium3",   "pc",
37         "pentium4",   "pc",
38         "core2",      "pc",
39         "k6",         "pc",
40         "athlon",     "pc",
41         "athlonxp",   "pc",
42         "athlon64",   "pc",
43         "armv5",      "arm",
44         0
45 };
46
47 const char *systems[] =
48 {
49         "linux",
50         "freebsd",
51         "windows",
52         0
53 };
54
55 const char *aliases[] =
56 {
57         "i586",  "pentium",
58         "i686",  "pentiumpro",
59         "win32", "windows",
60         0
61 };
62
63 }
64
65 Architecture::Architecture(Builder &b, const string &spec):
66         builder(b),
67         bits(0),
68         native(false)
69 {
70         if(spec.empty())
71         {
72 #ifdef WIN32
73                 system = "windows";
74 #else
75                 utsname un;
76                 if(uname(&un)==0)
77                 {
78                         system = tolower(un.sysname);
79                         parse_specification(tolower(un.machine));
80                         // We really only want to set type for the default arch
81                         cpu.clear();
82                 }
83 #endif
84                 bits = sizeof(void *)*numeric_limits<unsigned char>::digits;
85                 native = true;
86         }
87         else
88         {
89                 parse_specification(spec);
90                 const Architecture &native_arch = builder.get_native_arch();
91                 if(type.empty())
92                         type = native_arch.type;
93                 if(cpu.empty())
94                         cpu = native_arch.cpu;
95                 if(system.empty())
96                         system = native_arch.system;
97                 if(!bits)
98                 {
99                         if(type==native_arch.type)
100                                 bits = native_arch.bits;
101                         else
102                                 bits = 32;
103                 }
104
105                 if(type!=native_arch.type || system!=native_arch.system)
106                         cross_prefix = format("%s-%s", type, system);
107                 else if(bits!=native_arch.bits)
108                 {
109                         build_info.cflags.push_back(format("-m%d", bits));
110                         build_info.ldflags.push_back(format("-m%d", bits));
111                 }
112                 else
113                         native = true;
114
115                 if(!cpu.empty())
116                         build_info.cflags.push_back(format("-march=%s", cpu));
117         }
118         name = type;
119         if(!cpu.empty())
120                 name += format("-%s", cpu);
121         name += format("-%d-%s", bits, system);
122 }
123
124 void Architecture::set_tool(const string &t, const string &p)
125 {
126         tools[t] = p;
127 }
128
129 void Architecture::set_cross_prefix(const string &p)
130 {
131         cross_prefix = p;
132 }
133
134 std::string Architecture::get_tool(const string &t) const
135 {
136         StringMap::const_iterator i = tools.find(t);
137         if(i!=tools.end())
138         {
139                 if(i->second[0]=='-')
140                         return cross_prefix+i->second;
141                 else
142                         return i->second;
143         }
144
145         const Architecture &native_arch = builder.get_native_arch();
146         if(this!=&native_arch)
147         {
148                 if(!cross_prefix.empty())
149                         return cross_prefix+"-"+native_arch.get_tool(t);
150                 else
151                         return native_arch.get_tool(t);
152         }
153         else
154                 throw KeyError("Unknown tool", t);
155 }
156
157 bool Architecture::match_name(const string &pattern) const
158 {
159         vector<string> parts = split(pattern, "-");
160         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
161         {
162                 string part = resolve_alias(*i);
163                 if(part!=type && part!=cpu && part!=system)
164                         return false;
165         }
166         return true;
167 }
168
169 string Architecture::resolve_alias(const string &part) const
170 {
171         for(unsigned j=0; aliases[j]; j+=2)
172                 if(part==aliases[j])
173                         return aliases[j+1];
174
175         return part;
176 }
177
178 void Architecture::parse_specification(const string &spec)
179 {
180         vector<string> parts = split(spec, "-");
181         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
182         {
183                 string part = resolve_alias(*i);
184
185                 bool ok = false;
186
187                 for(unsigned j=0; (!ok && types[j]); ++j)
188                         if(part==types[j])
189                         {
190                                 if(!type.empty() && part!=type)
191                                         throw InvalidParameterValue("Conflicting type specification");
192                                 type = part;
193                                 ok = true;
194                         }
195
196                 for(unsigned j=0; (!ok && cpus[j]); j+=2)
197                         if(part==cpus[j])
198                         {
199                                 if(type.empty())
200                                         type = cpus[j+1];
201                                 else if(cpus[j+1]!=type)
202                                         throw InvalidParameterValue("Conflicting CPU specification");
203                                 cpu = part;
204                                 ok = true;
205                         }
206
207                 for(unsigned j=0; (!ok && systems[j]); ++j)
208                         if(part==systems[j])
209                         {
210                                 system = part;
211                                 ok = true;
212                         }
213
214                 if(!ok && (part=="32" || part=="64"))
215                 {
216                         bits = lexical_cast<unsigned>(part);
217                         ok = true;
218                 }
219
220                 if(!ok)
221                         throw InvalidParameterValue("Unrecognized part in arch specification: "+*i);
222         }
223 }
224
225
226 Architecture::Loader::Loader(Architecture &a):
227         arch(a)
228 {
229         add("prefix", &Architecture::cross_prefix);
230         add("tool",   &Loader::tool);
231 }
232
233 void Architecture::Loader::tool(const string &t, const string &p)
234 {
235         arch.tools[t] = p;
236 }