Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contrib: add --relative-rpath option to juliac.jl #57199

Merged
merged 3 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 34 additions & 23 deletions contrib/julia-config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ function includeDir()
return abspath(Sys.BINDIR, Base.INCLUDEDIR, "julia")
end

function ldflags(doframework)
doframework && return "-F$(shell_escape(frameworkDir()))"
function ldflags(; framework::Bool=false)
framework && return "-F$(shell_escape(frameworkDir()))"
fl = "-L$(shell_escape(libDir()))"
if Sys.iswindows()
fl = fl * " -Wl,--stack,8388608"
Expand All @@ -56,27 +56,40 @@ function ldflags(doframework)
return fl
end

function ldlibs(doframework)
function ldrpath()
libname = if Base.isdebugbuild()
"julia-debug"
else
"julia"
end
return "-Wl,-rpath,$(shell_escape(private_libDir())) -Wl,-rpath,$(shell_escape(libDir())) -l$libname"
end

function ldlibs(; framework::Bool=false, rpath::Bool=true)
# Return "Julia" for the framework even if this is a debug build.
# If the user wants the debug framework, DYLD_IMAGE_SUFFIX=_debug
# should be used (refer to man 1 dyld).
doframework && return "-framework $(Base.DARWIN_FRAMEWORK_NAME)"
framework && return "-framework $(Base.DARWIN_FRAMEWORK_NAME)"
libname = if Base.isdebugbuild()
"julia-debug"
else
"julia"
end
if Sys.isunix()
return "-L$(shell_escape(private_libDir())) -Wl,-rpath,$(shell_escape(libDir())) -Wl,-rpath,$(shell_escape(private_libDir())) -l$libname"
if rpath
return "-L$(shell_escape(private_libDir())) $(ldrpath())"
else
return "-L$(shell_escape(private_libDir()))"
end
else
return "-l$libname -lopenlibm"
end
end

function cflags(doframework)
function cflags(; framework::Bool=false)
flags = IOBuffer()
print(flags, "-std=gnu11")
if doframework
if framework
include = shell_escape(frameworkDir())
print(flags, " -F", include)
else
Expand All @@ -89,8 +102,8 @@ function cflags(doframework)
return String(take!(flags))
end

function allflags(doframework)
return "$(cflags(doframework)) $(ldflags(doframework)) $(ldlibs(doframework))"
function allflags(; framework::Bool=false, rpath::Bool=true)
return "$(cflags(; framework)) $(ldflags(; framework)) $(ldlibs(; framework, rpath))"
end

function check_args(args)
Expand All @@ -102,31 +115,29 @@ function check_args(args)
end

function check_framework_flag(args)
doframework = "--framework" in args
if doframework && !Base.DARWIN_FRAMEWORK
framework = "--framework" in args
if framework && !Base.DARWIN_FRAMEWORK
println(stderr, "NOTICE: Ignoring --framework because Julia is not packaged as a framework.")
return false
elseif !doframework && Base.DARWIN_FRAMEWORK
elseif !framework && Base.DARWIN_FRAMEWORK
println(stderr, "NOTICE: Consider using --framework because Julia is packaged as a framework.")
return false
end
return doframework
return framework
end

function main()
check_args(ARGS)
doframework = check_framework_flag(ARGS)
for args in ARGS
function (@main)(args)
check_args(args)
framework = check_framework_flag(args)
for args in args
if args == "--ldflags"
println(ldflags(doframework))
println(ldflags(; framework))
elseif args == "--cflags"
println(cflags(doframework))
println(cflags(; framework))
elseif args == "--ldlibs"
println(ldlibs(doframework))
println(ldlibs(; framework))
elseif args == "--allflags"
println(allflags(doframework))
println(allflags(; framework))
end
end
end

main()
36 changes: 31 additions & 5 deletions contrib/juliac.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Julia compiler wrapper script
# NOTE: The interface and location of this script are considered unstable/experimental

module JuliaConfig
include(joinpath(@__DIR__, "julia-config.jl"))
end

julia_cmd = `$(Base.julia_cmd()) --startup-file=no --history-file=no`
output_type = nothing # exe, sharedlib, sysimage
outname = nothing
file = nothing
add_ccallables = false
relative_rpath = false
verbose = false

help = findfirst(x->x == "--help", ARGS)
Expand All @@ -15,6 +20,7 @@ if help !== nothing
Usage: julia juliac.jl [--output-exe | --output-lib | --output-sysimage] <name> [options] <file.jl>
--experimental --trim=<no,safe,unsafe,unsafe-warn> Only output code statically determined to be reachable
--compile-ccallable Include all methods marked `@ccallable` in output
--relative-rpath Configure the library / executable to lookup all required libraries in an adjacent "julia/" folder
--verbose Request verbose output
""")
exit(0)
Expand All @@ -36,6 +42,8 @@ let i = 1
global add_ccallables = true
elseif arg == "--verbose"
global verbose = true
elseif arg == "--relative-rpath"
global relative_rpath = true
elseif startswith(arg, "--trim") || arg == "--experimental"
# forwarded args
push!(julia_args, arg)
Expand All @@ -53,11 +61,27 @@ end
isnothing(outname) && error("No output file specified")
isnothing(file) && error("No input file specified")

function get_rpath(; relative::Bool = false)
if relative
if Sys.isapple()
return "-Wl,-rpath,'@loader_path/julia/' -Wl,-rpath,'@loader_path/'"
elseif Sys.islinux()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should be Sys.isunix() instead of Sys.islinux()? It's not Linux-specific AFAICT.

return "-Wl,-rpath,'\$ORIGIN/julia/' -Wl,-rpath,'\$ORIGIN/'"
else
error("unimplemented")
end
else
return JuliaConfig.ldrpath()
end
end

absfile = abspath(file)
cflags = readchomp(`$(julia_cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --cflags `)
cflags = JuliaConfig.cflags(; framework=false)
cflags = Base.shell_split(cflags)
allflags = readchomp(`$(julia_cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --allflags`)
allflags = JuliaConfig.allflags(; framework=false, rpath=false)
allflags = Base.shell_split(allflags)
rpath = get_rpath(; relative = relative_rpath)
rpath = Base.shell_split(rpath)
tmpdir = mktempdir(cleanup=false)
initsrc_path = joinpath(tmpdir, "init.c")
init_path = joinpath(tmpdir, "init.a")
Expand Down Expand Up @@ -113,12 +137,14 @@ function link_products()
julia_libs = Base.shell_split(Base.isdebugbuild() ? "-ljulia-debug -ljulia-internal-debug" : "-ljulia -ljulia-internal")
try
if output_type == "--output-lib"
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
cmd2 = `cc $(allflags) $(rpath) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`
elseif output_type == "--output-sysimage"
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $(julia_libs)`)
cmd2 = `cc $(allflags) $(rpath) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $(julia_libs)`
else
run(`cc $(allflags) -o $outname -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
cmd2 = `cc $(allflags) $(rpath) -o $outname -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`
end
verbose && println("Running: $cmd2")
run(cmd2)
catch e
println("\nCompilation failed: ", e)
exit(1)
Expand Down