JuliaLang / PackageCompiler.jl

Compile your Julia Package
https://julialang.github.io/PackageCompiler.jl/dev/
MIT License
1.42k stars 188 forks source link

macOS: System image file fails consistency check on binary startup #738

Open ghyatzo opened 1 year ago

ghyatzo commented 1 year ago

Upon creating an app, the process goes on smoothly, untill it is time to actually call the binary. I get the error: ERROR: System image file failed consistency check: maybe opened the wrong version?

Julia Version 1.8.2
Commit 36034abf260 (2022-09-29 15:21 UTC)
Platform Info:
  OS: macOS (arm64-apple-darwin21.3.0)
  CPU: 10 × Apple M1 Pro
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, apple-m1)
  Threads: 8 on 8 virtual cores
Environment:
  JULIA_NUM_THREADS = 8
  JULIA_DEPOT_PATH = /Users/cshen/.local/julia

I installed julia through juliaup. the juliaup folder is in ~/.local/juliaup and the julia versions in ~/.local/julia/juliaup. the binaries in ~/.local/juliaup/bin are symlinked to ~/.local/bin which is in the PATH. I also have julia aliased to julia --project=@.

Could it be that the symlinking throws some pathing off somewhere?

bjarthur commented 7 months ago

others have this problem too and used the same -ld_classic workaround: https://www.scivision.dev/xcode-ld_classic/. possibly needed because of weak references as described in the "known issues" section here: https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking

bjarthur commented 7 months ago

can someone with xcode version 14 or less try the -ld_classic workaround described above? if it continues to work, i'd suggest we just add it universally.

PhilReinhold commented 7 months ago

@bjarthur

Unfortunately I've seen this flag break compilation with xcode 14 since I think it's unrecognized. I've used the following locally to detect xcode version and conditionally apply the flag:

function PackageCompiler.create_sysimg_from_object_file(object_files::Vector{String},
                                        sysimage_path::String;
                                        version,
                                        compat_level::String,
                                        soname::Union{Nothing, String})

    if soname === nothing && (Sys.isunix() && !Sys.isapple())
        soname = basename(sysimage_path)
    end
    mkpath(dirname(sysimage_path))
    # Prevent compiler from stripping all symbols from the shared lib.
    if Sys.isapple()
        cltools_version_cmd = `pkgutil --pkg-info=com.apple.pkg.CLTools_Executables`
        cltools_version = match(r"version: (.*)\n", readchomp(cltools_version_cmd))[1]
        if startswith(cltools_version, "15")
            o_file_flags = `-Wl,-all_load $object_files -Wl,-ld_classic`
        else
            o_file_flags = `-Wl,-all_load $object_files`
        end
    else
        o_file_flags = `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`
    end
    extra = get_extra_linker_flags(version, compat_level, soname)
    cmd = `$(bitflag()) $(march()) -shared -L$(julia_libdir()) -L$(julia_private_libdir()) -o $sysimage_path $o_file_flags $(Base.shell_split(ldlibs())) $extra`
    run_compiler(cmd; cplusplus=true)
    return nothing
end
bjarthur commented 7 months ago

@PhilReinhold submit a PR! is there any reason not to? you've found a nice solution and everyone here has verified it works for them.

thomasjankovic commented 6 months ago

I'll admit that I don't really understand what's going on here, but I saw this exhortation of success by adding the flags -Wl,-ld_classic, and decided to try it here.

I modified o_file_flags in PackageCompiler.jl:create_sysimg_from_object_file like so

function create_sysimg_from_object_file(object_files::Vector{String},
                                        sysimage_path::String;
                                        version,
                                        compat_level::String,
                                        soname::Union{Nothing, String})

    if soname === nothing && (Sys.isunix() && !Sys.isapple())
        soname = basename(sysimage_path)
    end
    mkpath(dirname(sysimage_path))
    # Prevent compiler from stripping all symbols from the shared lib.
    o_file_flags = Sys.isapple() ? `-Wl,-all_load $object_files -Wl,-ld_classic` : `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`
    extra = get_extra_linker_flags(version, compat_level, soname)
    cmd = `$(bitflag()) $(march()) -shared -L$(julia_libdir()) -L$(julia_private_libdir()) -o $sysimage_path $o_file_flags $(Base.shell_split(ldlibs())) $extra`
    run_compiler(cmd; cplusplus=true)
    return nothing
