]> git.tdb.fi Git - builder.git/blob - source/architecture.cpp
Add an alias for x86_64
[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         "x86_64", "athlon64",
60         "win32", "windows",
61         0
62 };
63
64 }
65
66 Architecture::Architecture(Builder &b, const string &spec):
67         builder(b),
68         bits(0),
69         native(false)
70 {
71         if(spec.empty())
72         {
73 #ifdef WIN32
74                 system = "windows";
75 #else
76                 utsname un;
77                 if(uname(&un)==0)
78                 {
79                         system = tolower(un.sysname);
80                         parse_specification(tolower(un.machine));
81                         // We really only want to set type for the default arch
82                         cpu.clear();
83                 }
84 #endif
85                 bits = sizeof(void *)*numeric_limits<unsigned char>::digits;
86                 native = true;
87         }
88         else
89         {
90                 parse_specification(spec);
91                 const Architecture &native_arch = builder.get_native_arch();
92                 if(type.empty())
93                         type = native_arch.type;
94                 if(cpu.empty())
95                         cpu = native_arch.cpu;
96                 if(system.empty())
97                         system = native_arch.system;
98                 if(!bits)
99                 {
100                         if(type==native_arch.type)
101                                 bits = native_arch.bits;
102                         else
103                                 bits = 32;
104                 }
105
106                 if(type!=native_arch.type || system!=native_arch.system)
107                         cross_prefix = format("%s-%s", type, system);
108                 else if(bits!=native_arch.bits)
109                 {
110                         build_info.cflags.push_back(format("-m%d", bits));
111                         build_info.ldflags.push_back(format("-m%d", bits));
112                 }
113                 else
114                         native = true;
115
116                 if(!cpu.empty())
117                         build_info.cflags.push_back(format("-march=%s", cpu));
118         }
119         name = type;
120         if(!cpu.empty())
121                 name += format("-%s", cpu);
122         name += format("-%d-%s", bits, system);
123 }
124
125 void Architecture::set_tool(const string &t, const string &p)
126 {
127         tools[t] = p;
128 }
129
130 void Architecture::set_cross_prefix(const string &p)
131 {
132         cross_prefix = p;
133 }
134
135 std::string Architecture::get_tool(const string &t) const
136 {
137         StringMap::const_iterator i = tools.find(t);
138         if(i!=tools.end())
139         {
140                 if(i->second[0]=='-')
141                         return cross_prefix+i->second;
142                 else
143                         return i->second;
144         }
145
146         const Architecture &native_arch = builder.get_native_arch();
147         if(this!=&native_arch)
148         {
149                 if(!cross_prefix.empty())
150                         return cross_prefix+"-"+native_arch.get_tool(t);
151                 else
152                         return native_arch.get_tool(t);
153         }
154         else
155                 throw KeyError("Unknown tool", t);
156 }
157
158 bool Architecture::match_name(const string &pattern) const
159 {
160         vector<string> parts = split(pattern, "-");
161         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
162         {
163                 string part = resolve_alias(*i);
164                 if(part!=type && part!=cpu && part!=system)
165                         return false;
166         }
167         return true;
168 }
169
170 string Architecture::resolve_alias(const string &part) const
171 {
172         for(unsigned j=0; aliases[j]; j+=2)
173                 if(part==aliases[j])
174                         return aliases[j+1];
175
176         return part;
177 }
178
179 void Architecture::parse_specification(const string &spec)
180 {
181         vector<string> parts = split(spec, "-");
182         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
183         {
184                 string part = resolve_alias(*i);
185
186                 bool ok = false;
187
188                 for(unsigned j=0; (!ok && types[j]); ++j)
189                         if(part==types[j])
190                         {
191                                 if(!type.empty() && part!=type)
192                                         throw InvalidParameterValue("Conflicting type specification");
193                                 type = part;
194                                 ok = true;
195                         }
196
197                 for(unsigned j=0; (!ok && cpus[j]); j+=2)
198                         if(part==cpus[j])
199                         {
200                                 if(type.empty())
201                                         type = cpus[j+1];
202                                 else if(cpus[j+1]!=type)
203                                         throw InvalidParameterValue("Conflicting CPU specification");
204                                 cpu = part;
205                                 ok = true;
206                         }
207
208                 for(unsigned j=0; (!ok && systems[j]); ++j)
209                         if(part==systems[j])
210                         {
211                                 system = part;
212                                 ok = true;
213                         }
214
215                 if(!ok && (part=="32" || part=="64"))
216                 {
217                         bits = lexical_cast<unsigned>(part);
218                         ok = true;
219                 }
220
221                 if(!ok)
222                         throw InvalidParameterValue("Unrecognized part in arch specification: "+*i);
223         }
224 }
225
226
227 Architecture::Loader::Loader(Architecture &a):
228         arch(a)
229 {
230         add("prefix", &Architecture::cross_prefix);
231         add("tool",   &Loader::tool);
232 }
233
234 void Architecture::Loader::tool(const string &t, const string &p)
235 {
236         arch.tools[t] = p;
237 }