Compare commits

...

4 Commits
0.2.0 ... 0.3.0

Author SHA1 Message Date
09e67381cb chore(release): 0.3.0 2020-09-22 20:29:06 +01:00
d21ccad3e4 docs(readme): update custom eln cache location instructions
Recent builds seem to pre-allocate empty `*.eln.tmp` files rather than
empty `*.eln` files. So the issue of empty `*.eln` files preventing
Emacs from starting should no longer be an issue.

I'm leaving #3 open for now, in case anyone is using older git SHAs from
the list of known good commits in #6.
2020-09-22 20:28:49 +01:00
036d2a82d9 Merge pull request #15 from jimeh/setup-library-path-with-elisp
feat(native_comp)!: use elisp patch instead of launcher script to set LIBRARY_PATH
2020-09-22 20:06:23 +01:00
111cb64993 feat(native_comp)!: use elisp patch instead of launcher script to set LIBRARY_PATH
Replace the launcher script with a emacs-lisp patch to `comp.el` which
sets the `LIBRARY_PATH` environment variable to point at the embedded
GCC/libgccjit.

This fixes issues related to the launcher script on macOS 10.15 and
later.

Fixes #14
BREAKING CHANGE: `--[no-]launcher` option is deprecated, as launcher script is no longer used.
2020-09-22 20:03:17 +01:00
5 changed files with 79 additions and 157 deletions

View File

