Compare commits

...

19 Commits

Author SHA1 Message Date
3d6c7fff64 chore(release): 0.6.42 2023-07-31 18:42:33 +01:00
d08d1b9b5c feat: options for log-level and github source repository
Changes:

- Adds optional --log-level flag and lots of debug output when level is
  set to "debug"
- Adds optional --github-src-repo flag to specify a custom GitHub
  repository to download source tarball from.
- Resolve all current Rubocop complaints.
2023-07-31 18:39:38 +01:00
6e32219c24 chore(deps): add webp to Brewfile 2023-07-31 18:36:22 +01:00
d2548191f1 chore(release): 0.6.41 2023-01-16 23:52:25 +00:00
8ed16b27c0 ci(builds): add python to CI dependencies 2023-01-16 23:23:43 +00:00
14f7aa13d9 chore(release): 0.6.40 2023-01-08 22:39:03 +00:00
59ebbdaa2b Merge pull request #79 from jimeh/fix-nightly-builds 2023-01-08 22:38:16 +00:00
d98c14dde5 chore(deps): remove python CI dependency
Instead use default python version install on macOS to install dmgbuild.
2023-01-08 21:21:54 +00:00
590b0ac21a chore(deps): remove curl from Brewfile
Curl is part of macOS, and the curl homebrew formula is keg-only.
Meaning there's no reason to install it for our purposes.
2023-01-08 20:39:17 +00:00
8c84ef128f chore(release): 0.6.39 2022-12-04 20:33:32 +00:00
8b447b6237 feat(version): correctly handle Emacs 30.x builds 2022-12-04 20:32:55 +00:00
c3d19694e7 feat(deprecate): posix-spawn patch is no longer supported
Nor is it needed, as it was only an issue in master for a short period
of time.
2022-12-04 20:30:20 +00:00
cff89684c6 chore(release): 0.6.38 2022-12-01 22:35:08 +00:00
48a512fbce feat(patch): add round-undecorated-frame from emacs-plus for 29.x 2022-12-01 22:30:48 +00:00
a3530c02e8 feat(patch): add support for experimental poll patch from emacs-plus for 29.x 2022-12-01 22:30:42 +00:00
138ac74ba5 chore(release): 0.6.37 2022-12-01 22:09:38 +00:00
0ba971ef61 feat(tree-sitter): support new --with-tree-sitter configure flag 2022-12-01 22:08:29 +00:00
1ae8771b2c chore(release): 0.6.36 2022-10-08 14:41:30 +01:00
1f2868d4b3 fix(native-comp): support new configure flag format
Commit e245c4f226979ccb717cccc8f82b2b0a0f96bdac on Emacs' master branch
added support for optional flags to the --with-native-compilation
configure flag.

This change to output of ./configure --help broke the native comp
detection present in our build script.

This change adds support for the new configure flag format, while also
using it to specify AOT when enabled.

It is still backwards compatible with the configure script in older
commits.

Fixes #76
2022-10-08 14:38:37 +01:00
4 changed files with 321 additions and 110 deletions

View File

@@ -1,9 +1,30 @@
AllCops:
TargetRubyVersion: 2.3
TargetRubyVersion: 2.4
NewCops: enable
Layout/LineLength:
Max: 80
Style/AccessorGrouping:
Enabled: false
Style/Documentation:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/BlockLength:
Enabled: false
Metrics/ClassLength:
Enabled: false
Metrics/CyclomaticComplexity:
Enabled: false
Metrics/MethodLength:
Enabled: false
Metrics/PerceivedComplexity:
Enabled: false

View File

@@ -2,7 +2,6 @@
brew 'autoconf'
brew 'coreutils'
brew 'curl'
brew 'dbus'
brew 'expat'
brew 'gcc'
@@ -25,4 +24,6 @@ brew 'nettle'
brew 'pkg-config'
brew 'sqlite'
brew 'texinfo'
brew 'tree-sitter'
brew 'webp'
brew 'zlib'

View File

