]> git.tdb.fi Git - builder.git/blob - source/architecture.cpp
Rewrite the architecture system
[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",  0,
32         "i486",       "pc",  0,
33         "pentium",    "pc",  0,
34         "i586",       "pc",  "pentium",
35         "pentiumpro", "pc",  0,
36         "i686",       "pc",  "pentiumpro",
37         "pentium2",   "pc",  0,
38         "pentium3",   "pc",  0,
39         "pentium4",   "pc",  0,
40         "core2",      "pc",  0,
41         "k6",         "pc",  0,
42         "athlon",     "pc",  0,
43         "athlonxp",   "pc",  0,
44         "athlon64",   "pc",  0,
45         "armv5",      "arm", 0,
46         0
47 };
48
49 const char *systems[] =
50 {
51         "linux",
52         "freebsd",
53         "windows",
54         0
55 };
56
57 }
58
59 Architecture::Architecture(Builder &b, const string &spec):
60         builder(b),
61         bits(0),
62         native(false)
63 {
64         if(spec.empty())
65         {
66 #ifdef WIN32
67                 system = "windows";
68 #else
69                 utsname un;
70                 if(uname(&un)==0)
71                 {
72                         system = tolower(un.sysname);
73                         parse_specification(tolower(un.machine));
74                         // We really only want to set type for the default arch
75                         cpu.clear();
76                 }
77 #endif
78                 bits = sizeof(void *)*numeric_limits<unsigned char>::digits;
79                 native = true;
80         }
81         else
82         {
83                 parse_specification(spec);
84                 const Architecture &native_arch = builder.get_native_arch();
85                 if(type.empty())
86                         type = native_arch.type;
87                 if(cpu.empty())
88                         cpu = native_arch.cpu;
89                 if(system.empty())
90                         system = native_arch.system;
91                 if(!bits)
92                 {
93                         if(type==native_arch.type)
94                                 bits = native_arch.bits;
95                         else
96                                 bits = 32;
97                 }
98
99                 if(type!=native_arch.type || system!=native_arch.system)
100                         cross_prefix = format("%s-%s", type, system);
101                 else if(bits!=native_arch.bits)
102                 {
103                         build_info.cflags.push_back(format("-m%d", bits));
104                         build_info.ldflags.push_back(format("-m%d", bits));
105                 }
106                 else
107                         native = true;
108
109                 if(!cpu.empty())
110                         build_info.cflags.push_back(format("-march=%s", cpu));
111         }
112         name = type;
113         if(!cpu.empty())
114                 name += format("-%s", cpu);
115         name += format("-%d-%s", bits, system);
116 }
117
118 void Architecture::set_tool(const string &t, const string &p)
119 {
120         tools[t] = p;
121 }
122
123 void Architecture::set_cross_prefix(const string &p)
124 {
125         cross_prefix = p;
126 }
127
128 std::string Architecture::get_tool(const string &t) const
129 {
130         StringMap::const_iterator i = tools.find(t);
131         if(i!=tools.end())
132         {
133                 if(i->second[0]=='-')
134                         return cross_prefix+i->second;
135                 else
136                         return i->second;
137         }
138
139         const Architecture &native_arch = builder.get_native_arch();
140         if(this!=&native_arch)
141         {
142                 if(!cross_prefix.empty())
143                         return cross_prefix+"-"+native_arch.get_tool(t);
144                 else
145                         return native_arch.get_tool(t);
146         }
147         else
148                 throw KeyError("Unknown tool", t);
149 }
150
151 bool Architecture::match_name(const string &pattern) const
152 {
153         vector<string> parts = split(pattern, "-");
154         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
155         {
156                 if(*i!=type && *i!=cpu && *i!=system)
157                         return false;
158         }
159         return true;
160 }
161
162 void Architecture::parse_specification(const string &spec)
163 {
164         vector<string> parts = split(spec, "-");
165         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
166         {
167                 bool ok = false;
168                 for(unsigned j=0; (!ok && types[j]); ++j)
169                         if(*i==types[j])
170                         {
171                                 if(!type.empty() && *i!=type)
172                                         throw InvalidParameterValue("Conflicting type specification");
173                                 type = *i;
174                                 ok = true;
175                         }
176                 for(unsigned j=0; (!ok && cpus[j]); j+=3)
177                         if(*i==cpus[j])
178                         {
179                                 if(type.empty())
180                                         type = cpus[j+1];
181                                 else if(cpus[j+1]!=type)
182                                         throw InvalidParameterValue("Conflicting CPU specification");
183                                 cpu = (cpus[j+2] ? cpus[j+2] : *i);
184                                 ok = true;
185                         }
186                 for(unsigned j=0; (!ok && systems[j]); ++j)
187                         if(*i==systems[j])
188                         {
189                                 system = *i;
190                                 ok = true;
191                         }
192                 if(!ok && (*i=="32" || *i=="64"))
193                 {
194                         bits = lexical_cast<unsigned>(*i);
195                         ok = true;
196                 }
197                 if(!ok)
198                         throw InvalidParameterValue("Unrecognized part in arch specification: "+*i);
199         }
200 }
201
202
203 Architecture::Loader::Loader(Architecture &a):
204         arch(a)
205 {
206         add("prefix", &Architecture::cross_prefix);
207         add("tool",   &Loader::tool);
208 }
209
210 void Architecture::Loader::tool(const string &t, const string &p)
211 {
212         arch.tools[t] = p;
213 }