Skip to content
Open
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
33 changes: 17 additions & 16 deletions src/bundling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ function bundle_products(recipe::BundleRecipe)
return
end

# Wipe top-level subdirs of a previous bundle so re-runs are idempotent
# (PackageCompiler's bundle_cert/bundle_artifacts cp without force). Only
# touch directories: top-level files are link products (the main artifact
# plus, on Windows, its sibling `.dll.a` import library) and must survive.
# Skip any subdir that contains the link output (programmatic API allows
# outname inside output_dir).
out_abs = abspath(recipe.output_dir)
outname_abs = abspath(recipe.link_recipe.outname)
if isdir(out_abs)
for entry in readdir(out_abs, join=true)
isdir(entry) || continue
startswith(relpath(outname_abs, abspath(entry)), "..") || continue
rm(entry; force=true, recursive=true)
end
end

# Ensure the bundle output directory exists
mkpath(recipe.output_dir)

Expand All @@ -24,22 +40,14 @@ function bundle_products(recipe::BundleRecipe)

# Re-home bundled libraries into the desired bundle layout
libdir = recipe.libdir
# Move `<output_dir>/julia` -> `<output_dir>/<libdir>/julia`
# Move `<output_dir>/julia` -> `<output_dir>/<libdir>/julia`.
src_julia_dir = joinpath(recipe.output_dir, "julia")
if isdir(src_julia_dir)
dest_root = joinpath(recipe.output_dir, libdir)
mkpath(dest_root)
dest_julia_dir = joinpath(dest_root, "julia")
if abspath(src_julia_dir) != abspath(dest_julia_dir)
if isdir(dest_julia_dir)
# Track this directory for removal in the consolidation function
dirs_to_remove = [dest_julia_dir]
else
dirs_to_remove = String[]
end
mv(src_julia_dir, dest_julia_dir; force=true)
else
dirs_to_remove = String[]
end
# On Windows, place required DLLs next to the executable (in bin/) for loader discovery
if Sys.iswindows()
Expand All @@ -55,8 +63,6 @@ function bundle_products(recipe::BundleRecipe)
end
end
end
else
dirs_to_remove = String[]
end

# Determine where to place the built product within the bundle
Expand All @@ -83,11 +89,6 @@ function bundle_products(recipe::BundleRecipe)
if Sys.isapple()
_codesign_bundle!(recipe)
end

# Now perform all directory removals at once
for dir in dirs_to_remove
rm(dir; force=true, recursive=true)
end
end

function remove_unnecessary_libraries(recipe::BundleRecipe)
Expand Down
27 changes: 18 additions & 9 deletions src/linking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ function link_products(recipe::LinkRecipe)
try
mkpath(dirname(recipe.outname))
is_shared_output = image_recipe.output_type != "--output-exe"
# Reject output paths that resolve to an existing directory; on case-insensitive
# filesystems this also catches case-only collisions with the package dir (#132).
if isdir(recipe.outname)
error("Output path '$(recipe.outname)' already exists as a directory " *
"(case-insensitive filesystems may match a differently-cased dir " *
"such as the package directory). Choose a different output name.")
end
# Base command
cmd2 = `$(compiler_cmd)`
for f in recipe.ld_flags
Expand All @@ -137,16 +144,18 @@ function link_products(recipe::LinkRecipe)
end
# Link in the whole archive and user-provided objects, then undo WHOLE_ARCHIVE
cmd2 = `$cmd2 -Wl,$(Base.Linking.WHOLE_ARCHIVE) $(image_recipe.img_path) $(image_recipe.extra_objects) -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $(julia_libs)`
# Platform-specific linker flags
# install_name / soname / import-lib are shared-library only.
lib_name = basename(recipe.outname)
if Sys.iswindows()
lib_basename, _ = splitext(lib_name)
import_lib_path = joinpath(dirname(recipe.outname), lib_basename * ".dll.a")
cmd2 = `$cmd2 -Wl,--out-implib=$(import_lib_path)`
elseif Sys.isapple()
cmd2 = `$cmd2 -Wl,-install_name,@rpath/$(lib_name)`
elseif Sys.islinux()
cmd2 = `$cmd2 -Wl,-soname,$(lib_name)`
if is_shared_output
if Sys.iswindows()
lib_basename, _ = splitext(lib_name)
import_lib_path = joinpath(dirname(recipe.outname), lib_basename * ".dll.a")
cmd2 = `$cmd2 -Wl,--out-implib=$(import_lib_path)`
elseif Sys.isapple()
cmd2 = `$cmd2 -Wl,-install_name,@rpath/$(lib_name)`
elseif Sys.islinux()
cmd2 = `$cmd2 -Wl,-soname,$(lib_name)`
end
end
image_recipe.verbose && println("Running: $cmd2")
run(cmd2)
Expand Down
Loading