@@ -85,4 +85,108 @@ function Base.BinaryPlatforms.validate_tags(tags::Dict)
8585 end
8686end
8787
88+ using . BinaryPlatforms: arch_mapping, os_mapping, libc_mapping, call_abi_mapping,
89+ libgfortran_version_mapping, cxxstring_abi_mapping, libstdcxx_version_mapping
90+
91+ function Base. parse (:: Type{Platform} , triplet:: AbstractString ; validate_strict:: Bool = false )
92+ # # Re-insert the architecture because the global assignments above don't stick
93+ # CPUID.ISAs_by_family["riscv64"] = [
94+ # # We have no way to test riscv64 features yet, so we're only going to declare the lowest ISA:
95+ # "riscv64" => CPUID.ISA(Set{UInt32}()),
96+ # ]
97+ # BinaryPlatforms.arch_mapping["riscv64"] = "(rv64|riscv64)"
98+ # BinaryPlatforms.arch_march_isa_mapping["riscv64"] = ["riscv64" => get_set("riscv64", "riscv64")]
99+
100+ # Helper function to collapse dictionary of mappings down into a regex of
101+ # named capture groups joined by "|" operators
102+ c (mapping) = string (" (" ,join ([" (?<$k >$v )" for (k, v) in mapping], " |" ), " )" )
103+
104+ # We're going to build a mondo regex here to parse everything:
105+ triplet_regex = Regex (string (
106+ " ^" ,
107+ # First, the core triplet; arch/os/libc/call_abi
108+ c (arch_mapping),
109+ c (os_mapping),
110+ c (libc_mapping),
111+ c (call_abi_mapping),
112+ # Next, optional things, like libgfortran/libstdcxx/cxxstring abi
113+ c (libgfortran_version_mapping),
114+ c (cxxstring_abi_mapping),
115+ c (libstdcxx_version_mapping),
116+ # Finally, the catch-all for extended tags
117+ " (?<tags>(?:-[^-]+\\ +[^-]+)*)?" ,
118+ " \$ " ,
119+ ))
120+
121+ m = match (triplet_regex, triplet)
122+ if m != = nothing
123+ # Helper function to find the single named field within the giant regex
124+ # that is not `nothing` for each mapping we give it.
125+ get_field (m, mapping) = begin
126+ for k in keys (mapping)
127+ if m[k] != = nothing
128+ # Convert our sentinel `nothing` values to actual `nothing`
129+ if endswith (k, " _nothing" )
130+ return nothing
131+ end
132+ # Convert libgfortran/libstdcxx version numbers
133+ if startswith (k, " libgfortran" )
134+ return VersionNumber (parse (Int,k[12 : end ]))
135+ elseif startswith (k, " libstdcxx" )
136+ return VersionNumber (3 , 4 , parse (Int,m[k][11 : end ]))
137+ else
138+ return k
139+ end
140+ end
141+ end
142+ end
143+
144+ # Extract the information we're interested in:
145+ arch = get_field (m, arch_mapping)
146+ os = get_field (m, os_mapping)
147+ libc = get_field (m, libc_mapping)
148+ call_abi = get_field (m, call_abi_mapping)
149+ libgfortran_version = get_field (m, libgfortran_version_mapping)
150+ libstdcxx_version = get_field (m, libstdcxx_version_mapping)
151+ cxxstring_abi = get_field (m, cxxstring_abi_mapping)
152+ function split_tags (tagstr)
153+ tag_fields = filter (! isempty, split (tagstr, " -" ))
154+ if isempty (tag_fields)
155+ return Pair{String,String}[]
156+ end
157+ return map (v -> Symbol (v[1 ]) => v[2 ], split .(tag_fields, " +" ))
158+ end
159+ tags = split_tags (m[" tags" ])
160+
161+ # Special parsing of os version number, if any exists
162+ function extract_os_version (os_name, pattern)
163+ m_osvn = match (pattern, m[os_name])
164+ if m_osvn != = nothing
165+ return VersionNumber (m_osvn. captures[1 ])
166+ end
167+ return nothing
168+ end
169+ os_version = nothing
170+ if os == " macos"
171+ os_version = extract_os_version (" macos" , r" .*darwin([\d\. ]+)" )
172+ end
173+ if os == " freebsd"
174+ os_version = extract_os_version (" freebsd" , r" .*freebsd([\d .]+)" )
175+ end
176+
177+ return Platform (
178+ arch, os;
179+ validate_strict,
180+ libc,
181+ call_abi,
182+ libgfortran_version,
183+ cxxstring_abi,
184+ libstdcxx_version,
185+ os_version,
186+ tags... ,
187+ )
188+ end
189+ throw (ArgumentError (" Platform `$(triplet) ` is not an officially supported platform" ))
190+ end
191+
88192end
0 commit comments