]> git.tdb.fi Git - builder.git/blob - source/architecture.cpp
847711e351c3c7fc47ff93b60494e539f8c4c4b3
[builder.git] / source / architecture.cpp
1 #include <limits>
2 #ifndef WIN32
3 #include <sys/utsname.h>
4 #endif
5 #include <msp/strings/format.h>
6 #include <msp/strings/utils.h>
7 #include "architecture.h"
8 #include "builder.h"
9
10 using namespace std;
11 using namespace Msp;
12
13 namespace {
14
15 const char *types[] =
16 {
17         "pc",
18         "arm",
19         "ppc",
20         0
21 };
22
23 const char *cpus[] =
24 {
25         "i386",       "pc",
26         "i486",       "pc",
27         "pentium",    "pc",
28         "pentiumpro", "pc",
29         "pentium2",   "pc",
30         "pentium3",   "pc",
31         "pentium4",   "pc",
32         "core2",      "pc",
33         "k6",         "pc",
34         "athlon",     "pc",
35         "athlonxp",   "pc",
36         "athlon64",   "pc",
37         "armv5",      "arm",
38         0
39 };
40
41 const char *systems[] =
42 {
43         "linux",
44         "freebsd",
45         "darwin",
46         "windows",
47         "android",
48         0
49 };
50
51 const char *aliases[] =
52 {
53         "x86",   "pc",
54         "i586",  "pentium",
55         "i686",  "pentiumpro",
56         "x86_64", "athlon64",
57         "win32", "windows",
58         "power macintosh", "ppc",
59         0
60 };
61
62 }
63
64 Architecture::Architecture(Builder &b, const string &spec):
65         builder(b),
66         bits(0),
67         native(false)
68 {
69         if(spec.empty())
70         {
71 #ifdef WIN32
72                 system = "windows";
73 #else
74                 utsname un;
75                 if(uname(&un)==0)
76                 {
77                         system = tolower(un.sysname);
78                         parse_specification(tolower(un.machine));
79                         // We really only want to set type for the default arch
80                         cpu.clear();
81                 }
82 #endif
83                 bits = sizeof(void *)*numeric_limits<unsigned char>::digits;
84                 native = true;
85         }
86         else
87         {
88                 parse_specification(spec);
89                 const Architecture &native_arch = builder.get_native_arch();
90                 if(type.empty())
91                         type = native_arch.type;
92                 if(system.empty())
93                         system = native_arch.system;
94                 if(!bits)
95                 {
96                         if(type==native_arch.type)
97                                 bits = native_arch.bits;
98                         else
99                                 bits = 32;
100                 }
101
102                 if(type!=native_arch.type || system!=native_arch.system)
103                         cross_prefix = format("%s-%s", type, system);
104                 else if(bits==native_arch.bits)
105                         native = true;
106         }
107         name = type;
108         if(!cpu.empty())
109                 name += format("-%s", cpu);
110         name += format("-%d-%s", bits, system);
111
112         if(system=="windows")
113         {
114                 sharedlib_patterns.push_back(Pattern("%.dll"));
115                 sharedlib_patterns.push_back(Pattern("lib%.dll"));
116                 /* XXX Hack: Consider import libraries (*.dll.a) as dynamic libraries,
117                 even though technically they are linked statically. */
118                 sharedlib_patterns.push_back(Pattern("lib%.dll.a"));
119                 staticlib_patterns.push_back(Pattern("lib%.a"));
120                 executable_patterns.push_back(Pattern("%.exe"));
121         }
122         else
123         {
124                 if(system=="darwin")
125                         sharedlib_patterns.push_back(Pattern("lib%.dylib"));
126                 else
127                         sharedlib_patterns.push_back(Pattern("lib%.so"));
128                 staticlib_patterns.push_back(Pattern("lib%.a"));
129                 executable_patterns.push_back(Pattern("%"));
130         }
131 }
132
133 bool Architecture::match_name(const string &pattern) const
134 {
135         bool negate = (pattern[0]=='!');
136         vector<string> parts = split(pattern.substr(negate), "-");
137         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
138         {
139                 string part = resolve_alias(*i);
140                 if((part=="32" && bits==32) || (part=="64" && bits==64))
141                         ;
142                 else if(part!=type && part!=cpu && part!=system)
143                         return negate;
144         }
145         return !negate;
146 }
147
148 string Architecture::resolve_alias(const string &part) const
149 {
150         for(unsigned j=0; aliases[j]; j+=2)
151                 if(part==aliases[j])
152                         return aliases[j+1];
153
154         return part;
155 }
156
157 void Architecture::parse_specification(const string &spec)
158 {
159         vector<string> parts = split(spec, "-");
160         for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
161         {
162                 string part = resolve_alias(*i);
163
164                 bool ok = false;
165
166                 for(unsigned j=0; (!ok && types[j]); ++j)
167                         if(part==types[j])
168                         {
169                                 if(!type.empty() && part!=type)
170                                         throw invalid_argument("Conflicting type specification");
171                                 type = part;
172                                 ok = true;
173                         }
174
175                 for(unsigned j=0; (!ok && cpus[j]); j+=2)
176                         if(part==cpus[j])
177                         {
178                                 if(type.empty())
179                                         type = cpus[j+1];
180                                 else if(cpus[j+1]!=type)
181                                         throw invalid_argument("Conflicting CPU specification");
182                                 cpu = part;
183                                 ok = true;
184                         }
185
186                 for(unsigned j=0; (!ok && systems[j]); ++j)
187                         if(part==systems[j])
188                         {
189                                 system = part;
190                                 ok = true;
191                         }
192
193                 if(!ok && (part=="32" || part=="64"))
194                 {
195                         bits = lexical_cast<unsigned>(part);
196                         ok = true;
197                 }
198
199                 if(!ok)
200                         throw invalid_argument("Unrecognized part in arch specification: "+*i);
201         }
202 }
203
204
205 Architecture::Loader::Loader(Architecture &a):
206         DataFile::ObjectLoader<Architecture>(a)
207 {
208         add("prefix", &Architecture::cross_prefix);
209 }