If you are trying different julia versions, you need to move the folder where sys.dll ends up in so it does it brand new.
Every deps.jl in any dependent package that has a built library, such as MbedTLS.jl or Rmath.jl or SpecialFunctions.jl all need to be modified to not use absolute paths on the harddrive to make deployment managable.
Change them from the generated code that came out of BinaryDependancy.jl
libxxxxx = joinpath(currentpath_for_deps, "usr","lib","libxxx.dll")
to
libxxxxx = "libxxx.dll"
Now you will need to copy dlls into the runpath or dll search path for each place you are planning on running from.
The package will get built into the root_modules but won't get listed properly. To enable proper listing as a baked in package, you can either look it up using the UUID at runtime with something like:
MyCustomPackage = Base.root_module(Base.PkgId(Base.UUID("abcdef0123-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), "MyCustomPackage"))
or you can spoof into the StdLibs. This feels more elegant for the end use of the function but is a little hacky up front.
You have to put in a fake StdLib folder for your module, with an empty src
folder, and make a simple project file.
A generic way to do that follows:
function make_package_placeholder_in_stdlib(pkg_name)
stdlib_path = joinpath(dirname(Base.julia_cmd().exec[1]), "..", "share", "julia", "stdlib", "v"*string(VERSION)[1:3])
# make the destination folder structure
new_dir = joinpath(stdlib_path, pkg_name, "src")
@show new_dir
mkpath(new_dir)
@assert isdir(new_dir)
# write an empty MyPackage.jl file under src
open(io->write(io, ""), joinpath(stdlib_path, pkg_name, "src", pkg_name * ".jl"), "w")
# write a TOML file with just the package name and the uuid
pkg_uuid = try
# string(Base.module_keys[findfirst(x-> x.name == pkg_name, Base.module_keys)].uuid)
Pkg.TOML.parsefile(joinpath(Pkg.API.dir(pkg_name),"Project.toml"))["uuid"]
catch e
@show findfirst(x-> x.name == pkg_name, Base.module_keys)
error("Failed to find $pkg_name 's uuid in its Project.toml")
end
stdlib_project_toml_file = joinpath(stdlib_path, pkg_name, "Project.toml")
# open(io->Pkg.TOML.print(io, Dict("name"=>pkg_name, "uuid"=>pkg_uuid)), stdlib_project_toml_file, "w")
open(stdlib_project_toml_file, "w") do io
Pkg.TOML.print(io, Dict("name"=>pkg_name, "uuid"=>pkg_uuid))
end
@show stdlib_project_toml_file
@assert isfile(stdlib_project_toml_file)
end
BUT using this function will gimp julia/loading.jl later. So when you are done compiling, you should clean up and remove this spoofed folder.
You can now build a custom julia sys library using
PackageCompiler.compile_package("MyCustomPackage"; force = false, reuse = false, cpu_target = "x86-64")
If you fail to remove the spoofed folder in StdLib
you end up with the following error when using Pkg.test
(MyCustomPackage) pkg> test MyCustomPackage
Testing MyCustomPackage
Resolving package versions...
WARNING: --output requested, but no modules defined during run
┌ Warning: The call to compilecache failed to create a usable precompiled cache file for MyCustomPackage [abcdef0123-xxxx-xxxx-xxxx-xxxxxxxxxxxx]
│ exception = ArgumentError: Invalid header in cache file /Users/username/.julia/compiled/v1.0/MyCustomPackage/xGNPz.ji.
└ @ Base loading.jl:969
ERROR: LoadError: KeyError: key MyCustomPackage [abcdef0123-xxxx-xxxx-xxxx-xxxxxxxxxxxx] not found
Stacktrace:
[1] getindex at ./dict.jl:478 [inlined]
[2] root_module at ./loading.jl:898 [inlined]
[3] require(::Base.PkgId) at ./loading.jl:864
[4] require(::Module, ::Symbol) at ./loading.jl:853
[5] include at ./boot.jl:317 [inlined]
[6] include_relative(::Module, ::String) at ./loading.jl:1044
[7] include(::Module, ::String) at ./sysimg.jl:29
[8] include(::String) at ./client.jl:392
[9] top-level scope at none:0
in expression starting at /Users/username/development/packages/MyCustomPackage/test/runtests.jl:5
ERROR: Package MyCustomPackage errored during testing