Taaitaaiger / jlrs

Julia bindings for Rust
MIT License
407 stars 22 forks source link

LoadError: UndefVarError: `N` not defined #136

Open ju6ge opened 2 weeks ago

ju6ge commented 2 weeks ago

I just tried to upgrade to jlrs 0.20.0 updated all the rust side code and it compiles creating a shared library. But I am running into a Library Load error on the julia side of things. I am using JlrsCore 0.4.0.

Previously using jlrs 0.19.2 and JlrsCore 0.3.0 this did not happen. Any Ideas why this is happening. I tried removing singular functions and types from the module, but I have not figured out where this is coming from.

Taaitaaiger commented 2 weeks ago

That's odd, it's an error originating from Julia, but I can't find any variable named N being accessed in jlrs or JlrsCore. Are you able to load JlrsCore in a Julia session, and could you share the backtrace?

ju6ge commented 1 week ago

Yes I am able to load JlrsCore, i am using julia version 1.10.4

This is the Backtrace I am getting when tring to import my Package with the jlrs Bindings to the crate:

ERROR: LoadError: UndefVarError: `N` not defined
Stacktrace:
 [1] top-level scope
   @ none:1
in expression starting at /home/judge/development/core/CoreLibrary.jl/src/Raw.jl:1
in expression starting at /home/judge/development/core/CoreLibrary.jl/src/CoreLibrary.jl:1
in expression starting at stdin:3
  ✗ CoreLibrary
  3 dependencies successfully precompiled in 11 seconds. 5 already precompiled.

ERROR: The following 1 direct dependency failed to precompile:

CoreLibrary [c560e7d1-5c2b-42e0-af8a-98b688cd9fea]

Failed to precompile CoreLibrary [c560e7d1-5c2b-42e0-af8a-98b688cd9fea] to "/home/judge/.julia/compiled/v1.10/CoreLibrary/jl_JAVcrS".
ERROR: LoadError: UndefVarError: `N` not defined
Stacktrace:
 [1] top-level scope
   @ none:1
in expression starting at /home/judge/development/core/CoreLibrary.jl/src/Raw.jl:1
in expression starting at /home/judge/development/core/CoreLibrary.jl/src/CoreLibrary.jl:1
in expression starting at stdin:
Stacktrace:
 [1] precompile(pkgs::Vector{Pkg.Types.PackageSpec}; io::Base.TTY, kwargs::@Kwargs{_from_loading::Bool})
   @ Pkg.API /usr/share/julia/stdlib/v1.10/Pkg/src/API.jl:159
 [2] precompile
   @ /usr/share/julia/stdlib/v1.10/Pkg/src/API.jl:147 [inlined]
 [3] #precompile#114
   @ /usr/share/julia/stdlib/v1.10/Pkg/src/API.jl:146 [inlined]

For some more context this is the Contents of Raw.jl it is the JlrsCore import of the shared library:

module Raw

using JlrsCore.Wrap

libpath = joinpath(dirname(@__FILE__), "../assets/libcore.so")
@wrapmodule(libpath, :core_bootstrap)

function __init__()
    @initjlrs
end

end
Taaitaaiger commented 1 week ago

I've just run the export tests with Julia 1.10.4 on Linux and everything succeeded. It doesn't test precompilation though, which is precisely what's failing for you...

A few sanity checks:

  1. Did you replace the old library with the newly built one?
  2. Is the installed version of JlrsCore 0.4.0 according to pkg> status JlrsCore?
  3. Does your library or wrapped code use or create a constant named N?
  4. Does the library search path, includingLD_LIBRARY_PATH (assuming you're using Linux based on the .so extension), contain any lib directory of an old Julia installation?
ju6ge commented 5 days ago

Hi,

sorry for the delay in answering. I was busy chasing/solving other things. But I did have some time to dig a bit deeper:

To your sanity checks: 1 Yes I definitely replaced the library with the newly built one. 2 Output of status JlrsCore

   pkg> status JlrsCore
   Project CoreLibrary v0.6.1
   Status `/home/judge/development/core/CoreLibrary.jl/Project.toml`
     [29be08bc] JlrsCore v0.4.0

4 Nope that is not the case

But Point 3 did bring me closer to the problem:

There is no direct use of any constant named N either in the rust code nor in the julia code. But …

There is a rust side export with something like the following signature:

julia_module! {
 fn convert(&self, data: TypedArray<f64>) -> JlrsResult<TypedArrayRet<f64>> as  convert;
}

If I remove this export from the module precompilation works again. With it it fails. Since I think there where some changes related to how jlrs 0.20.0 handles Arrays that might be the reason for this issue. This export was already part of a version of the library using jlrs 0.19.2 and it did work there, so this does seem to be a regression.

I would need some more time to write a full little example library replicating the issue.

Taaitaaiger commented 5 days ago

Ah, that makes sense. Yeah, that would lead to an undefined N due to

unsafe impl<'scope, 'data, T: ConstructType, const N: isize> CCallArg
    for TypedRankedArray<'scope, 'data, T, N>
{
    type CCallArgType = Self;
    type FunctionArgType = Self;
}

unsafe impl<T: ConstructType, const N: isize> CCallReturn for TypedRankedArrayRet<T, N> {
    type CCallReturnType = TypedRankedArray<'static, 'static, T, N>;
    type FunctionReturnType = TypedRankedArray<'static, 'static, T, N>;
    type ReturnAs = Self;

    #[inline]
    unsafe fn return_or_throw(self) -> Self::ReturnAs {
        self
    }
}

which only works if N is known.

I'll try to fix it this weekend, as a work-around you should be able to use Value and ValueRet instead and cast the argument to a TypedArray in the function body. Or if you only want to support a single rank, you can set it explictly by using TypedRankedArray with N set to that rank.

Taaitaaiger commented 3 hours ago

Should be fixed by #137 and JlrsCore.jl 0.5.

ju6ge commented 44 minutes ago

Thanks I will give it a try tomorrow and will report the results.