@@ -2,6 +2,17 @@
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.3.0](https://github.com/jimeh/build-emacs-for-macos/compare/0.2.0...0.3.0) (2020-09-22)
### ⚠ BREAKING CHANGES
* **native_comp:** `--[no-]launcher` option is deprecated, as launcher script is no longer used.
### Features
* **native_comp:** use elisp patch instead of launcher script to set LIBRARY_PATH ([111cb64](https://github.com/jimeh/build-emacs-for-macos/commit/111cb6499368d14853a5927d38a43fc5e2f759f4)), closes [#14](https://github.com/jimeh/build-emacs-for-macos/issues/14)
## [0.2.0](https://github.com/jimeh/build-emacs-for-macos/compare/0.1.1...0.2.0) (2020-09-20)

View File

@@ -160,26 +160,13 @@ By default natively compiled `*.eln` files will be cached in
the first element of the `comp-eln-load-path` variable. The path string must end
with a `/`.
Also it seems somewhat common that some `*.eln` files are left behind with a
zero-byte file size if Emacs is quit while async native compilation is in
progress. Such empty files causes errors on startup, and needs to be deleted.
Below is an example which stores all compiled `*.eln` files in `cache/eln-cache`
within your Emacs configuration directory, and also deletes any `*.eln` files in
said directory which have a file size of zero bytes:
within your Emacs configuration directory:
```elisp
(when (boundp 'comp-eln-load-path)
(let ((eln-cache-dir (expand-file-name "cache/eln-cache/"
user-emacs-directory))
(find-exec (executable-find "find")))
(setcar comp-eln-load-path eln-cache-dir)
;; Quitting emacs while native compilation in progress can leave zero byte
;; sized *.eln files behind. Hence delete such files during startup.
(when find-exec
(call-process find-exec nil nil nil eln-cache-dir
"-name" "*.eln" "-size" "0" "-delete" "-or"
"-name" "*.eln.tmp" "-size" "0" "-delete"))))
(setcar comp-eln-load-path
(expand-file-name "cache/eln-cache/" user-emacs-directory)))
```
### Issues

View File

@@ -72,7 +72,6 @@ class Build
DOWNLOAD_URL = 'https://github.com/emacs-mirror/emacs/tarball/%s'
LATEST_URL = 'https://api.github.com/repos/emacs-mirror/emacs/commits/%s'
NATIVE_COMP_REF_REGEXP = %r{^feature/native-comp}.freeze
LAUNCHER_TEMPLATE = './launcher.bash.erb'
attr_reader :root_dir
attr_reader :source_dir
@@ -96,16 +95,11 @@ class Build
autogen
detect_native_comp if options[:native_comp].nil?
if options[:native_comp] && options[:launcher].nil?
options[:launcher] = true
end
app = compile_source(@source_dir)
symlink_internals(app)
LibEmbedder.new(app, brew_dir, extra_libs).embed
LibGccJitEmbedder.new(app, gcc_dir).embed if options[:native_comp]
LauncherEmbedder.new(app, LAUNCHER_TEMPLATE).embed if options[:launcher]
archive_app(app)
end
@@ -256,6 +250,8 @@ class Build
apply_native_comp_macos_fixes
end
apply_native_comp_env_setup_patch(source)
ENV['CFLAGS'] = [
"-I#{gcc_dir}/include",
'-O2',
@@ -426,6 +422,17 @@ class Build
system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}")
end
def apply_native_comp_env_setup_patch(source)
term = 'native-compile-setup-environment-variables'
file = 'lisp/emacs-lisp/comp.el'
return if `grep '#{term}' '#{file}'`.strip.size.positive?
apply_patch(
{ file: "#{__dir__}/patches/native-comp-env-setup.patch" },
source
)
end
def apply_native_comp_macos_fixes
filename = 'Makefile.in'
pattern = /^src: Makefile\n(.*BIN_DESTDIR.*)\nblessmail: Makefile src\n/m
@@ -521,7 +528,10 @@ class Build
def apply_patch(patch, target)
err "\"#{target}\" does not exist." unless File.exist?(target)
if patch[:url]
if patch[:file]
info 'Applying patch...'
FileUtils.cd(target) { run_cmd('patch', '-f', '-p1', '-i', patch[:file]) }
elsif patch[:url]
patch_dir = "#{target}/macos_patches"
run_cmd('mkdir', '-p', patch_dir)
@@ -535,8 +545,7 @@ class Build
info "Downloading patch: #{patch[:url]}"
run_cmd('curl', '-L#', patch[:url], '-o', patch_file)
info 'Applying patch...'
FileUtils.cd(target) { run_cmd('patch', '-f', '-p1', '-i', patch_file) }
apply_patch({ file: patch_file }, target)
elsif patch[:replace]
err 'Patch replace input error' unless patch[:replace].size == 3
@@ -739,67 +748,6 @@ class LibGccJitEmbedder < AbstractEmbedder
end
end
class LauncherEmbedder < AbstractEmbedder
attr_reader :template
def initialize(app, template)
super(app)
@template = template
end
def embed
if embedded?
info 'Launcher script already embedded in Emacs.app'
return
end
info 'Embedding launcher script into Emacs.app'
unless File.exist?("#{bin}#{bin_suffix}")
FileUtils.mv(bin, "#{bin}#{bin_suffix}")
end
unless File.exist?("#{bin}#{bin_suffix}#{dump_ext}")
FileUtils.mv("#{bin}#{dump_ext}", "#{bin}#{bin_suffix}#{dump_ext}")
end
unless File.exist?(bin)
File.write(bin, launcher)
File.chmod(0o775, bin)
end
end
private
def bin_suffix
'-bin'
end
def dump_ext
'.pdmp'
end
def embedded?
File.exist?(bin) &&
File.exist?("#{bin}#{bin_suffix}") &&
File.exist?("#{bin}#{bin_suffix}#{dump_ext}")
end
def launcher
@launcher ||= ERB.new(File.read(template)).result(binding)
end
def library_paths
@library_paths ||= Dir[
"#{lib_dir}/gcc/*",
"#{lib_dir}/gcc/*/gcc/*apple-darwin*/*"
].map do |p|
p.gsub(/^#{Regexp.escape(lib_dir + '/')}/, '')
end.sort_by { |p| [p.size, p] }
end
end
if __FILE__ == $PROGRAM_NAME
cli_options = {
macos_fixes: true,
@@ -855,12 +803,6 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:macos_fixes] = v
end
opts.on('--[no-]launcher',
'Enable/disable embedded launcher script ' \
'(default: enabled if native-comp is enabled)') do |v|
cli_options[:launcher] = v
end
opts.on('--rsvg', 'Enable SVG image support via librsvg, ' \
'can yield a unstable build (default: disabled)') do
cli_options[:rsvg] = true
@@ -885,6 +827,12 @@ if __FILE__ == $PROGRAM_NAME
'use --native-full-aot instead'
end
end
opts.on('--[no-]launcher',
'DEPRECATED: Launcher script is no longer used.') do |_|
raise Error, '--[no-]launcher option is deprecated, launcher ' \
'script is no longer used.'
end
end.parse!
Build.new(File.expand_path(__dir__), ARGV.shift, cli_options).build

View File

@@ -1,65 +0,0 @@
#!/bin/bash
# This launcher script is not part of Emacs proper. It is from the
# build-emacs-for-macos project (https://github.com/jimeh/build-emacs-for-macos)
# and helps facilitate proper startup of Emacs with environment varibales set as
# needed.
#
# Licensed under CC0 1.0 Universal:
# https://creativecommons.org/publicdomain/zero/1.0/
#
set -e
resolve_link() {
local file="$1"
while [ -L "$file" ]; do
file="$(readlink "$file")"
done
echo "$file"
}
realname() {
local path="$1"
local resolved
local cwd
cwd="$(pwd)"
resolved="$(resolve_link "$path")"
cd "$(dirname "$resolved")"
echo "$(pwd)/$(basename "$resolved")"
cd "$cwd"
}
join() {
local IFS="$1"
local parts=()
shift
for arg in "$@"; do
if [ "$arg" != "" ]; then
parts+=("$arg")
fi
done
echo "${parts[*]}"
}
DIR="$(dirname "$(realname "$0")")"
BIN="${DIR}/Emacs<%= bin_suffix %>"
export PATH="${DIR}/bin:${DIR}/libexec:${PATH}"
<% if library_paths.any? %>
LIB_PATHS=(
'<%= library_paths.map { |p| p.gsub('\'', "\"'\"") }.join("'\n '") %>'
)
for lib in "${LIB_PATHS[@]}"; do
if [ -d "${DIR}/<%= lib_dir_name %>/${lib}" ]; then
libs="$(join : "$libs" "${DIR}/<%= lib_dir_name %>/${lib}")"
fi
done
LIBRARY_PATH="$(join : "$libs" "$LIBRARY_PATH")"
export LIBRARY_PATH
<% end %>
exec "$BIN" "$@"

View File

@@ -0,0 +1,41 @@
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 25e2de9..14ee6dc 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -2801,6 +2801,36 @@ queued with LOAD %"
(comp-run-async-workers)
(message "Compilation started."))))
+;;;###autoload
+(defun native-compile-setup-environment-variables (&rest _args)
+ "Ensure LIBRARY_PATH is set correctly when libgccjit is bundled."
+ (when (and (eq system-type 'darwin)
+ (string-match-p "\.app\/Contents\/MacOS\/?$"
+ invocation-directory))
+ (let* ((library-path-env (getenv "LIBRARY_PATH"))
+ (gcc-dir (car (file-expand-wildcards
+ (concat invocation-directory "lib-*/gcc/*"))))
+ (gcc-darwin-dir (car (file-expand-wildcards
+ (concat gcc-dir "/gcc/*apple-darwin*/*"))))
+ (lib-paths (append
+ (list gcc-dir gcc-darwin-dir)
+ (if library-path-env (list library-path-env) (list)))))
+
+ (when (and gcc-dir gcc-darwin-dir)
+ (setenv "LIBRARY_PATH" (mapconcat 'identity lib-paths ":")))))
+
+ ;; Remove advice, as it only needs to run once.
+ (advice-remove 'native-compile
+ 'native-compile-setup-environment-variables)
+ (advice-remove 'native-compile-async
+ 'native-compile-setup-environment-variables))
+
+;; Ensure environment setup runs before any native compilation.
+(advice-add 'native-compile :before
+ 'native-compile-setup-environment-variables)
+(advice-add 'native-compile-async :before
+ 'native-compile-setup-environment-variables)
+
(provide 'comp)
;;; comp.el ends here