Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add riscv64 PlatformSupport #374

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Add riscv64 PlatformSupport #374

wants to merge 1 commit into from

Conversation

eschnett
Copy link
Contributor

@eschnett eschnett commented Apr 7, 2024

No description provided.

@giordano
Copy link
Member

giordano commented Apr 7, 2024

What's the corresponding PR to Yggdrasil?

@eschnett
Copy link
Contributor Author

eschnett commented Apr 9, 2024

That's a complicated story... Adding a new architecture requires patches to BinaryBuilderBase, BinaryBuilder, and Julia itself. I'm building Yggdrasil packages with Julia 1.7, and it doesn't seem viable to have patches against it accepted.

At the moment this is just a test balloon to support RISC-V as a new architecture in general.

I think I'll start by opening a PR against Julia's master branch.

@giordano
Copy link
Member

giordano commented Apr 9, 2024

Ok, yeah, my next comment was going to be that it'll be complicated to have this going on with current incarnation of BinaryBuilder given adding new architectures/OSes requires changing in Julia, but we're currently stuck with Julia v1.7. https://github.com/JuliaPackaging/BinaryBuilder2.jl should improve the situation going forward, but we are definitely not there yet. But please do start with contributing changes to julia!

@eschnett
Copy link
Contributor Author

eschnett commented Apr 9, 2024

The BinaryBuilder PR JuliaPackaging/BinaryBuilder.jl#1321.

@eschnett
Copy link
Contributor Author

eschnett commented Apr 9, 2024

The BinaryBuilderBase PR: #375

@eschnett
Copy link
Contributor Author

eschnett commented Apr 9, 2024

The Yggdrasil PR: JuliaPackaging/Yggdrasil#8468

@eschnett
Copy link
Contributor Author

eschnett commented Apr 9, 2024

And the PR for Julia itself: JuliaLang/julia#54011

oscardssmith added a commit to JuliaLang/julia that referenced this pull request Apr 29, 2024
This patch adds support for `riscv64` as binary platform.

Note: This only allows Julia to handle `riscv64` in `BinaryPlatforms`
and `CPUID`. There is no support for either code generation or building
Julia on RISC-V systems. This is only a necessary first step towards
these goals. In particular, this is necessary to support building
external libraries for RISC-V via BinaryBuilder as described in
JuliaPackaging/BinaryBuilderBase.jl#374.

---------

Co-authored-by: Oscar Smith <[email protected]>
@oscardssmith
Copy link

Now that the julia side is merged, is this ready?

@giordano
Copy link
Member

That's really not that easy. BinaryBuilder only works with julia v1.7, so the changes in Julia v1.12 won't help. I think whatever changes we need to do on this side will have to wait for BinaryBuilder2

@eschnett
Copy link
Contributor Author

I have made corresponding changes to Julia 1.7. We could (i.e., I will have to) maintain a feature branch. This will allow us to go forward in the short term, and we can then merge some changes into BinaryBuilder, BinaryBuilderBase, and the Yggdrasil base image (or respective feature branches...)

@maleadt
Copy link
Contributor

maleadt commented Oct 22, 2024

@eschnett Couldn't we pirate the definitions in to get this functionality in 1.7?

using Base: BinaryPlatforms

@static if !haskey(BinaryPlatforms.arch_mapping, "riscv64")

using .BinaryPlatforms: CPUID
CPUID.ISAs_by_family["riscv64"] = [
    # We have no way to test riscv64 features yet, so we're only going to declare the lowest ISA:
    "riscv64" => CPUID.ISA(Set{UInt32}()),
]

@eval Base.BinaryPlatforms begin
    function validate_tags(tags::Dict)
        throw_invalid_key(k) = throw(ArgumentError("Key \"$(k)\" cannot have value \"$(tags[k])\""))
        # Validate `arch`
        if tags["arch"]  ("x86_64", "i686", "armv7l", "armv6l", "aarch64", "powerpc64le", "riscv64")
            throw_invalid_key("arch")
        end
        # Validate `os`
        if tags["os"]  ("linux", "macos", "freebsd", "windows")
            throw_invalid_key("os")
        end
        # Validate `os`/`arch` combination
        throw_os_mismatch() = throw(ArgumentError("Invalid os/arch combination: $(tags["os"])/$(tags["arch"])"))
        if tags["os"] == "windows" && tags["arch"]  ("x86_64", "i686", "armv7l", "aarch64")
            throw_os_mismatch()
        end
        if tags["os"] == "macos" && tags["arch"]  ("x86_64", "aarch64")
            throw_os_mismatch()
        end

        # Validate `os`/`libc` combination
        throw_libc_mismatch() = throw(ArgumentError("Invalid os/libc combination: $(tags["os"])/$(tags["libc"])"))
        if tags["os"] == "linux"
            # Linux always has a `libc` entry
            if tags["libc"]  ("glibc", "musl")
                throw_libc_mismatch()
            end
        else
            # Nothing else is allowed to have a `libc` entry
            if haskey(tags, "libc")
                throw_libc_mismatch()
            end
        end

        # Validate `os`/`arch`/`call_abi` combination
        throw_call_abi_mismatch() = throw(ArgumentError("Invalid os/arch/call_abi combination: $(tags["os"])/$(tags["arch"])/$(tags["call_abi"])"))
        if tags["os"] == "linux" && tags["arch"]  ("armv7l", "armv6l")
            # If an ARM linux has does not have `call_abi` set to something valid, be sad.
            if !haskey(tags, "call_abi") || tags["call_abi"]  ("eabihf", "eabi")
                throw_call_abi_mismatch()
            end
        else
            # Nothing else should have a `call_abi`.
            if haskey(tags, "call_abi")
                throw_call_abi_mismatch()
            end
        end

        # Validate `libgfortran_version` is a parsable `VersionNumber`
        throw_version_number(k) = throw(ArgumentError("\"$(k)\" cannot have value \"$(tags[k])\", must be a valid VersionNumber"))
        if "libgfortran_version" in keys(tags) && tryparse(VersionNumber, tags["libgfortran_version"]) === nothing
            throw_version_number("libgfortran_version")
        end

        # Validate `cxxstring_abi` is one of the two valid options:
        if "cxxstring_abi" in keys(tags) && tags["cxxstring_abi"]  ("cxx03", "cxx11")
            throw_invalid_key("cxxstring_abi")
        end

        # Validate `libstdcxx_version` is a parsable `VersionNumber`
        if "libstdcxx_version" in keys(tags) && tryparse(VersionNumber, tags["libstdcxx_version"]) === nothing
            throw_version_number("libstdcxx_version")
        end
    end
end

BinaryPlatforms.arch_mapping["riscv64"] = "(rv64|riscv64)"

function get_set(arch, name)
    all = BinaryPlatforms.CPUID.ISAs_by_family[arch]
    return all[findfirst(x -> x.first == name, all)].second
end
BinaryPlatforms.arch_march_isa_mapping["riscv64"] =
    ["riscv64" => get_set("riscv64", "riscv64")]

end

@giordano
Copy link
Member

Yeah, I'd be ok with a little hack like that, BinaryBuilder is typically used as a standalone application only, not as a library used by others, so it's kinda "safe" in this regard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants