Skip to content

Commit

Permalink
fix(build/embed): include all Emacs C sources and related files in th…
Browse files Browse the repository at this point in the history
…e Emacs.app bundle (#120)

Changelog files from the `src` directory are however excluded. They're
6.7MB, span 1985 to 2015, and are not very relevant for inclusion within
the Emacs.app bundle.

Resolves jimeh/emacs-builds#40
  • Loading branch information
jimeh authored Nov 28, 2024
1 parent 4c99775 commit ccb4f3f
Showing 1 changed file with 50 additions and 32 deletions.
82 changes: 50 additions & 32 deletions build-emacs-for-macos
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ class Build

patches.each { |patch| apply_patch(patch, target) }

# Keep a copy of src after patches have been applied. This will be used to
# embed C sources into the output Emacs.app bundle.
cmd('cp', '-a', File.join(target, 'src'), File.join(target, 'src.orig'))

target
end

Expand Down Expand Up @@ -1136,8 +1140,12 @@ class AbstractEmbedder
@app = app
end

def relative_path(path)
Pathname.new(path).relative_path_from(Pathname.new(app)).to_s
def relative_path(base, path)
Pathname.new(path).relative_path_from(Pathname.new(base)).to_s
end

def relative_app_path(path)
relative_path(app, path)
end

def invocation_dir
Expand Down Expand Up @@ -1207,30 +1215,44 @@ class CSourcesEmbedder < AbstractEmbedder
def embed
info 'Bundling C source files into Emacs.app for documentation purposes...'

orig_src_dir = File.join(source_dir, 'src.orig')
src_dir = File.join(source_dir, 'src')
target_dir = File.join(resources_dir, 'src')
debug "Copying *.c and *.h files from '#{src_dir}' " \
"to: #{relative_path(target_dir)}"

Dir[File.join(src_dir, '**', '*.{c,h}')].each do |f|
rel = f[src_dir.size + 1..-1]
target = File.join(target_dir, rel)
FileUtils.mkdir_p(File.dirname(target))
cmd('cp', '-pRL', f, target)
debug "Copying Emacs C sources to #{relative_app_path(target_dir)}"

if File.exist?(orig_src_dir)
copy_sources(orig_src_dir, target_dir)
else
copy_sources(
src_dir, target_dir, File.join('**', '*.{awk,c,cc,h,in,m,mk}')
)
end

if File.exist?(site_start_el_file) &&
File.read(site_start_el_file).include?(PATH_PATCH)
return
end

debug "Patching '#{relative_path(site_start_el_file)}' to allow Emacs to " \
'find bundled C sources'
debug "Patching '#{relative_app_path(site_start_el_file)}' to allow " \
'Emacs to find bundled C sources'
File.open(site_start_el_file, 'a') { |f| f.puts("\n#{PATH_PATCH}") }
end

private

def copy_sources(src_dir, target_dir, pattern = File.join('**', '*'))
Dir[File.join(src_dir, pattern)].each do |f|
next if File.directory?(f) ||
File.basename(f).downcase.start_with?('changelog')

rel = relative_path(src_dir, f)
target = File.join(target_dir, rel)
FileUtils.mkdir_p(File.dirname(target))
run_cmd('cp', '-pRL', f, target)
end
end

def site_start_el_file
@site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el')
end
Expand All @@ -1256,10 +1278,9 @@ class LibEmbedder < AbstractEmbedder
binary ||= bin

FileUtils.cd(File.dirname(app)) do
rel_path = Pathname.new(lib_dir).relative_path_from(
Pathname.new(File.dirname(binary))
).to_s
rpath = File.join('@executable_path', rel_path)
rpath = File.join(
'@executable_path', relative_path(File.dirname(binary), lib_dir)
)

copy, relink = build_bundle_plan(binary)

Expand Down Expand Up @@ -1300,7 +1321,7 @@ class LibEmbedder < AbstractEmbedder

return if mf.rpaths.include?(rpath)

debug "Setting rpath for '#{relative_path(macho_file)}' to: #{rpath}"
debug "Setting rpath for '#{relative_app_path(macho_file)}' to: #{rpath}"
mf.add_rpath(rpath)
while_writable(macho_file) { mf.write! }
end
Expand Down Expand Up @@ -1330,7 +1351,7 @@ class LibEmbedder < AbstractEmbedder

if macho_file.start_with?(app)
debug 'Calculating bundling instructions for: ' \
"#{relative_path(macho_file)}"
"#{relative_app_path(macho_file)}"
else
debug "Calculating bundling instructions for: #{macho_file}"
end
Expand Down Expand Up @@ -1413,7 +1434,8 @@ class LibEmbedder < AbstractEmbedder

next if File.exist?(target)

debug "Copying '#{source}' to: '#{relative_path(target)}' ('#{dylib_id}')"
debug "Copying '#{source}' to: " \
"'#{relative_app_path(target)}' ('#{dylib_id}')"
FileUtils.mkdir_p(File.dirname(target))
cmd('cp', '-pRL', source, target)

Expand All @@ -1434,7 +1456,7 @@ class LibEmbedder < AbstractEmbedder

relink_files = relink.group_by { |r| r[:target_file] }
relink_files.each do |target_file, relinks|
debug "Changing linked dylibs in: '#{relative_path(target_file)}'"
debug "Changing linked dylibs in: '#{relative_app_path(target_file)}'"
mf = MachO.open(target_file)
changed = false

Expand Down Expand Up @@ -1556,7 +1578,7 @@ class GccLibEmbedder < AbstractEmbedder
rpaths = mf.rpaths.reject { |r| r == '@loader_path' }
next if rpaths.none?

debug "Tidying up rpaths from: #{relative_path(file_path)}"
debug "Tidying up rpaths from: #{relative_app_path(file_path)}"
rpaths.each { |r| mf.delete_rpath(r) }
mf.write!
end
Expand Down Expand Up @@ -1586,10 +1608,6 @@ class GccLibEmbedder < AbstractEmbedder
gcc_info.darwin_lib_dir
end

def relative_dir(path, root)
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
end

def site_start_el_file
@site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el')
end
Expand Down Expand Up @@ -1676,17 +1694,17 @@ class GccInfo

def app_bundle_target_lib_dir
@app_bundle_target_lib_dir ||=
relative_dir(
File.join(embedder.lib_dir, target_lib_dir),
embedder.invocation_dir
relative_path(
embedder.invocation_dir,
File.join(embedder.lib_dir, target_lib_dir)
)
end

def app_bundle_target_darwin_lib_dir
@app_bundle_target_darwin_lib_dir ||=
relative_dir(
File.join(embedder.lib_dir, sanitized_target_darwin_lib_dir),
embedder.invocation_dir
relative_path(
embedder.invocation_dir,
File.join(embedder.lib_dir, sanitized_target_darwin_lib_dir)
)
end

Expand Down Expand Up @@ -1761,8 +1779,8 @@ class GccInfo
@embedder ||= AbstractEmbedder.new(Dir.mktmpdir(%w[Emacs .app]))
end

def relative_dir(path, root)
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
def relative_path(base, path)
Pathname.new(path).relative_path_from(Pathname.new(base)).to_s
end
end

Expand Down

0 comments on commit ccb4f3f

Please sign in to comment.