@@ -2,6 +2,47 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.6.42](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.41...v0.6.42) (2023-07-31)
### Features
* options for log-level and github source repository ([d08d1b9](https://github.com/jimeh/build-emacs-for-macos/commit/d08d1b9b5c4001302564dc8915884c465802f3b5))
### [0.6.41](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.40...v0.6.41) (2023-01-16)
### [0.6.40](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.39...v0.6.40) (2023-01-08)
### [0.6.39](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.38...v0.6.39) (2022-12-04)
### Features
* **deprecate:** posix-spawn patch is no longer supported ([c3d1969](https://github.com/jimeh/build-emacs-for-macos/commit/c3d19694e7e4d33d462c9917683c2d63f69002f5))
* **version:** correctly handle Emacs 30.x builds ([8b447b6](https://github.com/jimeh/build-emacs-for-macos/commit/8b447b6237fbbd94c4e72af8ee79969c7cfc9363))
### [0.6.38](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.37...v0.6.38) (2022-12-01)
### Features
* **patch:** add round-undecorated-frame from emacs-plus for 29.x ([48a512f](https://github.com/jimeh/build-emacs-for-macos/commit/48a512fbce79759caa987e2880585bd0bc937977))
* **patch:** add support for experimental poll patch from emacs-plus for 29.x ([a3530c0](https://github.com/jimeh/build-emacs-for-macos/commit/a3530c02e8260106f87d464e5cb398dcb2819460))
### [0.6.37](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.36...v0.6.37) (2022-12-01)
### Features
* **tree-sitter:** support new --with-tree-sitter configure flag ([0ba971e](https://github.com/jimeh/build-emacs-for-macos/commit/0ba971ef61a195c91e87aa381d5d3b044461b4f6))
### [0.6.36](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.35...v0.6.36) (2022-10-08)
### Bug Fixes
* **native-comp:** support new configure flag format ([1f2868d](https://github.com/jimeh/build-emacs-for-macos/commit/1f2868d4b3784e906665e9f3b6b9bba8fd72292f)), closes [#76](https://github.com/jimeh/build-emacs-for-macos/issues/76)
### [0.6.35](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.34...v0.6.35) (2022-08-10)

View File

@@ -7,6 +7,7 @@ require 'erb'
require 'etc'
require 'fileutils'
require 'json'
require 'logger'
require 'net/http'
require 'optparse'
require 'pathname'
@@ -18,33 +19,68 @@ require 'yaml'
class Error < StandardError; end
module Output
def info(msg, newline: true)
out "INFO: #{msg}", newline: newline
end
class << self
LEVELS = {
debug: Logger::DEBUG,
error: Logger::ERROR,
fatal: Logger::FATAL,
info: Logger::INFO,
unknown: Logger::UNKNOWN,
warn: Logger::WARN
}.freeze
def out(msg, newline: true)
if newline
warn "==> #{msg}"
else
$stderr.print "==> #{msg}"
def log_level
LEVELS.key(logger.level)
end
def log_level=(level)
logger.level = LEVELS.fetch(level&.to_sym)
end
def logger
@logger ||= Logger.new($stderr).tap do |logger|
logger.level = Logger::INFO
logger.formatter = proc do |severity, _datetime, _progname, msg|
"==> #{severity.upcase}: #{msg}"
end
end
end
end
def err(msg = nil)
%i[debug info warn error].each do |severity|
define_method(severity) do |msg, newline: true|
logger.send(severity, format_msg(msg, newline: newline))
end
end
def fatal(msg = nil)
raise Error, msg
end
private
def logger
Output.logger
end
def format_msg(msg, newline: true)
msg = msg.join("\n") if msg.is_a?(Array)
msg = msg.strip
msg = "#{msg}\n" if newline
msg
end
end
module System
include Output
def run_cmd(*args)
out("CMD: #{args.join(' ')}")
debug "executing: #{args.join(' ')}"
cmd(*args)
end
def cmd(*args)
system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}")
system(*args) || fatal("Exit code: #{$CHILD_STATUS.exitstatus}")
end
end
@@ -61,7 +97,7 @@ end
class OSVersion
def initialize
@version = `sw_vers -productVersion`.match(
/(?<major>\d+)(?:\.(?<minor>\d+)(:?\.(?<patch>\d+))?)?/
/(?<major>\d+)(?:\.(?<minor>\d+)(?:\.(?<patch>\d+))?)?/
)
end
@@ -86,8 +122,7 @@ class Build
include Output
include System
EMACS_MIRROR_REPO = 'emacs-mirror/emacs'
DOWNLOAD_URL = 'https://github.com/emacs-mirror/emacs/tarball/%s'
DEFAULT_GITHUB_REPO = 'emacs-mirror/emacs'
attr_reader :root_dir
attr_reader :source_dir
@@ -106,7 +141,7 @@ class Build
load_plan(options[:plan]) if options[:plan]
unless meta[:sha] && meta[:date]
err 'Failed to get commit info from GitHub.'
fatal 'Failed to get commit info from GitHub.'
end
tarball = download_tarball(meta[:sha])
@@ -122,7 +157,9 @@ class Build
CLIHelperEmbedder.new(app).embed
CSourcesEmbedder.new(app, @source_dir).embed
LibEmbedder.new(app, brew_dir, extra_libs, options[:relink_eln]).embed
LibEmbedder.new(
app, brew_dir, extra_libs, relink_eln_files: options[:relink_eln]
).embed
GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp]
archive_build(build_dir) if options[:archive]
@@ -131,6 +168,7 @@ class Build
private
def load_plan(filename)
debug "Loading plan from: #{filename}"
plan = YAML.safe_load(File.read(filename), [:Time])
@ref = plan.dig('source', 'ref')
@@ -163,6 +201,10 @@ class Build
@output_dir ||= (options[:output] || File.join(root_dir, 'builds'))
end
def github_src_repo
@github_src_repo ||= options[:github_src_repo] || DEFAULT_GITHUB_REPO
end
def brew_dir
@brew_dir ||= `brew --prefix`.chomp
end
@@ -189,8 +231,8 @@ class Build
def download_tarball(sha)
FileUtils.mkdir_p(tarballs_dir)
url = (DOWNLOAD_URL % sha)
filename = "emacs-mirror-emacs-#{sha[0..6]}.tgz"
url = "https://github.com/#{github_src_repo}/tarball/#{sha}"
filename = "#{github_src_repo.gsub(/[^a-zA-Z0-9-]+/, '-')}-#{sha[0..6]}.tgz"
target = File.join(tarballs_dir, filename)
if File.exist?(target)
@@ -212,7 +254,7 @@ class Build
log_args[1..-1]
end
out "CMD: #{log_args.join(' ')}"
debug "executing: #{log_args.join(' ')}"
cmd(*args)
target
@@ -231,7 +273,7 @@ class Build
info 'Extracting tarball...'
result = run_cmd('tar', '-xzf', filename, '-C', sources_dir)
err 'Tarball extraction failed.' unless result
fatal 'Tarball extraction failed.' unless result
patches.each { |patch| apply_patch(patch, target) }
@@ -250,26 +292,53 @@ class Build
@supports_xwidgets ||= !!configure_help.match(/\s+--with-xwidgets\s+/)
end
def supports_tree_sitter?
@supports_tree_sitter ||= !!configure_help.match(
/\s+--with-tree-sitter(\s|=).+/
)
end
def supports_native_comp?
@supports_native_comp ||= !native_comp_configure_flag.nil?
end
def native_comp_configure_match
@native_comp_configure_match ||= configure_help.match(
/\s+?(--with-native(?:comp|-compilation))(.+)?\s+?/
)
end
def native_comp_configure_flag
@native_comp_configure_flag ||= configure_help.match(
/\s+(--with-native(?:comp|-compilation))\s+/
)&.[](1)
return @native_comp_configure_flag if @native_comp_configure_flag
return unless native_comp_configure_match&.[](1)
@native_comp_configure_flag = [
native_comp_configure_match[1],
native_comp_configure_flag_arg
].compact.join('=')
end
def native_comp_configure_flag_arg
return @native_comp_configure_flag_arg if @native_comp_configure_flag_arg
return if native_comp_configure_match&.[](2) != '[=TYPE]'
@native_comp_configure_flag_arg = \
(options[:native_full_aot] ? 'aot' : 'yes')
end
def detect_native_comp
info 'Detecting native-comp support: ', newline: false
info 'Detecting native-comp support...'
options[:native_comp] = supports_native_comp?
puts options[:native_comp] ? 'Supported' : 'Not supported'
info 'Native-comp is: ' \
"#{options[:native_comp] ? 'Supported' : 'Not supported'}"
end
def verify_native_comp
return if supports_native_comp?
err 'This emacs source tree does not support native-comp'
fatal 'This emacs source tree does not support native-comp'
end
def autogen
@@ -288,7 +357,7 @@ class Build
if File.exist?(emacs_app)
info 'Emacs.app already exists in ' \
"\"#{target.gsub(root_dir + '/', '')}\", attempting to use."
"\"#{target.gsub("#{root_dir}/", '')}\", attempting to use."
return emacs_app
end
@@ -305,7 +374,7 @@ class Build
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
'-O2',
(options[:native_march] ? '-march=native' : nil),
ENV['CFLAGS']
ENV.fetch('CFLAGS', nil)
].compact.join(' ')
ENV['LDFLAGS'] = [
@@ -316,14 +385,14 @@ class Build
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
# Ensure library re-linking and code signing will work after building.
'-Wl,-headerpad_max_install_names',
ENV['LDFLAGS']
ENV.fetch('LDFLAGS', nil)
].compact.join(' ')
ENV['LIBRARY_PATH'] = [
gcc_info.lib_dir,
gcc_info.darwin_lib_dir,
gcc_info.libgccjit_lib_dir,
ENV['LIBRARY_PATH']
ENV.fetch('LIBRARY_PATH', nil)
].compact.join(':')
end
@@ -337,7 +406,7 @@ class Build
File.join(brew_dir, 'opt/zlib/lib/pkgconfig'),
File.join(brew_dir, 'Homebrew/Library/Homebrew/os/mac/pkgconfig',
OS.version.to_s),
ENV['PKG_CONFIG_PATH']
ENV.fetch('PKG_CONFIG_PATH', nil)
].compact.join(':')
ENV['PATH'] = [
@@ -346,11 +415,11 @@ class Build
File.join(brew_dir, 'opt/gnu-sed/libexec/gnubin'),
File.join(brew_dir, 'bin'),
File.join(brew_dir, 'opt/texinfo/bin'),
ENV['PATH']
ENV.fetch('PATH', nil)
].compact.join(':')
ENV['LIBRARY_PATH'] = [
ENV['LIBRARY_PATH'],
ENV.fetch('LIBRARY_PATH', nil),
'/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib'
].compact.join(':')
@@ -365,11 +434,14 @@ class Build
if options[:xwidgets] && supports_xwidgets?
configure_flags << '--with-xwidgets'
end
if options[:tree_sitter] && supports_tree_sitter?
configure_flags << '--with-tree-sitter'
end
configure_flags << native_comp_configure_flag if options[:native_comp]
configure_flags << '--without-rsvg' if options[:rsvg] == false
configure_flags << '--without-dbus' if options[:dbus] == false
run_cmd './configure', *configure_flags
run_cmd './configure', *configure_flags.compact
# Disable aligned_alloc on Mojave and below. See issue:
# https://github.com/daviderestivo/homebrew-emacs-head/issues/15
@@ -386,8 +458,12 @@ class Build
make_flags << "BYTE_COMPILE_EXTRA_FLAGS=--eval '(setq comp-speed 2)'"
if options[:native_full_aot]
info 'Using NATIVE_FULL_AOT=1'
make_flags << 'NATIVE_FULL_AOT=1'
info 'Using native compile full AOT'
# We do not need to supply the full AOT make arg if
# --with-native-compilation=aot configure flag is supported.
unless native_comp_configure_flag_arg
make_flags << 'NATIVE_FULL_AOT=1'
end
ENV.delete('NATIVE_FAST_BOOT')
else
ENV.delete('NATIVE_FULL_AOT')
@@ -395,11 +471,11 @@ class Build
end
end
run_cmd 'make', *make_flags
run_cmd 'make', *make_flags.compact
run_cmd 'make', 'install'
end
err 'Build failed.' unless File.exist?(emacs_app)
fatal 'Build failed.' unless File.exist?(emacs_app)
emacs_app
end
@@ -409,8 +485,8 @@ class Build
target_dir = File.join(output_dir, build_name)
if File.exist?(target_dir)
err "Output directory #{target_dir} already exists, " \
'please delete it and try again'
fatal "Output directory #{target_dir} already exists, " \
'please delete it and try again'
end
info "Copying \"#{app_name}\" to: #{target_dir}"
@@ -488,7 +564,8 @@ class Build
'MacOS/lib/emacs/**/native-lisp'].first
if source.nil?
err 'Failed to find native-lisp cache directory for symlink creation.'
fatal 'Failed to find native-lisp cache directory for ' \
'symlink creation.'
end
end
@@ -504,7 +581,7 @@ class Build
contents_dir = File.join(app, 'Contents')
FileUtils.cd(contents_dir) do
filename = Dir['MacOS/Emacs.pdmp', 'MacOS/libexec/Emacs.pdmp'].first
err "no Emacs.pdmp file found in #{app}" unless filename
fatal "no Emacs.pdmp file found in #{app}" unless filename
info 'patching Emacs.pdmp to point at new native-lisp paths'
content = File.read(filename, mode: 'rb').gsub(
@@ -516,7 +593,7 @@ class Build
"../native-lisp/#{sanitized_eln_version}/"
)
File.open(filename, 'w') { |f| f.write(content) }
File.write(filename, content)
end
end
@@ -548,7 +625,10 @@ class Build
build = File.basename(build_dir)
parent_dir = File.dirname(build_dir)
if !File.exist?(archive_filename)
if File.exist?(archive_filename)
info "#{filename} archive exists in " \
"#{target_dir}, skipping archving."
else
info "Creating #{filename} archive in \"#{target_dir}\"..."
FileUtils.cd(parent_dir) do
cmd('tar', '-cjf', archive_filename, build)
@@ -558,9 +638,6 @@ class Build
FileUtils.rm_rf(build_dir)
end
end
else
info "#{filename} archive exists in " \
"#{target_dir}, skipping archving."
end
end
@@ -576,7 +653,7 @@ class Build
.gsub('#define HAVE_ALLOCA_H 1',
'#undef HAVE_ALLOCA_H')
File.open(filename, 'w') { |f| f.write(content) }
File.write(filename, content)
end
def meta
@@ -585,9 +662,9 @@ class Build
ref_sha = options[:git_sha] || ref
info "Fetching info for git ref: #{ref_sha}"
commit_json = github_api_get(
"/repos/#{EMACS_MIRROR_REPO}/commits/#{ref_sha}"
"/repos/#{github_src_repo}/commits/#{ref_sha}"
)
err "Failed to get commit info about: #{ref_sha}" if commit_json.nil?
fatal "Failed to get commit info about: #{ref_sha}" if commit_json.nil?
commit = JSON.parse(commit_json)
meta = {
@@ -617,31 +694,32 @@ class Build
end
def effective_version
@effective_version ||= begin
case ref
when /^emacs-26.*/
'emacs-26'
when /^emacs-27.*/
'emacs-27'
when /^emacs-28.*/
'emacs-28'
else
'emacs-29'
end
end
@effective_version ||= case ref
when /^emacs-26.*/
'emacs-26'
when /^emacs-27.*/
'emacs-27'
when /^emacs-28.*/
'emacs-28'
when /^emacs-29.*/
'emacs-29'
else
'emacs-30'
end
end
def patches(opts = {})
p = []
if %w[emacs-26 emacs-27 emacs-28 emacs-29].include?(effective_version)
if %w[emacs-26 emacs-27 emacs-28 emacs-29 emacs-30]
.include?(effective_version)
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/fix-window-role.patch"
}
end
if %w[emacs-27 emacs-28 emacs-29].include?(effective_version)
if %w[emacs-27 emacs-28 emacs-29 emacs-30].include?(effective_version)
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/system-appearance.patch"
@@ -662,11 +740,15 @@ class Build
end
end
if %w[emacs-28 emacs-29].include?(effective_version)
if options[:posix_spawn]
if %w[emacs-29 emacs-30].include?(effective_version)
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/round-undecorated-frame.patch"
}
if options[:poll]
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/posix-spawn.patch"
"patches/#{effective_version}/poll.patch"
}
end
end
@@ -711,7 +793,7 @@ class Build
end
def apply_patch(patch, target)
err "\"#{target}\" does not exist." unless File.exist?(target)
fatal "\"#{target}\" does not exist." unless File.exist?(target)
if patch[:file]
info 'Applying patch...'
@@ -739,7 +821,7 @@ class Build
end
elsif patch[:replace]
err 'Patch replace input error' unless patch[:replace].size == 3
fatal 'Patch replace input error' unless patch[:replace].size == 3
file, before, after = patch[:replace]
info "Applying patch to #{file}..."
@@ -751,7 +833,7 @@ class Build
return
end
err "\"#{file}\" does not exist in #{target}"
fatal "\"#{file}\" does not exist in #{target}"
end
f = File.open(filepath, 'rb')
@@ -764,7 +846,7 @@ class Build
return
end
err "Replacement failed in #{file}"
fatal "Replacement failed in #{file}"
end
f.reopen(filepath, 'wb').write(s)
@@ -805,11 +887,15 @@ class AbstractEmbedder
attr_reader :app
def initialize(app)
err "#{app} does not exist" unless File.exist?(app)
fatal "#{app} does not exist" unless File.exist?(app)
@app = app
end
def relative_path(path)
Pathname.new(path).relative_path_from(Pathname.new(app)).to_s
end
def invocation_dir
@invocation_dir ||= File.join(app, 'Contents', 'MacOS')
end
@@ -865,12 +951,16 @@ class CSourcesEmbedder < AbstractEmbedder
end
def embed
info 'Embedding C source files into Emacs.app for documentation purposes'
info 'Bundling C source files into Emacs.app for documentation purposes...'
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(resources_dir, 'src', rel)
target = File.join(target_dir, rel)
FileUtils.mkdir_p(File.dirname(target))
cmd('cp', '-pRL', f, target)
end
@@ -878,6 +968,8 @@ class CSourcesEmbedder < AbstractEmbedder
return if File.exist?(site_start_el_file) &&
File.read(site_start_el_file).include?(PATH_PATCH)
debug "Patching '#{relative_path(site_start_el_file)}' to allow Emacs to " \
'find bundled C sources'
File.open(site_start_el_file, 'a') do |f|
f.puts("\n#{PATH_PATCH}")
end
@@ -895,7 +987,7 @@ class LibEmbedder < AbstractEmbedder
attr_reader :extra_libs
attr_reader :relink_eln_files
def initialize(app, lib_source, extra_libs = [], relink_eln_files = true)
def initialize(app, lib_source, extra_libs = [], relink_eln_files: true)
super(app)
@lib_source = lib_source
@@ -904,7 +996,7 @@ class LibEmbedder < AbstractEmbedder
end
def embed
info 'Embedding libraries into Emacs.app'
info 'Bundling shared libraries into Emacs.app...'
binary = "#{bin}-bin" if File.exist?("#{bin}-bin")
binary ||= bin
@@ -920,7 +1012,7 @@ class LibEmbedder < AbstractEmbedder
copy_extra_libs(extra_libs, binary) if extra_libs.any?
if relink_eln_files && eln_files.any?
info "Embedding libraries for #{eln_files.size} *.eln files " \
info "Bundling shared libraries for #{eln_files.size} *.eln files " \
'within Emacs.app'
eln_files.each { |f| copy_libs(f) }
@@ -941,49 +1033,76 @@ class LibEmbedder < AbstractEmbedder
return if rpaths.include?(rpath)
while_writable(exe) do
debug "Setting rpath for '#{relative_path(exe)}' to: #{rpath}"
cmd('install_name_tool', '-add_rpath', rpath, exe)
end
end
def copy_libs(exe)
exe_file = File.basename(exe)
exe_filename = File.basename(exe)
copied_libs = []
debug "Bundling shared libraries for: #{relative_path(exe)}"
`otool -L "#{exe}"`.split("\n")[1..-1].each do |line|
# Parse otool -L output
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
next unless match && match[1].start_with?(lib_source)
next unless match
lib_filepath = match[1]
lib_filename = File.basename(lib_filepath)
# Only bundle libraries from lib_source.
next unless lib_filepath.start_with?(lib_source)
unless File.exist?(lib_filepath)
warn "-- Shared library '#{lib_filepath}' does not exist, skipping"
next
end
copied = false
while_writable(exe) do
if match[2] == exe_file
cmd('install_name_tool', '-id',
File.join('@rpath', match[2].to_s), exe)
if lib_filename == exe_filename
id_name = File.join('@rpath', lib_filename)
debug "-- Setting install name to: #{id_name}"
cmd('install_name_tool', '-id', id_name, exe)
else
cmd('install_name_tool', '-change', match[1],
File.join('@rpath', match[2].to_s), exe)
debug "-- Bundling shared library: #{lib_filepath}"
lib_target = File.join(lib_dir, lib_filename)
unless File.exist?(lib_target)
debug '-- -- Copying to: ' \
"#{relative_path(File.join(lib_dir, lib_filename))}"
FileUtils.mkdir_p(lib_dir)
cmd('cp', '-pRL', lib_filepath, lib_target)
copied_libs << lib_target
copied = true
end
change_target = File.join('@rpath', lib_filename)
debug "-- -- Relinking to: #{change_target}"
cmd('install_name_tool', '-change', lib_filepath, change_target, exe)
end
end
next if match[2] == exe_file || File.exist?(File.join(lib_dir, match[2]))
FileUtils.mkdir_p(lib_dir)
cmd('cp', '-pRL', match[1], lib_dir)
copy_libs(File.join(lib_dir, match[2].to_s))
next if lib_filename == exe_filename || !copied
end
copied_libs.each { |lib| copy_libs(lib) }
end
def copy_extra_libs(extra_libs, exe)
def copy_extra_libs(extra_libs, _exe)
extra_libs.each do |lib|
debug "Bundling extra shared library: #{lib}"
lib_file = File.basename(lib)
target = "#{lib_dir}/#{lib_file}"
unless File.exist?(target)
FileUtils.mkdir_p(lib_dir)
debug "-- Copying to: #{lib_file}"
cmd('cp', '-pRL', lib, lib_dir)
end
while_writable(target) do
cmd('install_name_tool', '-id',
File.join('@rpath', lib_file), target)
end
copy_libs(target)
end
end
@@ -1011,10 +1130,10 @@ class GccLibEmbedder < AbstractEmbedder
return
end
info 'Embedding libgccjit into Emacs.app'
info 'Bundling libgccjit into Emacs.app'
if gcc_info.lib_dir.empty?
err "No suitable GCC lib dir found in #{gcc_info.root_dir}"
fatal "No suitable GCC lib dir found in #{gcc_info.root_dir}"
end
FileUtils.mkdir_p(File.dirname(target_dir))
@@ -1029,6 +1148,7 @@ class GccLibEmbedder < AbstractEmbedder
return if File.exist?(site_start_el_file) &&
File.read(site_start_el_file).include?(env_setup)
debug 'Setting up site-start.el for self-contained native-comp Emacs.app'
File.open(site_start_el_file, 'a') do |f|
f.puts("\n#{env_setup}")
end
@@ -1175,18 +1295,18 @@ class GccInfo
end
def verify_libgccjit
err 'gcc not installed' unless Dir.exist?(root_dir)
err 'libgccjit not installed' unless Dir.exist?(libgccjit_root_dir)
fatal 'gcc not installed' unless Dir.exist?(root_dir)
fatal 'libgccjit not installed' unless Dir.exist?(libgccjit_root_dir)
if libgccjit_lib_dir&.empty?
err "Detected libgccjit (#{libgccjit_root_dir}) does not have any " \
'libgccjit.so* files. Please try reinstalling libgccjit: ' \
'brew reinstall libgccjit'
if libgccjit_lib_dir.empty?
fatal "Detected libgccjit (#{libgccjit_root_dir}) does not have any " \
'libgccjit.so* files. Please try reinstalling libgccjit: ' \
'brew reinstall libgccjit'
end
return if major_version == libgccjit_major_version
err <<~TEXT
fatal <<~TEXT
Detected GCC and libgccjit library paths do not belong to the same major
version of GCC. Detected paths:
- #{lib_dir}
@@ -1194,7 +1314,7 @@ class GccInfo
TEXT
end
def get_binding
def get_binding # rubocop:disable Naming/AccessorMethodName
binding
end
@@ -1219,10 +1339,13 @@ if __FILE__ == $PROGRAM_NAME
rsvg: true,
dbus: true,
xwidgets: true,
tree_sitter: true,
github_src_repo: nil,
github_auth: true,
dist_include: ['COPYING'],
archive: true,
archive_keep: false
archive_keep: false,
log_level: 'info'
}
begin
@@ -1254,6 +1377,12 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:xwidgets] = v
end
opts.on('--[no-]tree-sitter',
'Enable/disable tree-sitter if supported' \
'(default: enabled)') do |v|
cli_options[:tree_sitter] = v
end
opts.on('--[no-]native-comp',
'Enable/disable native-comp ' \
'(default: enabled if supported)') do |v|
@@ -1293,8 +1422,8 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:no_titlebar] = true
end
opts.on('--posix-spawn', 'Apply posix-spawn patch (default: disabled)') do
cli_options[:posix_spawn] = true
opts.on('--posix-spawn', 'Apply posix-spawn patch (deprecated)') do
warn '==> WARN: posix-spawn patch is deprecated as has no effect.'
end
opts.on('--no-frame-refocus',
@@ -1302,6 +1431,19 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:no_frame_refocus] = true
end
opts.on('--[no-]poll',
'Enable/disable experimental use of poll() instead of select() ' \
'to support > 1024 file descriptors ' \
'(default: disabled)') do |v|
cli_options[:poll] = v
end
opts.on('--github-src-repo REPO',
'Specify a GitHub repo to download source tarballs from ' \
'(default: emacs-mirror/emacs)') do |v|
cli_options[:github_src_repo] = v
end
opts.on('--[no-]github-auth',
'Make authenticated GitHub API requests if GITHUB_TOKEN ' \
'environment variable is set.' \
@@ -1342,6 +1484,11 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:archive_keep] = v
end
opts.on('--log-level LEVEL',
'Build script log level (default: info)') do |v|
cli_options[:log_level] = v
end
opts.on(
'--plan FILE',
'Follow given plan file, instead of using given git ref/sha'
@@ -1350,6 +1497,7 @@ if __FILE__ == $PROGRAM_NAME
end
end.parse!
Output.log_level = cli_options[:log_level]
work_dir = cli_options.delete(:work_dir)
Build.new(work_dir, ARGV.shift, cli_options).build
rescue Error => e