From 70c9d08118e50355a46a4a9b8d20c95278df5285 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:14:13 -0700 Subject: [PATCH 1/9] switch to using Wolfram app discovery --- Project.toml | 1 + deps/build.jl | 114 ------------------------------------------------ src/MathLink.jl | 18 +++----- src/init.jl | 30 +++++++++---- src/link.jl | 37 +++++++++++----- src/wstp.jl | 54 +++++++++++------------ 6 files changed, 82 insertions(+), 172 deletions(-) delete mode 100644 deps/build.jl diff --git a/Project.toml b/Project.toml index c58dd9a..a53e254 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.5.1" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +WolframAppDiscovery_jll = "630c5959-bfb3-598a-bb45-cbcabe526631" [compat] julia = "1" diff --git a/deps/build.jl b/deps/build.jl deleted file mode 100644 index 852f9d7..0000000 --- a/deps/build.jl +++ /dev/null @@ -1,114 +0,0 @@ -using Libdl - -function find_lib_ker() - if haskey(ENV,"JULIA_MATHLINK") && haskey(ENV,"JULIA_MATHKERNEL") - return ENV["JULIA_MATHLINK"], ENV["JULIA_MATHKERNEL"] - elseif Sys.isapple() - # we query OS X metadata for possible non-default installations - # TODO: can use `mdls -raw -name kMDItemVersion $path` to get the versio - - # Mathematica - for path in readlines(`mdfind "kMDItemCFBundleIdentifier == 'com.wolfram.Mathematica'"`) - lib = joinpath(path,"Contents/Frameworks/mathlink.framework/mathlink") - ker = joinpath(path,"Contents/MacOS/MathKernel") - if isfile(lib) && isfile(ker) - return lib, ker - end - end - - # Wolfram Engine - for path in readlines(`mdfind "kMDItemCFBundleIdentifier == 'com.wolfram.*'"`) - # kernels are located in sub-application - subpath = joinpath(path, "Contents/Resources/Wolfram Player.app") - lib = joinpath(subpath,"Contents/Frameworks/mathlink.framework/mathlink") - ker = joinpath(subpath,"Contents/MacOS/MathKernel") - if isfile(lib) && isfile(ker) - return lib, ker - end - end - - elseif Sys.isunix() - archdir = Sys.ARCH == :arm ? "Linux-ARM" : - Sys.ARCH == :x86_64 ? "Linux-x86-64" : - "Linux" - - ker = get(ENV,"JULIA_MATHKERNEL") do - for kername in ["WolframKernel", "MathKernel", "wolfram", "math"] - if Sys.isexecutable(Sys.which(kername)) - return kername - end - end - - for mpath in ["/usr/local/Wolfram/Mathematica","/opt/Wolfram/WolframEngine"] - if isdir(mpath) - vers = readdir(mpath) - ver = vers[argmax(map(VersionNumber,vers))] - for kername in ["WolframKernel", "MathKernel", "wolfram", "math"] - fullkername = joinpath(mpath,ver,"Executables",kername) - if Sys.isexecutable(fullkername) - return fullkername - end - end - end - end - error("Could not find Wolfram engine kernel") - end - - @show basepath = String(read(`$ker -noprompt -run "WriteString[\$Output,\$InstallationDirectory];Exit[]"`)) - - lib = Libdl.find_library( - ["libML$(Sys.WORD_SIZE)i4","libML$(Sys.WORD_SIZE)i3"], - [joinpath(basepath,"SystemFiles/Links/MathLink/DeveloperKit",archdir,"CompilerAdditions")]) - - return lib, ker - elseif Sys.iswindows() - archdir = Sys.ARCH == :x86_64 ? "Windows-x86-64" : - "Windows" - - # TODO: query Windows Registry, see RCall.jl - # it looks like it registers stuff in - # HKEY_LOCAL_MACHINE\SOFTWARE\Wolfram Research\Installations\ - # but not clear how it is organized - if haskey(ENV, "JULIA_WOLFRAM_DIR") - wpaths = [ENV["JULIA_WOLFRAM_DIR"]] - else - wpaths = String[] - for dir in ["C:\\Program Files\\Wolfram Research\\Mathematica", "C:\\Program Files\\Wolfram Research\\Wolfram Engine"] - if isdir(mpath) - for ver in readdir(mpath) - push!(wpaths, joinpath(dir, ver)) - end - end - end - end - for wpath in wpaths - lib = Libdl.find_library( - ["ml$(Sys.WORD_SIZE)i4.dll", "libML$(Sys.WORD_SIZE)i4", "ml$(Sys.WORD_SIZE)i3.dll", "libML$(Sys.WORD_SIZE)i3"], - [joinpath(wpath,"SystemFiles\\Links\\MathLink\\DeveloperKit",archdir,"SystemAdditions")]) - ker = joinpath(wpath,"math.exe") - return lib, ker - end - end - - error("Could not find Mathematica or Wolfram Engine installation.\nPlease set the `JULIA_MATHLINK` and `JULIA_MATHKERNEL` variables.") -end - - -if get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", "false") == "true" - # We need to be able to install and load this package without error for - # Julia's registry AutoMerge to work. Just write a fake Mathematica path. - mlib = "" - mker = "WolframKernel" - @info "Pretending fake installation exists" mlib mker -else - mlib,mker = find_lib_ker() - @info "Installation found" mlib mker -end - - - -open("deps.jl","w") do f - println(f, "# this file is automatically generated") - println(f, :(const mlib = $mlib)) - println(f, :(const mker = $mker)) -end diff --git a/src/MathLink.jl b/src/MathLink.jl index 450c63c..3ae06d5 100644 --- a/src/MathLink.jl +++ b/src/MathLink.jl @@ -4,22 +4,14 @@ using Printf export @W_str, @W_cmd, weval +using WolframAppDiscovery_jll -###Checking that the deps.jl file exists. And throwing a readable error if it does not! - -FilePath=@__DIR__ -FilePath=FilePath[1:end-4]*"/deps/deps.jl" - - -#if isfile("../deps/deps.jl") - #include("../deps/deps.jl") -if isfile(FilePath) - include(FilePath) +if VERSION >= v"1.8" + libwstp::String = "" else - error("The file $FilePath does not exist.\n" - *"This usually means that the MathLink installation failed.\n" - *"Have you checked that Mathematica is installed on your system?") + libwstp = "" end + include("types.jl") include("consts.jl") include("init.jl") diff --git a/src/init.jl b/src/init.jl index ee626eb..8c6bf47 100644 --- a/src/init.jl +++ b/src/init.jl @@ -29,20 +29,34 @@ function refcount_dec() # refcount zero, all objects finalized, now finalize MathLink if Threads.atomic_sub!(REFCOUNT, 1) == 1 # void WSDeinitialize(WSENV env) - ccall((:MLDeinitialize, mlib), Cvoid, (CEnv,), env) + ccall((:WSDeinitialize, libwstp), Cvoid, (CEnv,), env) env.ptr = C_NULL end end + function __init__() - if mlib == "" - ###when JULIA_REGISTRYCI_AUTOMERGE=true the mlib is an empty string, and we can test for that - # We need to be able to install and load this package without error for - # Julia's registry AutoMerge to work. Skip initialization of the mathlink library. - @info "Pretending fake installation works" - else + + out = IOBuffer() + if !success(pipeline(`$(wolfram_app_discovery()) default --raw-value wstp-compiler-additions-directory`, out)) + @debug "Could not find WSTP installation" + return + end + wstp_dir = String(take!(out)) + + if Sys.iswindows() + global libwstp = joinpath(wstp_dir, "SystemAdditions", "wstp$(Sys.WORD_SIZE)i4.dll") + elseif Sys.isapple() + global libwstp = joinpath(wstp_dir, "wstp.framework", "wstp") + elseif Sys.isunix() + global libwstp = joinpath(wstp_dir, "CompilerAdditions", "libWSTP$(Sys.WORD_SIZE)i4.so") + end + + @info "WSTP installation found" wstp_dir libwstp + + if libwstp != "" # WSENV WSInitialize(WSEnvironmentParameter p) - env.ptr = ccall((:MLInitialize, mlib), CEnv, (Ptr{Cvoid},), C_NULL) + env.ptr = ccall((:WSInitialize, libwstp), CEnv, (Ptr{Cvoid},), C_NULL) if env.ptr == C_NULL error("Could not initialize MathLink library") end diff --git a/src/link.jl b/src/link.jl index 4d33bfb..8659d31 100644 --- a/src/link.jl +++ b/src/link.jl @@ -19,10 +19,13 @@ const defaultlink = Link(C_NULL) # we define an in-place version to operate on defaultlink function open!(link::Link, args::AbstractString) + if env.ptr == C_NULL + error("WSTP library not found, set WOLFRAM_APP_DIRECTORY environment variable") + end # MLOpenString # local link err = Ref{Cint}() - ptr = ccall((:MLOpenString, mlib), CLink, + ptr = ccall((:WSOpenString, libwstp), CLink, (Env, Cstring, Ptr{Cint}), env, args, err) if err[] != 0 @@ -36,10 +39,13 @@ function open!(link::Link, args::AbstractString) end function open!(link::Link, args::Vector) + if env.ptr == C_NULL + error("WSTP library not found, set WOLFRAM_APP_DIRECTORY environment variable") + end # MLOpenString # local link err = Ref{Cint}() - ptr = ccall((:MLOpenArgcArgv, mlib), CLink, + ptr = ccall((:WSOpenArgcArgv, libwstp), CLink, (Env, Cint, Ptr{Cstring}, Ptr{Cint}), env, length(args), args, err) if err[] != 0 @@ -56,7 +62,7 @@ open(args::AbstractString) = open!(Link(C_NULL), args) function Base.close(link::Link) if link.ptr != C_NULL - ccall((:MLClose, mlib), Cvoid, (CLink,), link) + ccall((:WSClose, libwstp), Cvoid, (CLink,), link) link.ptr = C_NULL refcount_dec() end @@ -64,17 +70,17 @@ end function getname(link::Link) # WSLINK WSGetLinkName(WSLINK link) - ptr = ccall((:MLUTF8LinkName, mlib), Cstring, (CLink,), link) + ptr = ccall((:WSUTF8LinkName, libwstp), Cstring, (CLink,), link) ptr == C_NULL && throw(MathLinkError(link)) str = unsafe_string(ptr) - ccall((:MLReleaseUTF8LinkName, mlib), Cvoid, (CLink,Cstring), link, ptr) + ccall((:WSReleaseUTF8LinkName, libwstp), Cvoid, (CLink,Cstring), link, ptr) return str end function duplicate(link::Link, name::AbstractString) # WSLINK WSDuplicateLink(WSLINK link, int *errp) err = Ref{Cint}() - ptr = ccall((:MLDuplicateLink, mlib), CLink, (CLink, Cstring, Ptr{Cint}), link, name, err) + ptr = ccall((:WSDuplicateLink, libwstp), CLink, (CLink, Cstring, Ptr{Cint}), link, name, err) if err[] != 0 throw(MathLinkError(link)) end @@ -84,12 +90,23 @@ function duplicate(link::Link, name::AbstractString) return newlink end +""" + local_kernel_path() + +The path to the local kernel. This is used to launch a link to the kernel. +""" +function local_kernel_path() + read(`$(wolfram_app_discovery()) default --raw-value kernel-executable-path`, String) +end + + function _defaultlink() if defaultlink.ptr == C_NULL + kernel = local_kernel_path() args = [ "-linkname", - "\"$mker\" -mathlink", + "\"$(escape_string(kernel))\" -wstp", "-linkmode", "launch", ] @@ -113,7 +130,7 @@ Base.cconvert(::Type{CMark}, mark::Mark) = mark.ptr # we don't overload Base.mark as it has different behaviour function Mark(link::Link) # WSMARK WSCreateMark(WSLINK link) - ptr = ccall((:MLCreateMark, mlib), Ptr{Cvoid}, (CLink,), link) + ptr = ccall((:WSCreateMark, libwstp), Ptr{Cvoid}, (CLink,), link) ptr == C_NULL && throw(MathLinkError(link)) mark = Mark(link, ptr) refcount_inc() @@ -123,7 +140,7 @@ end function Base.seek(link::Link, mark::Mark, offset::Integer=Cint(0)) # WSMARK WSSeekToMark(WSLINK link,WSMARK mark,int n) - ptr = ccall((:MLSeekToMark, mlib), Ptr{Cvoid}, + ptr = ccall((:WSSeekToMark, libwstp), Ptr{Cvoid}, (CLink, CMark, Cint), link, mark, offset) ptr == C_NULL && throw(MathLinkError(link)) return nothing @@ -132,7 +149,7 @@ end function Base.close(mark::Mark) if mark.ptr != C_NULL # void WSDestroyMark(WSLINK link,WSMARK mark) - ccall((:MLDestroyMark, mlib), Cvoid, + ccall((:WSDestroyMark, libwstp), Cvoid, (CLink, CMark), mark.link, mark) mark.ptr = C_NULL refcount_dec() diff --git a/src/wstp.jl b/src/wstp.jl index 421d89b..00eae7c 100644 --- a/src/wstp.jl +++ b/src/wstp.jl @@ -3,22 +3,22 @@ struct MathLinkError <: Exception msg::String end function MathLinkError(link::Link) - err = ccall((:MLError, mlib), Error, (CLink,), link) - msg = unsafe_string(ccall((:MLErrorMessage, mlib), Cstring, (CLink,), link)) + err = ccall((:WSError, libwstp), Error, (CLink,), link) + msg = unsafe_string(ccall((:WSErrorMessage, libwstp), Cstring, (CLink,), link)) clearerror(link) newpacket(link) MathLinkError(err, msg) end clearerror(link::Link) = - ccall((:MLClearError, mlib), Cint, (CLink,), link) + ccall((:WSClearError, libwstp), Cint, (CLink,), link) endpacket(link::Link) = - ccall((:MLEndPacket, mlib), Cint, (CLink,), link) + ccall((:WSEndPacket, libwstp), Cint, (CLink,), link) newpacket(link::Link) = - ccall((:MLNewPacket, mlib), Cint, (CLink,), link) + ccall((:WSNewPacket, libwstp), Cint, (CLink,), link) nextpacket(link::Link) = - ccall((:MLNextPacket, mlib), Packet, (CLink,), link) + ccall((:WSNextPacket, libwstp), Packet, (CLink,), link) macro wschk(expr) link = expr.args[5] # first argument @@ -32,7 +32,7 @@ end function getargcount(link::Link) r = Ref{Cint}() # int WSGetArgCount(WSLINK link,int *n) - @wschk ccall((:MLGetArgCount, mlib), Cint, + @wschk ccall((:WSGetArgCount, libwstp), Cint, (CLink, Ptr{Cint}), link, r) r[] @@ -40,14 +40,14 @@ end function putargcount(link::Link, n::Integer) # int WSPutArgCount(WSLINK link,int n) - @wschk ccall((:MLPutArgCount, mlib), Cint, + @wschk ccall((:WSPutArgCount, libwstp), Cint, (CLink, Cint), link, n) nothing end function putfunction(link::Link, w::WSymbol, nargs::Integer) # int MLPutUTF8Function(( MLLINK l , const unsigned char * s , int v , int n ) - @wschk ccall((:MLPutUTF8Function, mlib), Cint, + @wschk ccall((:WSPutUTF8Function, libwstp), Cint, (CLink, Ptr{UInt8}, Cint, Cint), link, w.name, sizeof(w.name), nargs) nothing @@ -57,12 +57,12 @@ function getfunction(link::Link) r_bytes = Ref{Cint}() r_nargs = Ref{Cint}() # int MLGetUTF8Function( MLLINK l , const unsigned char ** s , int * v , int * n ) - @wschk ccall((:MLGetUTF8Function, mlib), Cint, + @wschk ccall((:WSGetUTF8Function, libwstp), Cint, (CLink, Ptr{Ptr{UInt8}}, Ptr{Cint}, Ptr{Cint}), link, r_str, r_bytes, r_nargs) str = unsafe_string(r_str[], r_bytes[]) # void MLReleaseUTF8Symbol(MLLINK link,const unsigned char *s,int len) - ccall((:MLReleaseUTF8Symbol, mlib), Cvoid, + ccall((:WSReleaseUTF8Symbol, libwstp), Cvoid, (CLink, Ptr{UInt8}, Cint), link, r_str[], r_bytes[]) return WSymbol(str), r_nargs[] @@ -71,7 +71,7 @@ end # WSymbol function put(link::Link, w::WSymbol) # int MLPutUTF8Symbol(MLLINK link,const unsigned char *s,int len) - @wschk ccall((:MLPutUTF8Symbol, mlib), Cint, + @wschk ccall((:WSPutUTF8Symbol, libwstp), Cint, (CLink, Ptr{UInt8}, Cint), link, w.name, sizeof(w.name)) nothing @@ -81,12 +81,12 @@ function get(link::Link, ::Type{WSymbol}) r_bytes = Ref{Cint}() r_chars = Ref{Cint}() # int MLGetUTF8Symbol(MLLINK link,const unsigned char **s,int *b,int *c) - @wschk ccall((:MLGetUTF8Symbol, mlib), Cint, + @wschk ccall((:WSGetUTF8Symbol, libwstp), Cint, (CLink, Ptr{Ptr{UInt8}}, Ptr{Cint}, Ptr{Cint}), link, r_str, r_bytes, r_chars) str = unsafe_string(r_str[], r_bytes[]) # void MLReleaseUTF8Symbol(MLLINK link,const unsigned char *s,int len) - ccall((:MLReleaseUTF8Symbol, mlib), Cvoid, + ccall((:WSReleaseUTF8Symbol, libwstp), Cvoid, (CLink, Ptr{UInt8}, Cint), link, r_str[], r_bytes[]) return WSymbol(str) @@ -95,7 +95,7 @@ end # WReal/WInteger function put(link::Link, w::WReal) # int MLPutRealNumberAsUTF8String(MLLINK l, const unsigned char *s, int n) - @wschk ccall((:MLPutRealNumberAsUTF8String, mlib), Cint, + @wschk ccall((:WSPutRealNumberAsUTF8String, libwstp), Cint, (CLink, Ptr{UInt8}, Cint), link, w.value, sizeof(w.value)) nothing @@ -105,12 +105,12 @@ function get(link::Link, ::Type{W}) where W <: Union{WReal,WInteger} r_bytes = Ref{Cint}() r_chars = Ref{Cint}() # int MLGetNumberAsUTF8String(MLLINK l, const unsigned char **s, int *v, int *c) - @wschk ccall((:MLGetNumberAsUTF8String, mlib), Cint, + @wschk ccall((:WSGetNumberAsUTF8String, libwstp), Cint, (CLink, Ptr{Ptr{UInt8}}, Ptr{Cint}, Ptr{Cint}), link, r_str, r_bytes, r_chars) str = unsafe_string(r_str[], r_bytes[]) # void MLReleaseUTF8String(MLLINK link,const unsigned char *s,int len) - ccall((:MLReleaseUTF8String, mlib), Cvoid, + ccall((:WSReleaseUTF8String, libwstp), Cvoid, (CLink, Ptr{UInt8}, Cint), link, r_str[], r_bytes[]) return W(str) @@ -120,7 +120,7 @@ end # String function put(link::Link, str::Union{String,SubString}) # int MLPutUTF8String(MLLINK link,const unsigned char *s,int len) - @wschk ccall((:MLPutUTF8String, mlib), Cint, + @wschk ccall((:WSPutUTF8String, libwstp), Cint, (CLink, Ptr{UInt8}, Cint), link, str, sizeof(str)) nothing @@ -130,12 +130,12 @@ function get(link::Link, ::Type{String}) r_bytes = Ref{Cint}() r_chars = Ref{Cint}() # int MLGetUTF8String(MLLINK link,const unsigned char **s,int *b,int *c) - @wschk ccall((:MLGetUTF8String, mlib), Cint, + @wschk ccall((:WSGetUTF8String, libwstp), Cint, (CLink, Ptr{Ptr{UInt8}}, Ptr{Cint}, Ptr{Cint}), link, r_str, r_bytes, r_chars) str = unsafe_string(r_str[], r_bytes[]) # void MLReleaseUTF8String(MLLINK link,const unsigned char *s,int len) - ccall((:MLReleaseUTF8String, mlib), Cvoid, + ccall((:WSReleaseUTF8String, libwstp), Cvoid, (CLink, Ptr{UInt8}, Cint), link, r_str[], r_bytes[]) return str @@ -152,12 +152,12 @@ for (f, T) in [ @eval begin function put(link::Link, x::$T) # note slightly bizarre handling of Float32 - @wschk ccall(($(QuoteNode(Symbol(:MLPut, f))), mlib), Cint, (CLink, $(f == :Real32 ? Float64 : T)), link, x) + @wschk ccall(($(QuoteNode(Symbol(:WSPut, f))), libwstp), Cint, (CLink, $(f == :Real32 ? Float64 : T)), link, x) nothing end function get(link::Link, ::Type{$T}) r = Ref{$T}() - @wschk ccall(($(QuoteNode(Symbol(:MLGet, f))), mlib), Cint, (CLink, Ptr{$T}), link, r) + @wschk ccall(($(QuoteNode(Symbol(:WSGet, f))), libwstp), Cint, (CLink, Ptr{$T}), link, r) r[] end end @@ -167,17 +167,17 @@ end # Get fns gettype(link::Link) = - ccall((:MLGetType, mlib), Token, (CLink,), link) + ccall((:WSGetType, libwstp), Token, (CLink,), link) getrawtype(link::Link) = - ccall((:MLGetRawType, mlib), Token, (CLink,), link) + ccall((:WSGetRawType, libwstp), Token, (CLink,), link) puttype(link::Link, t::Token) = - @wschk ccall((:MLPutType, mlib), Cint, (CLink, Token), link, t) + @wschk ccall((:WSPutType, libwstp), Cint, (CLink, Token), link, t) getnext(link::Link) = - ccall((:MLGetNext, mlib), Token, (CLink,), link) + ccall((:WSGetNext, libwstp), Token, (CLink,), link) getnextraw(link::Link) = - ccall((:MLGetNextRaw, mlib), Token, (CLink,), link) + ccall((:WSGetNextRaw, libwstp), Token, (CLink,), link) From c03406aa399798ff9e47f2da630c97ed3a080b3e Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:22:03 -0700 Subject: [PATCH 2/9] fix some paths --- .github/workflows/CI.yml | 4 ++-- src/init.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4d8719c..f50ec8b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,6 +20,8 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + env: + WOLFRAM_APP_DIRECTORY: '${{ runner.temp }}\${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: @@ -102,8 +104,6 @@ jobs: - uses: julia-actions/setup-julia@v1 - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - env: - JULIA_WOLFRAM_DIR: '${{ runner.temp }}\${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 diff --git a/src/init.jl b/src/init.jl index 8c6bf47..59b7d90 100644 --- a/src/init.jl +++ b/src/init.jl @@ -45,7 +45,7 @@ function __init__() wstp_dir = String(take!(out)) if Sys.iswindows() - global libwstp = joinpath(wstp_dir, "SystemAdditions", "wstp$(Sys.WORD_SIZE)i4.dll") + global libwstp = joinpath(wstp_dir, "wstp$(Sys.WORD_SIZE)i4.dll") elseif Sys.isapple() global libwstp = joinpath(wstp_dir, "wstp.framework", "wstp") elseif Sys.isunix() From 732bf639caa874601fc937ff4332d5b1fb41aa0d Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:24:49 -0700 Subject: [PATCH 3/9] fix paths --- src/init.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.jl b/src/init.jl index 59b7d90..c5e5809 100644 --- a/src/init.jl +++ b/src/init.jl @@ -49,7 +49,7 @@ function __init__() elseif Sys.isapple() global libwstp = joinpath(wstp_dir, "wstp.framework", "wstp") elseif Sys.isunix() - global libwstp = joinpath(wstp_dir, "CompilerAdditions", "libWSTP$(Sys.WORD_SIZE)i4.so") + global libwstp = joinpath(wstp_dir, "libWSTP$(Sys.WORD_SIZE)i4.so") end @info "WSTP installation found" wstp_dir libwstp From 23461ee99933cd9b1963ac90abc8a0c969d9eaf2 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:27:59 -0700 Subject: [PATCH 4/9] fix path --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f50ec8b..f45cd57 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -21,7 +21,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: - WOLFRAM_APP_DIRECTORY: '${{ runner.temp }}\${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' + WOLFRAM_APP_DIRECTORY: '${{ runner.temp }}/${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: From 580b3deeeb7aa1a1b589be9df574cbdc8f0115fd Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:35:24 -0700 Subject: [PATCH 5/9] more fixes --- .github/workflows/CI.yml | 4 ++-- README.md | 42 +++------------------------------------- src/init.jl | 2 +- 3 files changed, 6 insertions(+), 42 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f45cd57..0ba582c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,8 +20,6 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - env: - WOLFRAM_APP_DIRECTORY: '${{ runner.temp }}/${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: @@ -47,6 +45,8 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + env: + RUST_BACKTRACE: 1 - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: diff --git a/README.md b/README.md index 4788d90..01e08c0 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ This package provides access to Mathematica/Wolfram Engine via the MathLink libr ## Installation -The package requires an installation of either [Mathematica](http://www.wolfram.com/mathematica/) or the free [Wolfram Engine](https://www.wolfram.com/engine/). It will attempt to find the installation at build time; if this fails, please see the [installation troubleshoot](#installation-troubleshoot) below. - - +The package requires an installation of either [Mathematica](http://www.wolfram.com/mathematica/) or the free [Wolfram Engine](https://www.wolfram.com/engine/). It will attempt to find the installation at load time using [wolfram-app-discovery](https://github.com/WolframResearch/wolfram-app-discovery-rs). A precise location can be specied by setting the `WOLFRAM_APP_DIRECTORY` environment variable. + + ## Usage The main interface consists of the `W""` string macro for specifying symbols. These are call-overloaded for building more complicated expressions. @@ -166,42 +166,6 @@ julia> W2Mstr(W`b/(c^(a+c))`) Printing in Jupyter notebooks is, by default, done in latex. This can be turned off with the command `MathLink.set_texOutput(false)` -## Installation Troubleshoot -The package requires an installation of either [Mathematica](http://www.wolfram.com/mathematica/) or the free [Wolfram Engine](https://www.wolfram.com/engine/). It will attempt to find the installation at build time; if this fails, you will need to set the following environment variables: -- `JULIA_MATHKERNEL`: the path of the MathKernel executable -- `JULIA_MATHLINK`: the path of the MathLink dynamic library named - - `libML64i4.so`/ `libML32i4.so` on Linux - - `ml64i4.dll`/`ml32i4.dll`/`libML64.dll`/ `libML32.dll` on Windows - -After setting, you may need to manually build the package -```julia -(@v1.X) pkg> build MathLink -``` - -A separate workaround is to directly edit the deps/deps.jl file, which should be located (on Linux) at `~/.julia/packages/MathLink//deps/deps.jl` - -The contents of `deps.jl` could for instance, read -```julia -const mlib = "/usr/local/Wolfram/Mathematica/11.3/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/libML64i4" -const mker = "WolframKernel" -``` -After creating the file `deps.jl` try loading MathLink the usual way -```julia -(@v1.X) pkg> using MathLink -``` -If you do not have a Mathematica installation at all, the above trick still works, but then you must leave the path blank -```julia -const mlib = "" -const mker = "WolframKernel" -``` -Loading `MathLink` then proclaims -```julia -julia> using MathLink -[ Info: Precompiling MathLink [18c93696-a329-5786-9845-8443133fa0b4] -[ Info: Pretending fake installation works -``` - - ## Notes - Mathematica, Wolfram, MathLink are all trademarks of Wolfram Research. diff --git a/src/init.jl b/src/init.jl index c5e5809..fe40e24 100644 --- a/src/init.jl +++ b/src/init.jl @@ -45,7 +45,7 @@ function __init__() wstp_dir = String(take!(out)) if Sys.iswindows() - global libwstp = joinpath(wstp_dir, "wstp$(Sys.WORD_SIZE)i4.dll") + global libwstp = joinpath(wstp_dir, "..", "SystemAdditions", "wstp$(Sys.WORD_SIZE)i4.dll") elseif Sys.isapple() global libwstp = joinpath(wstp_dir, "wstp.framework", "wstp") elseif Sys.isunix() From 087f8518d403e203dfe4c7488a915e77516c1857 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 21:50:23 -0700 Subject: [PATCH 6/9] full Mac stacktrace --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0ba582c..53fe8a2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -46,7 +46,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: - RUST_BACKTRACE: 1 + RUST_BACKTRACE: full - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: From 2cdd24c0da99625cb451e3d59e9770e71f8a8a0b Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 22:04:15 -0700 Subject: [PATCH 7/9] run with JULIA_DEBUG --- .github/workflows/CI.yml | 5 +++++ src/init.jl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 53fe8a2..1c259c4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,6 +20,8 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + env: + JULIA_DEBUG: MathLink - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: @@ -46,6 +48,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: + JULIA_DEBUG: MathLink RUST_BACKTRACE: full - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 @@ -105,6 +108,8 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + env: + JULIA_DEBUG: MathLink - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: diff --git a/src/init.jl b/src/init.jl index fe40e24..3a0af75 100644 --- a/src/init.jl +++ b/src/init.jl @@ -52,7 +52,7 @@ function __init__() global libwstp = joinpath(wstp_dir, "libWSTP$(Sys.WORD_SIZE)i4.so") end - @info "WSTP installation found" wstp_dir libwstp + @debug "WSTP installation found" wstp_dir libwstp if libwstp != "" # WSENV WSInitialize(WSEnvironmentParameter p) From 9874a01b73570fbf11e9d8135931f26349ff9bb1 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 22:20:48 -0700 Subject: [PATCH 8/9] .github/workflows/CI.yml --- .github/workflows/CI.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1c259c4..30f8194 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -42,10 +42,12 @@ jobs: echo 'Installing Wolfram Engine...' brew install --cask wolfram-engine echo 'Installed Wolfram Engine.' - + - uses: julia-actions/setup-julia@v1 - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 + - run: mdfind "kMDItemCFBundleIdentifier == 'com.wolfram.*'" + - run: julia --project -e 'using WolframAppDiscovery_jll; run(`$(wolfram_app_discovery()) default`)' - uses: julia-actions/julia-runtest@v1 env: JULIA_DEBUG: MathLink @@ -110,6 +112,7 @@ jobs: - uses: julia-actions/julia-runtest@v1 env: JULIA_DEBUG: MathLink + WOLFRAM_APP_DIRECTORY: '${{ runner.temp }}\${{ env.WOLFRAMENGINE_INSTALLATION_SUBDIRECTORY }}' - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: From 4df0075880bcdf84c3eb38e003c491f1295e29fc Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2023 22:29:38 -0700 Subject: [PATCH 9/9] show info --- .github/workflows/CI.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 30f8194..888d39c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -47,6 +47,7 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - run: mdfind "kMDItemCFBundleIdentifier == 'com.wolfram.*'" + - run: mdls "/Applications/Wolfram Engine.app" - run: julia --project -e 'using WolframAppDiscovery_jll; run(`$(wolfram_app_discovery()) default`)' - uses: julia-actions/julia-runtest@v1 env: