Skip to content

Commit bb322ce

Browse files
authored
Support platform augmentation for riscv64 (#1368)
* Support platform augmentation for riscv64 * Correct string interpolation syntax * Clean up comments * Use raw string * Set `arch_mapping["riscv64"]`
1 parent 6981412 commit bb322ce

File tree

2 files changed

+125
-6
lines changed

2 files changed

+125
-6
lines changed

src/AutoBuild.jl

+122-2
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,124 @@ function build_jll_package(src_name::String,
14161416
!ispath(pkg_dir) && mkdir(pkg_dir)
14171417
write(joinpath(pkg_dir, "platform_augmentation.jl"), augment_platform_block)
14181418

1419+
overload_parse = raw"""
1420+
# Update Base.parse to support riscv64, needed for Julia <1.12
1421+
@static if !haskey(BinaryPlatforms.arch_mapping, "riscv64")
1422+
1423+
BinaryPlatforms.arch_mapping["riscv64"] = "(rv64|riscv64)"
1424+
1425+
function bbparse(::Type{Platform}, triplet::AbstractString; validate_strict::Bool = false)
1426+
arch_mapping = BinaryPlatforms.arch_mapping
1427+
os_mapping = BinaryPlatforms.os_mapping
1428+
libc_mapping = BinaryPlatforms.libc_mapping
1429+
call_abi_mapping = BinaryPlatforms.call_abi_mapping
1430+
libgfortran_version_mapping = BinaryPlatforms.libgfortran_version_mapping
1431+
cxxstring_abi_mapping = BinaryPlatforms.cxxstring_abi_mapping
1432+
libstdcxx_version_mapping = BinaryPlatforms.libstdcxx_version_mapping
1433+
1434+
# Helper function to collapse dictionary of mappings down into a regex of
1435+
# named capture groups joined by "|" operators
1436+
c(mapping) = string("(",join(["(?<$k>$v)" for (k, v) in mapping], "|"), ")")
1437+
1438+
# We're going to build a mondo regex here to parse everything:
1439+
triplet_regex = Regex(string(
1440+
"^",
1441+
# First, the core triplet; arch/os/libc/call_abi
1442+
c(arch_mapping),
1443+
c(os_mapping),
1444+
c(libc_mapping),
1445+
c(call_abi_mapping),
1446+
# Next, optional things, like libgfortran/libstdcxx/cxxstring abi
1447+
c(libgfortran_version_mapping),
1448+
c(cxxstring_abi_mapping),
1449+
c(libstdcxx_version_mapping),
1450+
# Finally, the catch-all for extended tags
1451+
"(?<tags>(?:-[^-]+\\+[^-]+)*)?",
1452+
"\$",
1453+
))
1454+
1455+
m = match(triplet_regex, triplet)
1456+
if m !== nothing
1457+
# Helper function to find the single named field within the giant regex
1458+
# that is not `nothing` for each mapping we give it.
1459+
get_field(m, mapping) = begin
1460+
for k in keys(mapping)
1461+
if m[k] !== nothing
1462+
# Convert our sentinel `nothing` values to actual `nothing`
1463+
if endswith(k, "_nothing")
1464+
return nothing
1465+
end
1466+
# Convert libgfortran/libstdcxx version numbers
1467+
if startswith(k, "libgfortran")
1468+
return VersionNumber(parse(Int,k[12:end]))
1469+
elseif startswith(k, "libstdcxx")
1470+
return VersionNumber(3, 4, parse(Int,m[k][11:end]))
1471+
else
1472+
return k
1473+
end
1474+
end
1475+
end
1476+
end
1477+
1478+
# Extract the information we're interested in:
1479+
arch = get_field(m, arch_mapping)
1480+
os = get_field(m, os_mapping)
1481+
libc = get_field(m, libc_mapping)
1482+
call_abi = get_field(m, call_abi_mapping)
1483+
libgfortran_version = get_field(m, libgfortran_version_mapping)
1484+
libstdcxx_version = get_field(m, libstdcxx_version_mapping)
1485+
cxxstring_abi = get_field(m, cxxstring_abi_mapping)
1486+
function split_tags(tagstr)
1487+
tag_fields = filter(!isempty, split(tagstr, "-"))
1488+
if isempty(tag_fields)
1489+
return Pair{String,String}[]
1490+
end
1491+
return map(v -> Symbol(v[1]) => v[2], split.(tag_fields, "+"))
1492+
end
1493+
tags = split_tags(m["tags"])
1494+
1495+
# Special parsing of os version number, if any exists
1496+
function extract_os_version(os_name, pattern)
1497+
m_osvn = match(pattern, m[os_name])
1498+
if m_osvn !== nothing
1499+
return VersionNumber(m_osvn.captures[1])
1500+
end
1501+
return nothing
1502+
end
1503+
os_version = nothing
1504+
if os == "macos"
1505+
os_version = extract_os_version("macos", r".*darwin([\d.]+)"sa)
1506+
end
1507+
if os == "freebsd"
1508+
os_version = extract_os_version("freebsd", r".*freebsd([\d.]+)"sa)
1509+
end
1510+
if os == "openbsd"
1511+
os_version = extract_os_version("openbsd", r".*openbsd([\d.]+)"sa)
1512+
end
1513+
1514+
return Platform(
1515+
arch, os;
1516+
validate_strict,
1517+
libc,
1518+
call_abi,
1519+
libgfortran_version,
1520+
cxxstring_abi,
1521+
libstdcxx_version,
1522+
os_version,
1523+
tags...,
1524+
)
1525+
end
1526+
throw(ArgumentError("Platform `$(triplet)` is not an officially supported platform"))
1527+
end
1528+
1529+
else
1530+
# riscv64 is supported, all is fine
1531+
1532+
const bbparse = parse
1533+
1534+
end
1535+
"""
1536+
14191537
write(joinpath(pkg_dir, "select_artifacts.jl"),
14201538
"""
14211539
push!(Base.LOAD_PATH, dirname(@__DIR__))
@@ -1424,16 +1542,18 @@ function build_jll_package(src_name::String,
14241542
include("./platform_augmentation.jl")
14251543
artifacts_toml = joinpath(dirname(@__DIR__), "Artifacts.toml")
14261544
1545+
$(overload_parse)
1546+
14271547
# Get "target triplet" from ARGS, if given (defaulting to the host triplet otherwise)
14281548
target_triplet = get(ARGS, 1, Base.BinaryPlatforms.host_triplet())
14291549
14301550
# Augment this platform object with any special tags we require
1431-
platform = augment_platform!(HostPlatform(parse(Platform, target_triplet)))
1551+
platform = augment_platform!(HostPlatform(bbparse(Platform, target_triplet)))
14321552
14331553
# Select all downloadable artifacts that match that platform
14341554
artifacts = select_downloadable_artifacts(artifacts_toml; platform, include_lazy=true)
14351555
1436-
#Output the result to `stdout` as a TOML dictionary
1556+
# Output the result to `stdout` as a TOML dictionary
14371557
TOML.print(stdout, artifacts)
14381558
""")
14391559
end

test/building.jl

+3-4
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,14 @@ shards_to_test = expand_cxxstring_abis(expand_gfortran_versions(shards_to_test))
116116
if !(platforms_match(shard, Platform("i686", "windows")) ||
117117
platforms_match(shard, Platform("aarch64", "freebsd")) ||
118118
platforms_match(shard, Platform("riscv64", "linux")))
119-
# Rust is broken on 32-bit Windows and unavailable on FreeBSD AArch64 and RISC-V, let's skip it
119+
# Rust is broken on 32-bit Windows and unavailable on FreeBSD AArch64 and Linux RISC-V, let's skip it
120120
push!(products, ExecutableProduct("hello_world_rust", :hello_world_rust))
121121
end
122122

123123
compilers = [:c, :go]
124-
# Don't even ask for Rust on FreeBSD AArch64 or RISC-V
124+
# Don't even ask for Rust on FreeBSD AArch64 and Linux RISC-V
125125
if !(platforms_match(shard, Platform("aarch64", "freebsd")) ||
126-
platforms_match(shard, Platform("riscv64", "linux"))
127-
)
126+
platforms_match(shard, Platform("riscv64", "linux")))
128127
push!(compilers, :rust)
129128
end
130129

0 commit comments

Comments
 (0)