end

and now I am able to produce sysimages following the tutorial which have symbols exported and julia happily loads, despite being on xcode CLT version 15.

Probably not the right course of action to just add this flag universally, but maybe having a mechanism for passing additional linker flags could be part of the create_sysimage interface.

Can confirm that this worked for me too. Julia 1.9.4 and gcc-13.

jayscook commented 6 months ago

Hey folks, I went ahead and opened a PR for @PhilReinhold's fix. I'd love it if someone can review! I haven't contributed here before so please let me know if I'm missing any conventions, considerations, etc.

rallen10 commented 4 months ago

@bjarthur

Unfortunately I've seen this flag break compilation with xcode 14 since I think it's unrecognized. I've used the following locally to detect xcode version and conditionally apply the flag:

function PackageCompiler.create_sysimg_from_object_file(object_files::Vector{String},
                                        sysimage_path::String;
                                        version,
                                        compat_level::String,
                                        soname::Union{Nothing, String})

    if soname === nothing && (Sys.isunix() && !Sys.isapple())
        soname = basename(sysimage_path)
    end
    mkpath(dirname(sysimage_path))
    # Prevent compiler from stripping all symbols from the shared lib.
    if Sys.isapple()
        cltools_version_cmd = `pkgutil --pkg-info=com.apple.pkg.CLTools_Executables`
        cltools_version = match(r"version: (.*)\n", readchomp(cltools_version_cmd))[1]
        if startswith(cltools_version, "15")
            o_file_flags = `-Wl,-all_load $object_files -Wl,-ld_classic`
        else
            o_file_flags = `-Wl,-all_load $object_files`
        end
    else
        o_file_flags = `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`
    end
    extra = get_extra_linker_flags(version, compat_level, soname)
    cmd = `$(bitflag()) $(march()) -shared -L$(julia_libdir()) -L$(julia_private_libdir()) -o $sysimage_path $o_file_flags $(Base.shell_split(ldlibs())) $extra`
    run_compiler(cmd; cplusplus=true)
    return nothing
end

I was experiencing the same problem and I can confirm the above fix works on

rallen10 commented 4 months ago

Similar issue here on

Julia Version 1.8.4
Commit 00177ebc4fc (2022-12-23 21:32 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin21.4.0)
  CPU: 16 × Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 16 on 16 virtual cores
Environment:
  JULIA_NUM_THREADS = auto

the app execute smoothly when it is in the folder where it has been compiled but fail with ERROR: System image file failed consistency check: maybe opened the wrong version? when relocated anywhere else. Using the example of the package

> Code/Julia/PackageCompiler.jl/examples/MyAppCompiled/bin/MyApp 
  Downloaded artifact: MKL
ARGS = String[]
Base.PROGRAM_FILE = "Code/Julia/PackageCompiler.jl/examples/MyAppCompiled/bin/MyApp"
...

> cp -r Code/Julia/PackageCompiler.jl/examples/MyAppCompiled .
> MyAppCompiled/bin/MyApp                                     
ERROR: System image file failed consistency check: maybe opened the wrong version?

@FerreolS did you ever get resolution for your problem? It seems to be closely-related-yet-distinct from the workarounds mentioned in this thread. After using @PhilReinhold fix I am able to build an app and run it in its build location; but now I am facing your problem where relocating the app causes the consistency check error to re-appear.

I've created a new issue: #943

ctarn commented 4 months ago

I run into the same problem again... I previously set JULIA_CC to gcc-13, and it doesn't work after some changes to my iMac (maybe updating OS). So I switched back clang, and changed the flag to -Wl,-ld_classic, as suggested by @PhilReinhold, and it works now.

o_file_flags = Sys.isapple() ? `-Wl,-ld_classic,-all_load $object_files` : `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`

Hope we can solve the issue soon.😵‍💫

stevezhaoUS commented 4 months ago

I have face the same issue, hope it can be fix soon.

abelozerov commented 2 weeks ago

Facing the same issue on x64 machine