1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
// file : butl/target-triplet -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#ifndef BUTL_TARGET_TRIPLET
#define BUTL_TARGET_TRIPLET
#include <string>
#include <ostream>
#include <butl/export>
namespace butl
{
// This is the ubiquitous 'target triplet' that loosely has the CPU-VENDOR-OS
// form which, these days, quite often takes the CPU-VENDOR-OS-ABI form. Plus
// some fields can sometimes be omitted. This looseness makes it hard to base
// any kind of decisions on the triplet without canonicalizing it and then
// splitting it into components. The way we are going to split it is like
// this:
//
// CPU
//
// This one is reasonably straightforward. Note that we always expect at
// least two components with the first being the CPU. In other words, we
// don't try to guess what just 'mingw32' might mean like config.sub does.
//
// VENDOR
//
// This can be a machine vendor as in i686-apple-darwin8, a toolchain vendor
// as in i686-lfs-linux-gnu, or something else as in arm-softfloat-linux-gnu.
// Just as we think vendor is pretty irrelevant and can be ignored, comes
// MinGW-W64 and calls itself *-w64-mingw32. While it is tempting to
// attribute w64 to OS-ABI, the MinGW-W64 folks insist it is a (presumably
// toolchain) vendor.
//
// Another example where the vendor seems to be reused for something else
// entirely is the Intel's MIC architecture: x86_64-k1om-linux.
//
// To make things more regular we also convert the information-free vendor
// names 'pc', 'unknown' and 'none' to the empty name.
//
// OS/KERNEL-OS/OS-ABI
//
// This is where things get really messy and instead of trying to guess, we
// call the entire thing SYSTEM. Except, in certain cases, we factor out the
// trailing version, again, to make SYSTEM easier to compare to. For example,
// *-darwin14.5.0 becomes 'darwin' and '14.5.0'.
//
// Again, to make things more regular, if the first component in SYSTEM is
// none, then it is removed (so *-none-eabi becomes just 'eabi').
//
// Values for two-component systems (e.g., linux-gnu) that don't specify
// VENDOR explicitly are inherently ambiguous: is 'linux' VENDOR or part of
// SYSTEM? The only way to handle this is to recognize their specific names
// as special cases and this is what we do for some of the more common
// ones. The alternative would be to first run such names through config.sub
// which adds explicit VENDOR and this could be a reasonable fallback
// strategy for (presumably less common) cases were we don't split things
// correctly.
//
// Note also that the version splitting is only done for certain commonly-
// used targets.
//
// Some examples of canonicalization and splitting:
//
// x86_64-apple-darwin14.5.0 x86_64 apple darwin 14.5.0
// x86_64-unknown-freebsd10.2 x86_64 freebsd 10.2
// i686-elf i686 elf
// arm-eabi arm eabi
// arm-none-eabi arm eabi
// arm-none-linux-gnueabi arm linux-gnueabi
// arm-softfloat-linux-gnu arm softfloat linux-gnu
// i686-pc-mingw32 i686 mingw32
// i686-w64-mingw32 i686 w64 mingw32
// i686-lfs-linux-gnu i686 lfs linux-gnu
// x86_64-unknown-linux-gnu x86_64 linux-gnu
// x86_64-linux-gnux32 x86_64 linux-gnux32
// x86_64-microsoft-win32-msvc14.0 x86_64 microsoft win32-msvc 14.0
//
// Similar to version splitting, for certain commonly-used targets we also
// derive the "target class" which can be used as a shorthand, more
// convenient way to identify a targets. If the target is not recognized,
// then the special 'other' value is used. Currently the following classes
// are recognized:
//
// linux *-*-linux-*
// macos *-apple-darwin*
// bsd *-*-(freebsd|openbsd|netbsd)*
// windows *-*-win32-* | *-*-mingw32
//
// References:
//
// 1. The libtool repository contains the PLATFORM file that lists many known
// triplets.
//
// 2. LLVM has the Triple class with similar goals.
//
struct LIBBUTL_EXPORT target_triplet
{
std::string cpu;
std::string vendor;
std::string system;
std::string version;
std::string class_;
// Assemble and returning the canonical (i.e., the one we round-trip)
// target triplet string.
//
std::string
string () const;
bool
empty () const {return cpu.empty ();}
int
compare (const target_triplet& y) const
{
int r;
return
(r = cpu.compare (y.cpu)) != 0 ? r :
(r = vendor.compare (y.vendor)) != 0 ? r :
(r = system.compare (y.system)) != 0 ? r :
( version.compare (y.version));
}
// Parse the triplet throw std::invalid_argument if the triplet is not
// recognizable.
//
explicit
target_triplet (const std::string&);
target_triplet () = default;
};
inline bool
operator== (const target_triplet& x, const target_triplet& y)
{
return x.compare (y) == 0;
}
inline bool
operator!= (const target_triplet& x, const target_triplet& y)
{
return !(x == y);
}
inline std::ostream&
operator<< (std::ostream& o, const target_triplet& x)
{
return o << x.string ();
}
}
#endif // BUTL_TARGET_TRIPLET
|