Skip to content

JuliaC --trim compatibility #507

@langestefan

Description

@langestefan

TimeZones.jl is currently not compatible with JuliaC and the trim option.

MWE:

mwe_timezones.jl

module MWE

using TimeZones  # This is all it takes to trigger the crash

Base.@ccallable function hello()::Int32
    return Int32(42)
end

end

mwe_demo.c

#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <unistd.h>

typedef int (*hello_fn)(void);
static char lib_path[4096];

int main(void) {
    ssize_t len = readlink("/proc/self/exe", lib_path, sizeof(lib_path) - 1);
    lib_path[len] = '\0';
    char *s = strrchr(lib_path, '/');
    if (s) *(s + 1) = '\0';
    strcat(lib_path, "libmwe_timezones.so");

    void *h = dlopen(lib_path, RTLD_NOW | RTLD_GLOBAL);
    if (!h) { fprintf(stderr, "dlopen: %s\n", dlerror()); return 1; }

    hello_fn f = (hello_fn)dlsym(h, "hello");
    printf("hello() = %d\n", f());
    dlclose(h);
    return 0;
}

Build without trim, works fine

julia -e '
using JuliaC
img = ImageRecipe(output_type="--output-lib", file="mwe_timezones.jl",
                  trim_mode="no", add_ccallables=true, project=".")
link = LinkRecipe(image_recipe=img, outname="build_notrim/lib/libmwe_timezones")
bun = BundleRecipe(link_recipe=link, output_dir="build_notrim")
compile_products(img); link_products(link); bundle_products(bun)'

# Build and run C demo
gcc -o build_notrim/lib/mwe_demo mwe_demo.c -ldl
LD_LIBRARY_PATH=build_notrim/lib:build_notrim/lib/julia ./build_notrim/lib/mwe_demo
# Output: hello() = 42

Build with trim succeeds, running fails

julia -e '
using JuliaC
img = ImageRecipe(output_type="--output-lib", file="mwe_timezones.jl",
                  trim_mode="unsafe", add_ccallables=true, project=".")
link = LinkRecipe(image_recipe=img, outname="build_trim/lib/libmwe_timezones")
bun = BundleRecipe(link_recipe=link, output_dir="build_trim")
compile_products(img); link_products(link); bundle_products(bun)'

# Build and run C demo
gcc -o build_trim/lib/mwe_demo mwe_demo.c -ldl
LD_LIBRARY_PATH=build_trim/lib:build_trim/lib/julia ./build_trim/lib/mwe_demo
# Output: fatal: Core.InitError(mod=:TimeZones, error=Core.MethodError(f=Artifacts.var"#_artifact_str"()...))

The output is:

Output
dlopen succeeded!
fatal: error thrown and no exception handler available.
Core.InitError(mod=:TimeZones, error=Core.MethodError(f=Artifacts.var"#_artifact_str"(), args=(TZJData, "/home/langestefan/.julia/packages/TZJData/gKErz/Artifacts.toml", Base.SubString{Core.String}(string="tzjdata", offset=0, ncodeunits=7), "", Base.Dict{Core.String, Any}(slots=Memory{Core.UInt8}(16, 0x7f87870b9040)[0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], keys=Memory{Core.String}(16, 0x7f878709dd90)[
  #<null>,
  #<null>,
  "tzjdata",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>], vals=Memory{Any}(16, 0x7f878709d900)[
  #<null>,
  #<null>,
  Base.Dict{Core.String, Any}(slots=Memory{Core.UInt8}(16, 0x7f87870b9010)[0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00], keys=Memory{Core.String}(16, 0x7f878709dcc0)[
  #<null>,
  #<null>,
  #<null>,
  "git-tree-sha1",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "download",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>], vals=Memory{Any}(16, 0x7f878709d9f0)[
  #<null>,
  #<null>,
  #<null>,
  "a2939c302ec6f8c6eeb94e4734c96b162e1ff7b5",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  Array{Any, 1}(dims=(1,), mem=Memory{Any}(3, 0x7f878709dac0)[
  Base.Dict{Core.String, Any}(slots=Memory{Core.UInt8}(16, 0x7f87870b8f70)[0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00], keys=Memory{Core.String}(16, 0x7f878709dbf0)[
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "sha256",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "url",
  #<null>,
  #<null>], vals=Memory{Any}(16, 0x7f878709db50)[
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "75d5f6bf78963b5362e46263a9493dc0d460a720eb5f468fdeb50a61dd63649d",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "https://github.com/JuliaTime/TZJData.jl/releases/download/v1.5.0+2025b/tzjfile-v1-tzdata2025b.tar.gz",
  #<null>,
  #<null>], ndel=0, count=2, age=0x0000000000000003, idxfloor=1, maxprobe=0),
  #<null>,
  #<null>]),
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>], ndel=0, count=2, age=0x0000000000000003, idxfloor=1, maxprobe=0),
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>], ndel=0, count=1, age=0x0000000000000002, idxfloor=1, maxprobe=0), Base.SHA1(bytes=(0xa2, 0x93, 0x9c, 0x30, 0x2e, 0xc6, 0xf8, 0xc6, 0xee, 0xb9, 0x4e, 0x47, 0x34, 0xc9, 0x6b, 0x16, 0x2e, 0x1f, 0xf7, 0xb5)), Base.BinaryPlatforms.Platform(tags=Base.Dict{Core.String, Core.String}(slots=Memory{Core.UInt8}(16, 0x7f87870b9330)[0x00, 0x00, 0xdd, 0x8d, 0xf7, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0xe9, 0x00, 0x00, 0xb7, 0xea], keys=Memory{Core.String}(16, 0x7f878709e730)[
  #<null>,
  #<null>,
  "libgfortran_version",
  "arch",
  "julia_version",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "libc",
  #<null>,
  "libstdcxx_version",
  #<null>,
  #<null>,
  "os",
  "cxxstring_abi"], vals=Memory{Core.String}(16, 0x7f878709e690)[
  #<null>,
  #<null>,
  "5.0.0",
  "x86_64",
  "1.12.5",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "glibc",
  #<null>,
  "3.4.30",
  #<null>,
  #<null>,
  "linux",
  "cxx11"], ndel=0, count=7, age=0x0000000000000008, idxfloor=1, maxprobe=2), compare_strategies=Base.Dict{Core.String, Core.Function}(slots=Memory{Core.UInt8}(16, 0x7f87870b9120)[0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00], keys=Memory{Core.String}(16, 0x7f878709e460)[
  #<null>,
  #<null>,
  "julia_version",
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  #<null>,
  "libstdcxx_version",
  #<null>,
  #<null>,
  #<null>,
  #<null>], vals=Memory{Core.Function}(16, 0x7f878709dfd0)[#<null>, #<null>, Base.BinaryPlatforms.var"#4#5"(), #<null>, #<null>, #<null>, #<null>, #<null>, #<null>, #<null>, #<null>, Base.BinaryPlatforms.var"#compare_version_cap"(), #<null>, #<null>, #<null>, #<null>], ndel=0, count=2, age=0x0000000000000003, idxfloor=1, maxprobe=0)), Base.Val{Artifacts}()), world=0x0000000000009791))

Loading TimeZones.jl is enough to cause the failure.

My guess is that --trim removes Artifacts._artifact_str because it is unreachable from hello().

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions