diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index 8b1eb55cbe4f4..6794834834d25 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -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" @@ -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 @@ -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) @@ -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() diff --git a/contrib/juliac.jl b/contrib/juliac.jl index 3d1a3ef13fe79..8b413fccd6231 100644 --- a/contrib/juliac.jl +++ b/contrib/juliac.jl @@ -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) @@ -15,6 +20,7 @@ if help !== nothing Usage: julia juliac.jl [--output-exe | --output-lib | --output-sysimage] [options] --experimental --trim= 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) @@ -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) @@ -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() + 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") @@ -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)