# Will juliac solve the relocatabiliy issue?

**URL:** <https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780>\
**Category:** General Usage\
**Tags:** question\
**Created:** [August 22, 2025, 7:35pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780 "2025-08-22T19:35:14Z")\
**Posts on this page:** 17\
**Page:** 2

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 23, 2025, 2:47pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/21 "2025-08-23T14:47:52Z")

</div>

In the case of Oxygen.jl the use of `@ __DIR__ ` here is very suspect.

> <https://github.com/OxygenFramework/Oxygen.jl/blob/84eb8971d6554466de0b0fbddf6c32867497b001/src/constants.jl#L12-L17>

The other thing that makes this hard is that the builder paths could just be used to print debug messages, and not actually accessed. I think that is what is going on in GLMakie with this `name` `ShaderSource` field (but hard to tell for sure)

> <https://github.com/MakieOrg/Makie.jl/blob/687c4466ce00154714297e36a7f610443c6ad5be/GLMakie/src/GLMakie.jl#L50>

I found these by searching for `@ __DIR__ ` and `@path` because these seem to be very easy macros to misuse.

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [August 23, 2025, 3:19pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/22 "2025-08-23T15:19:58Z")

</div>

Yes, there is an open issue

> <https://github.com/OxygenFramework/Oxygen.jl/issues/259#issuecomment-3216679951>
>
> I have created an App using Oxygen (using \`PackageCompiler\`) and have put it int…o a Docker image (a multi-stage build where I only copied the contents of the App folder to the final image).
> 
> The app per se works fine, I can call my get and post endpoints.
> However, when I go to \`127.0.0.1:8980/docs\`, the container throws an error
> 
> \`\`\`
> SystemError: opening file "/home/jl/.julia/packages/Oxygen/jV71k/data/swagger@5.7.2/swagger-ui-bundle.js": No such file or directory
> \`\`\`
> 
> Since the \`.julia/packages\` directory no longer exists, this is no big surprise.
> The same problem occurs if I copy the app and move it to another computer without a Julia installation.
> 
> I don't quite understand why this is the case since you are using \`RelocatableFolders\`; somehow the scratch space is not generated?
> 
> Julia: Version 1.11.3
> Oxygen: Version 1.7.1
> 
> \`\`\`
> \[ Info: Listening on: 0.0.0.0:8980, thread id: 1
> ┌ Error: handle\_connection handler error. 
> │ 
> │ ===========================
> │ HTTP Error message:
> │ 
> │ ERROR: TaskFailedException
> │ Stacktrace:
> │ \[1\] wait(?::Task)
> │ @ Base ./task.jl:370
> │ \[2\] (::Oxygen.Core.var"#18#21"{Oxygen.Core.var"#16#17"{Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String}}})(?::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}})
> │ @ Oxygen.Core ~/.julia/packages/Oxygen/jV71k/src/core.jl:289
> │ \[3\] #invokelatest#2
> │ @ ./essentials.jl:1055 \[inlined\]
> │ \[4\] invokelatest
> │ @ ./essentials.jl:1052 \[inlined\]
> │ \[5\] handle\_connection(?::Function, ?::HTTP.Connections.Connection{Sockets.TCPSocket}, ?::HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, ?::Int64, ?::Function, ?::Bool)
> │ @ HTTP.Servers ~/.julia/packages/HTTP/MIUdD/src/Servers.jl:469
> │ \[6\] (::HTTP.Servers.var"#16#17"{Oxygen.Core.var"#18#21"{Oxygen.Core.var"#16#17"{Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String}}}, HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, Set{HTTP.Connections.Connection}, Int64, Oxygen.Core.var"#26#27", ReentrantLock, Bool, Base.Semaphore, HTTP.Connections.Connection{Sockets.TCPSocket}})()
> │ @ HTTP.Servers ~/.julia/packages/HTTP/MIUdD/src/Servers.jl:401
> │ 
> │ nested task error: TaskFailedException
> │ Stacktrace:
> │ \[1\] wait(?::Task)
> │ @ Base ./task.jl:370
> │ \[2\] (::Oxygen.Core.var"#19#22"{HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}, Oxygen.Core.var"#16#17"{Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String}}})()
> │ @ Oxygen.Core ~/.julia/packages/Oxygen/jV71k/src/core.jl:287
> │     
> │ nested task error: SystemError: opening file "/home/jl/.julia/packages/Oxygen/jV71k/data/swagger@5.7.2/swagger-ui-bundle.js": No such file or directory
> │ Stacktrace:
> │ \[1\] systemerror(?::String, ?::Int32; ?::Nothing)
> │ @ Base ./error.jl:176
> │ \[2\] systemerror
> │ @ ./error.jl:175 \[inlined\]
> │ \[3\] open(?::String; ?::Bool, ?::Nothing, ?::Nothing, ?::Nothing, ?::Nothing, ?::Nothing)
> │ @ Base ./iostream.jl:295
> │ \[4\] open
> │ @ ./iostream.jl:277 \[inlined\]
> │ \[5\] open(?::Base.var"#472#473"{String}, ?::String; ?::@Kwargs{})
> │ @ Base ./io.jl:408
> │ \[6\] swaggerhtml(?::String, ?::String)
> │ @ Oxygen.Core.AutoDoc ./\<missing\>:0
> │ \[7\] (::Oxygen.Core.var"#65#67"{Oxygen.Core.var"#69#73"{String, String}, Oxygen.Core.Handlers.var"#26#28"{Oxygen.Core.Handlers.var"#26#27#29"{Oxygen.Core.Handlers.var"#4#16"}}})(?::HTTP.Messages.Request)
> │ @ Oxygen.Core ./\<missing\>:0
> │ \[8\] (::HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing})(?::HTTP.Messages.Request)
> │ @ HTTP.Handlers ~/.julia/packages/HTTP/MIUdD/src/Handlers.jl:439
> │ \[9\] (::Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String})(?::HTTP.Messages.Request)
> │ @ Oxygen.Core ~/.julia/packages/Oxygen/jV71k/src/core.jl:397
> │ \[10\] #13
> │ @ ~/.julia/packages/Oxygen/jV71k/src/core.jl:255 \[inlined\]
> │ \[11\] (::HTTP.Handlers.var"#1#2"{Oxygen.Core.var"#13#15"{Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String}, Sockets.IPv4, HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}}})(?::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}})
> │ @ HTTP.Handlers ~/.julia/packages/HTTP/MIUdD/src/Handlers.jl:58
> │ \[12\] #16
> │ @ ~/.julia/packages/Oxygen/jV71k/src/core.jl:272 \[inlined\]
> │ \[13\] (::Oxygen.Core.var"#20#23"{HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}, Oxygen.Core.var"#16#17"{Oxygen.Core.var"#30#32"{Oxygen.Core.var"#35#38"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, Bool, Bool}, HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}, String}}})()
> │ @ Oxygen.Core ~/.julia/packages/Oxygen/jV71k/src/core.jl:286
> │ request =
> │ HTTP.Messages.Request:
> │ """
> │ GET /docs HTTP/1.1
> │ Host: 127.0.0.1:8980
> │ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0
> │ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,\*/\*;q=0.8
> │ Accept-Language: de,en-US;q=0.7,en;q=0.3
> │ Accept-Encoding: gzip, deflate, br, zstd
> │ Connection: keep-alive
> │ Upgrade-Insecure-Requests: 1
> │ Sec-Fetch-Dest: document
> │ Sec-Fetch-Mode: navigate
> │ Sec-Fetch-Site: none
> │ Sec-Fetch-User: ?1
> │ Priority: u=0, i
> │    
> │ """
> └ @ HTTP.Servers ~/.julia/packages/HTTP/MIUdD/src/Servers.jl:483
> \[ Info: 2025-04-15T15:01:40+0000 - 172.17.0.1:35380 - "GET /docs HTTP/1.1" 500
> \`\`\`

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 23, 2025, 4:43pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/23 "2025-08-23T16:43:43Z")

</div>

I think it would be cool to have the Julia equivalent of

> **[SDL3/CategoryStorage](https://wiki.libsdl.org/SDL3/CategoryStorage)**
>
> The Simple Directmedia Layer Wiki

Basically a very restrictive api that forces the code to explicitly answer what, how, and when user data or app data should be accessed, to make these issues really hard to run into.

One issue with `@path` from RelocatableFolders.jl is that it tries to hide things behind a macro that have to be explicitly decided on by the developer for things to work well.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [August 23, 2025, 6:07pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/24 "2025-08-23T18:07:25Z")

</div>

> [@nhz2](#):
>
> found these by searching for `@ __DIR__ ` and `@path` because these seem to be very easy macros to misuse.

Also `pathof` and `pkgdir`.

These being available as API in the first place is perhaps the root of the problem here. Probably someone should make a doc PR to discourage their use outside debugging and perhaps deprecate them.

EDIT: found relevant discussion, see PRs linked here:

> <https://github.com/JuliaLang/julia/issues/54430>
>
> ~The proposed use I have for this is for when packages are looking for their Art…ifacts.toml file, they have to annoying things, and non relocatable ones even more annyoingly. (Maybe we need to add something like \`@\_\_PKGDIR\` that does the relocatable thing)~
> 
> Currently \`@\_\_DIR\_\_\` bakes in the current path of the whenever it's called, but for this it's usually the path of the \`src\` directory of a package. Examples of this are the \`Artifacts.toml\` file or a \`examples/\`directory, The issue arises if one tries to move that package to another place, either via PkgCompiler or via copying the depot around. Those baked in absolute paths mean that it's not safe for this package to be relocatable.
> 
> I don't have a clear proposal for this, but I imagine it would just be a expansion of the relocatable package image work done by @fatteneder, specially since if you get the package those files are already there, we just don't have a nice way of getting to them.

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [August 23, 2025, 6:36pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/25 "2025-08-23T18:36:03Z")

</div>

There is a `Base.isrelocatable(pkg)` 🤯

> <https://github.com/JuliaLang/julia/blob/fc1fb4139e71ee57e90263769a8fef510353f11c/base/loading.jl#L1911>

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 23, 2025, 8:40pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/26 "2025-08-23T20:40:14Z")

</div>

Maybe there is a flaw in this test, but `pkgdir` seems to relocate as expected.

```sh
$ rm -rf /tmp/testpkgdir
$ JULIA_DEPOT_PATH="/tmp/testpkgdir/foo:" julia -e 'using Pkg; Pkg.add("Example")'
  Installing known registries into `/tmp/testpkgdir/foo`
       Added `General` registry to /tmp/testpkgdir/foo/registries
    Updating registry at `/tmp/testpkgdir/foo/registries/General.toml`
   Resolving package versions...
   Installed Example ─ v0.5.5
    Updating `/tmp/testpkgdir/foo/environments/v1.11/Project.toml`
  [7876af07] + Example v0.5.5
    Updating `/tmp/testpkgdir/foo/environments/v1.11/Manifest.toml`
  [7876af07] + Example v0.5.5
Precompiling project...
  1 dependency successfully precompiled in 0 seconds
$ JULIA_DEPOT_PATH="/tmp/testpkgdir/foo:" julia -e 'using Example; println(pkgdir(Example))'
/tmp/testpkgdir/foo/packages/Example/SUIr0
$ mv /tmp/testpkgdir/foo /tmp/testpkgdir/bar
$ JULIA_DEPOT_PATH="/tmp/testpkgdir/bar:" julia -e 'using Example; println(pkgdir(Example))'
/tmp/testpkgdir/bar/packages/Example/SUIr0

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 23, 2025, 9:50pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/27 "2025-08-23T21:50:01Z")

</div>

> [@ohmsweetohm1](#):
>
> Base.isrelocatable(pkg)

I think that’s just for making precompile caches relocatable at all, which could potentially let us install precompile caches and seems relevant to executables and libraries as well. It still can’t catch a program trying to read from a bad path, install missing dependencies, or do other undesirable behaviors at runtime.

[Julia 1.11 Highlights - Precompile file relocatability](https://julialang.org/blog/2024/10/julia-1.11-highlights/#precompile_file_relocatability)

[PSA: Cache relocation with Julia v1.11 - HackMD](https://hackmd.io/@Je8OcLYBQr2ociLAtslIug/BJvv7G9pa)

[Make precompile files relocatable/servable · Issue #47943 · JuliaLang/julia](https://github.com/JuliaLang/julia/issues/47943)

> [@ohmsweetohm1](#):
>
> Could this new tracing stuff for `--trim` be used to check if a path to the host machine is used ever again and warn?

There could be some static checks, but again, that only goes so far against bad practices. I have no idea how feasible it is, but let’s say we do have a (pre)compiler that identifies every instantiated file path tied to the host machine and warns if we ever use them via the end-product’s methods (we’d have to omit methods that only serve their purpose during precompilation). I release a product that passed that check, but you notice that it doesn’t work on your machine, or worse it fails sometimes for no clear reason. Turns out that while all the precompile-instantiated paths were relocatable, one of them had a file that stored _other_ paths that would only be instantiated at runtime or be used to generate new paths at runtime, possibly only on some runs. I failed to make _those_ relocatable, and a compiler can’t catch runtime paths it can’t be aware of. At some point, good tooling and instructions should be discoverable, and people need to opt in. Just last week, I ran into a prototype package that required end-users to separately install a shared library and store its path to an environment variable (which might be isolated to a shell session), then it searched that path in the global scope instead of ` __init__ `, which usually forces the use of `dev` instead of `add`; obviously not ideal, but making users separately install things and tweak settings isn’t that rare of a practice generally, and it needs to be deliberately improved or avoided.

It’s also worth keeping in mind that manually written paths are not the whole story for relocatability. The precompile cache relocatability improvements involved precompilation-generated paths, which _can_ be statically checked but isn’t something we were involved in or can control. Memory addresses need to be handled at runtime to not get stuck at a state only suitable for the host machine at precompile-time. The package could be getting data from URLs that are blocked on some networks. There might be more things that I’m just not aware of.

> [@nhz2](#):
>
> I found these by searching for `@ __DIR__ ` and `@path` because these seem to be very easy macros to misuse.

So `RelocatableFolders.@path` falling back to a scratchspace at runtime isn’t the straightforward solution?

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 23, 2025, 10:39pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/28 "2025-08-23T22:39:09Z")

</div>

I find baking in the data with the `read` function more straightforward:

> <https://github.com/ASML-Labs/PPTX.jl/blob/acc2cf70f7db4c13cbcfaa89ff1a581a8e87d328/src/constants.jl#L15-L16>

`@path` if I understand it correctly also bakes in the file data, and then when converted to a `String` writes the files somewhere to get a `String` path. This seems like a worse version of [Artifacts](https://pkgdocs.julialang.org/v1/artifacts/)

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 24, 2025, 6:13pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/29 "2025-08-24T18:13:09Z")

</div>

I created this script to check for relocation issues: [Julia Package Relocatability Test Script · GitHub](https://gist.github.com/nhz2/fef85cf22bef076348e921f5c46be2d3)

When I run it on normal packages like `julia reloc-helper.jl JSON` everything works.

When run on `julia reloc-helper.jl Oxygen` or `julia reloc-helper.jl GLMakie` it shows a stacktrace with the relocation issue:

```julia-auto
     Testing Running tests...
ERROR: LoadError: SystemError: opening file "/tmp/jl_29ZxGi/build/dev/Oxygen/src/methods.jl": No such file or directory
Stacktrace:
 [1] include(mod::Module, _path::String)
   @ Base ./Base.jl:562
 [2] include(x::String)
   @ Main.RunTests.TimeZoneTests /tmp/jl_29ZxGi/host/dev/Oxygen/test/extensions/timezonetests.jl:1
 [3] top-level scope
   @ /tmp/jl_29ZxGi/build/dev/Oxygen/src/Oxygen.jl:32
 [4] include(mod::Module, _path::String)
   @ Base ./Base.jl:562
 [5] include(x::String)
   @ Main.RunTests /tmp/jl_29ZxGi/host/dev/Oxygen/test/runtests.jl:1
 [6] top-level scope
   @ /tmp/jl_29ZxGi/host/dev/Oxygen/test/runtests.jl:8
 [7] include(fname::String)
   @ Main ./sysimg.jl:38
 [8] top-level scope
   @ none:6
in expression starting at /tmp/jl_29ZxGi/host/dev/Oxygen/test/extensions/timezonetests.jl:1
in expression starting at /tmp/jl_29ZxGi/host/dev/Oxygen/test/runtests.jl:1

```

```julia-auto
shader cache: Error During Test at /tmp/jl_qTURTz/host/dev/Makie/GLMakie/test/unit_tests.jl:9
  Got exception outside of a @test
  SystemError: opening file "/tmp/jl_qTURTz/build/dev/Makie/GLMakie/assets/shader/postprocessing/fullscreen.vert": No such file or directory
  Stacktrace:
    [1] systemerror(p::String, errno::Int32; extrainfo::Nothing)
      @ Base ./error.jl:176
    [2] systemerror
      @ ./error.jl:175 [inlined]
    [3] open(fname::String; lock::Bool, read::Nothing, write::Nothing, create::Nothing, truncate::Nothing, append::Nothing)
      @ Base ./iostream.jl:295
    [4] open
      @ ./iostream.jl:277 [inlined]
    [5] #open#465
      @ ./io.jl:408
    [6] open
      @ ./io.jl:407 [inlined]
    [7] read
      @ ./io.jl:507 [inlined]
    [8] ShaderSource
      @ /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/GLMakie.jl:55 [inlined]
    [9] (::GLMakie.var"#1#2"{String})()
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/GLMakie.jl:69
   [10] get!(default::GLMakie.var"#1#2"{String}, h::Dict{String, GLMakie.ShaderSource}, key::String)
      @ Base ./dict.jl:458
   [11] loadshader
      @ /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/GLMakie.jl:65 [inlined]
   [12] to_screen_postprocessor(framebuffer::GLMakie.GLFramebuffer, shader_cache::GLMakie.GLAbstraction.ShaderCache, screen_fb_id::Nothing)
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/postprocessing.jl:285
   [13] to_screen_postprocessor
      @ /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/postprocessing.jl:285 [inlined]
   [14] empty_screen(debugging::Bool, reuse::Bool, window::Nothing)
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/screen.jl:314
   [15] empty_screen(debugging::Bool; reuse::Bool, window::Nothing)
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/screen.jl:258
   [16] screen_from_pool(debugging::Bool; window::Nothing)
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/screen.jl:375
   [17] screen_from_pool
      @ /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/screen.jl:363 [inlined]
   [18] GLMakie.Screen(; resolution::Nothing, start_renderloop::Bool, window::Nothing, screen_config::@Kwargs{visible::Bool})
      @ GLMakie /tmp/jl_qTURTz/build/dev/Makie/GLMakie/src/screen.jl:462
   [19] macro expansion
      @ /tmp/jl_qTURTz/host/dev/Makie/GLMakie/test/unit_tests.jl:11 [inlined]
   [20] macro expansion
      @ ~/.julia/juliaup/julia-1.11.6+0.x64.linux.gnu/share/julia/stdlib/v1.11/Test/src/Test.jl:1709 [inlined]
   [21] top-level scope
      @ /tmp/jl_qTURTz/host/dev/Makie/GLMakie/test/unit_tests.jl:10
   [22] include(fname::String)
      @ Main ./sysimg.jl:38
   [23] macro expansion
      @ /tmp/jl_qTURTz/host/dev/Makie/GLMakie/test/runtests.jl:36 [inlined]
   [24] macro expansion
      @ ~/.julia/juliaup/julia-1.11.6+0.x64.linux.gnu/share/julia/stdlib/v1.11/Test/src/Test.jl:1709 [inlined]
   [25] top-level scope
      @ /tmp/jl_qTURTz/host/dev/Makie/GLMakie/test/runtests.jl:24
   [26] include(fname::String)
      @ Main ./sysimg.jl:38
   [27] top-level scope
      @ none:6

```

I used it to [fix MeshCat.jl](https://github.com/rdeits/MeshCat.jl/pull/265)

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 24, 2025, 7:31pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/30 "2025-08-24T19:31:30Z")

</div>

[Make sure that the paths are Path objects by ValentinKaisermayer · Pull Request #267 · OxygenFramework/Oxygen.jl · GitHub](https://github.com/OxygenFramework/Oxygen.jl/pull/267) fixes that Oxygen error. The next Oxygen error seems to be coming from Bonito.jl or WGLMakie.jl

> **Full error**
>
> ```julia-auto
> WGLMakie Utils tests: Error During Test at /tmp/jl_PG0swv/host/dev/Oxygen/test/extensions/wglmakietests.jl:10
> Got exception outside of a @test
> File not found: /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/js_dependencies/Bonito.bundled.js
> Stacktrace:
> [1] error(s::String)
> @ Base ./error.jl:35
> [2] #to_data_url#98
> @ /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/asset-serving/asset.jl:212 [inlined]
> [3] to_data_url(file_path::String)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/asset-serving/asset.jl:211
> [4] url(::Bonito.NoServer, asset::Bonito.Asset)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/asset-serving/no-server.jl:48
> [5] url(session::Bonito.Session{Bonito.NoConnection}, asset::Bonito.Asset)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/asset-serving/asset.jl:37
> [6] (::Bonito.var"#63#64"{Bool, Bool, String, Bonito.Session{Bonito.NoConnection}})()
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/session.jl:488
> [7] lock(f::Bonito.var"#63#64"{Bool, Bool, String, Bonito.Session{Bonito.NoConnection}}, l::ReentrantLock)
> @ Base ./lock.jl:232
> [8] #session_dom#62
> @ /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/session.jl:443 [inlined]
> [9] session_dom
> @ /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/session.jl:442 [inlined]
> [10] session_dom(session::Bonito.Session{Bonito.NoConnection}, app::Bonito.App; init::Bool, html_document::Bool)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/session.jl:363
> [11] session_dom(session::Bonito.Session{Bonito.NoConnection}, app::Bonito.App)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/session.jl:361
> [12] show_html(io::IOBuffer, app::Bonito.App; parent::Nothing)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/display.jl:78
> [13] show_html(io::IOBuffer, app::Bonito.App)
> @ Bonito /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/display.jl:63
> [14] show
> @ /tmp/jl_PG0swv/build/packages/Bonito/Xtz2t/src/display.jl:97 [inlined]
> [15] backend_show(screen::WGLMakie.Screen, io::IOBuffer, m::MIME{Symbol("text/html")}, scene::Makie.Scene)
> @ WGLMakie /tmp/jl_PG0swv/build/packages/WGLMakie/LOBCu/src/display.jl:205
> [16] show(io::IOBuffer, m::MIME{Symbol("text/html")}, figlike::Makie.FigureAxisPlot; backend::Module, update::Bool)
> @ Makie /tmp/jl_PG0swv/build/packages/Makie/FUAHr/src/display.jl:258
> [17] show
> @ /tmp/jl_PG0swv/build/packages/Makie/FUAHr/src/display.jl:247 [inlined]
> [18] response(content::Makie.FigureAxisPlot, mime_type::MIME{Symbol("text/html")}, status::Int64, headers::Vector{Any})
> @ WGLMakieExt /tmp/jl_PG0swv/build/dev/Oxygen/ext/WGLMakieExt.jl:21
> [19] html
> @ /tmp/jl_PG0swv/build/dev/Oxygen/ext/WGLMakieExt.jl:37 [inlined]
> [20] html(fig::Makie.FigureAxisPlot)
> @ WGLMakieExt /tmp/jl_PG0swv/build/dev/Oxygen/ext/WGLMakieExt.jl:37
> [21] macro expansion
> @ /tmp/jl_PG0swv/host/dev/Oxygen/test/extensions/wglmakietests.jl:14 [inlined]
> [22] macro expansion
> @ ~/.julia/juliaup/julia-1.11.6+0.x64.linux.gnu/share/julia/stdlib/v1.11/Test/src/Test.jl:1709 [inlined]
> [23] top-level scope
> @ /tmp/jl_PG0swv/host/dev/Oxygen/test/extensions/wglmakietests.jl:12
> [24] include(mod::Module, _path::String)
> @ Base ./Base.jl:562
> [25] include(x::String)
> @ Main.RunTests /tmp/jl_PG0swv/host/dev/Oxygen/test/runtests.jl:1
> [26] top-level scope
> @ /tmp/jl_PG0swv/host/dev/Oxygen/test/runtests.jl:12
> [27] include(fname::String)
> @ Main ./sysimg.jl:38
> [28] top-level scope
> @ none:6
> Test Summary: | Error Total Time
> WGLMakie Utils tests | 1 1 1.5s
> ERROR: LoadError: Some tests did not pass: 0 passed, 0 failed, 1 errored, 0 broken.
> in expression starting at /tmp/jl_PG0swv/host/dev/Oxygen/test/extensions/wglmakietests.jl:1
> in expression starting at /tmp/jl_PG0swv/host/dev/Oxygen/test/runtests.jl:1
> 
> ```

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [August 25, 2025, 11:06am UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/31 "2025-08-25T11:06:01Z")

</div>

> [@nhz2](#):
>
> I created this script to check for relocation issues: [Julia Package Relocatability Test Script · GitHub](https://gist.github.com/nhz2/fef85cf22bef076348e921f5c46be2d3)

Very cool work! 👍  
It would be nice if this was a package, and maybe a Github workflow such that a badge can be produced.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [August 25, 2025, 11:18am UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/32 "2025-08-25T11:18:54Z")

</div>

I want to clarify a few things about the current status of relocability.

As already mentioned in other posts, there are essentially two cases we distinguish:

1. Paths used with `include(..)/include_dependency()`.
2. Hardcoded strings, including uses of `@ __DIR__ ` and friends.

The first one is taken care of as of 1.11.  
As long as a user compiles a pkg into a writeable depot (first in `DEPOT_PATH`) it should work.  
Use `JULIA_DEBUG=loading` to debug re-compilation _and_ loading issues.

There are also two proposals to solve 2., but the discussion around this stalled.  
These solutions introduce a new macro that pkg authors need to opt-in for relocatability.

It might be possible to do away with (many cases of) hardcoded strings (global or function level)  
using a search-replace strategy. But I haven’t looked into this yet and it might come with load-time regressions.  
However, as Benny mentioned, people are allowed to do weird things with strings.  
So it seems reasonable to expect from pkg authors to do some thinking when writing pkg code that should be relocatable.  
The current issue is that we lack a solution for 2, which could either be a `@RELOCDIR` macro or a potential `Path` type.

What I haven’t touched is relocation issues in third-party libraries, e.g. hardcoded paths in a C lib.  
I hope these are more rare.

About `Base.isrelocatable`: Right now this only checks if a pkg is relocatable _after_ compliation is done,  
e.g. it checks if all `include()` paths could be resolved to a depot.  
It was added as some pkgs like to tinker with `DEPOT_PATH` mid compilation, which you shouldn’t do …

PS: I like the relocatability test script.

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 25, 2025, 3:48pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/33 "2025-08-25T15:48:25Z")

</div>

Thank you for all the work you’ve done in Julia to get precompilation relocatable.

Does calling `pkgdir` at runtime work as another alternative to `@ __DIR__ `? I don’t see how the two proposals would be better than that. For example, even though MeshCat.jl was using artifacts, I had to change:

```julia-auto
const VIEWER_ROOT = joinpath(first(readdir(artifact"meshcat", join=true)), "dist")

```

to

```julia-auto
VIEWER_ROOT() = joinpath(first(readdir(artifact"meshcat", join=true)), "dist")

```

If the data was in the repo, would something like:

```julia-auto
VIEWER_ROOT() = joinpath(pkgdir(@ __MODULE__ ), "dist")

```

have worked?

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [August 25, 2025, 4:20pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/34 "2025-08-25T16:20:09Z")

</div>

The const case doesn’t work, because the RHS will be expanded to an (absolute) path and this will be baked-into the pkgimage. This is case 2 from above.

I think the two function-based versions rely on the assumption that `VIEWER_ROOT()` will not be const-proped and evaluated during compilation, and thus, also expand to an absolute path. Not sure how likely it is that this will ever be optimized. Maybe the presence of `@ __MODULE__ ` even guards it from evaluation and makes it safer, not sure. Otherwise, it might be fine.

The, IMO, correct implementation uses a Base specific type, e.g. `RelocPath("/path/to/depot/sub/path/to/file")`. When we construct that object we replace the first part to read `@depot/sub/path/to/file` and then bake this string into the pkg image. That’s also how `include()` works, which I think is good.  
The current proposal comes with the overhead, that we have to patch the `"@depot"` every time we convert the type to a string. But it might be possible to only do this once during loading.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [August 25, 2025, 4:37pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/35 "2025-08-25T16:37:26Z")

</div>

I think to avoid downloading deps you need these options for `create_app`:

> <https://github.com/MakieOrg/Makie.jl/blob/master/relocatability.jl#L70>

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [August 25, 2025, 5:28pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/36 "2025-08-25T17:28:12Z")

</div>

The artifact version of `VIEWER_ROOT()` can’t be const-proped because by calling the function `artifacts_dirs` [julia/stdlib/Artifacts/src/Artifacts.jl at 364ecb3a114fd2638df60654807474e7f38cb04e · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/364ecb3a114fd2638df60654807474e7f38cb04e/stdlib/Artifacts/src/Artifacts.jl#L60), its output depends on the runtime state of `Base.DEPOT_PATH`

Currently, it looks like `pkgdir` is safe from const-prop because it does a runtime lookup into `Base.pkgorigins` [julia/base/loading.jl at 364ecb3a114fd2638df60654807474e7f38cb04e · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/364ecb3a114fd2638df60654807474e7f38cb04e/base/loading.jl#L528), but it would be nice for this to be documented.

A proper path system would be nice instead of doing everything with strings, but I don’t think this is absolutely needed to get all the major packages relocatable, given all the existing tools we have.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 25, 2025, 7:09pm UTC](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780/37 "2025-08-25T19:09:06Z")

</div>

Could this be added as a on optional test to Aqua.jl ?

[Previous page](https://discourse.julialang.org/t/will-juliac-solve-the-relocatabiliy-issue/131780.md?page=1)
