Compare commits

..

13 Commits

Author SHA1 Message Date
5cd9d1c5fa chore(release): 0.4.15 2021-05-31 23:25:03 +01:00
6ae14b597c Merge pull request #48 from jimeh/github-auth
feat(github): perform authenticated GitHub API requests when GITHUB_TOKEN env var is set
2021-05-31 23:23:24 +01:00
deda28e5ad feat(github): perform authenticated GitHub API requests when GITHUB_TOKEN env var is set
This should let people on shared connections use the script if they
have a GitHub Personal Access Token available in the GITHUB_TOKEN
environment variable.

When making unauthenticated API requests to GitHub, requests are rate
limited to 60 requests per hour based on source IP address. Hence on
shared connections the rate limit may easily be exceeded.

When making authenticated API requests to GitHub, up to 5000 requests
per hour is allowed, based on the authenticated user rather than source
IP address.
2021-05-31 23:14:54 +01:00
3d6caac962 chore(release): 0.4.14 2021-05-22 21:09:33 +01:00
11de27358d Merge pull request #43 from jimeh/improve-cli-integration
feat(cli): add "emacs" CLI launcher script to Emacs.app/Conents/MacOS/bin
2021-05-22 20:56:41 +01:00
8237aa9272 feat(cli): add "emacs" CLI launcher script to Emacs.app/Conents/MacOS/bin
This makes setting up a "emacs" terminal command that works with the
self-contained Emacs.app bundle much simpler, as you just need to add
Emacs.app/Conents/MacOS/bin to your PATH.

For example, if you place Emacs.app in /Applications, add this to your
shell setup:

    if [ -d "/Applications/Emacs.app/Contents/MacOS/bin" ]; then
      export PATH="/Applications/Emacs.app/Contents/MacOS/bin:$PATH"
      alias emacs="emacs -nw" # Always launch "emacs" in terminal mode.
    fi

The launcher script works by figuring out it's own absolute path on
disk, even if you are using a symlink to the script, it will resolve to
correct real path. This allows it to execute the main
Emacs.app/Contents/MacOS/Emacs executable via the correct path, so it
can correctly pick up its dependencies from within the Emacs.app bundle.

Fixes #41
2021-05-22 20:55:42 +01:00
3ffe83c94e docs(native_comp): update readme to reflect recent changes to native-comp 2021-05-22 20:32:51 +01:00
9f6ec5954f chore(release): 0.4.13 2021-05-22 18:52:45 +01:00
9ea79670d8 Merge pull request #42 from jimeh/prepare-for-codesign
feat(codesign): minor internal fix to output Emacs.app bundle for compatibility with codesign
2021-05-22 18:51:09 +01:00
72e40248e1 chore(cli): remove deprecated flags and update readme usage 2021-05-22 18:33:16 +01:00
7259111478 fix(codesign): prevent "bundle format unrecognized" error from codesign
Apple's codesign CLI toolthrows a "bundle format unrecognized" error if
there are any folders within the application that contain two dots in
their name.

Hence we need to get rid of the one instance of that we end up with from
GCC, and update the native-comp patch accordingly.

As of writing, this means renaming:
Emacs.app/Contents/MacOS/lib/gcc/11/gcc/x86_64-apple-darwin20/11.1.0

To:
Emacs.app/Contents/MacOS/lib/gcc/11/gcc/x86_64-apple-darwin20/11
2021-05-20 01:55:41 +01:00
bb45cda023 fix(embed): avoid potential error caused by trying to set duplicate rpath 2021-05-20 01:55:41 +01:00
ab872202df chore: minor improvement 2021-05-20 01:55:41 +01:00
5 changed files with 178 additions and 76 deletions

View File

@@ -2,6 +2,28 @@
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.4.15](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.14...0.4.15) (2021-05-31)
### Features
* **github:** perform authenticated GitHub API requests when GITHUB_TOKEN env var is set ([deda28e](https://github.com/jimeh/build-emacs-for-macos/commit/deda28e5aded2817bcc7956f377378576372816f))
### [0.4.14](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.13...0.4.14) (2021-05-22)
### Features
* **cli:** add "emacs" CLI launcher script to Emacs.app/Conents/MacOS/bin ([8237aa9](https://github.com/jimeh/build-emacs-for-macos/commit/8237aa9272ce1d13a412b2495cbaa90df38d928b)), closes [#41](https://github.com/jimeh/build-emacs-for-macos/issues/41)
### [0.4.13](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.12...0.4.13) (2021-05-22)
### Bug Fixes
* **codesign:** prevent "bundle format unrecognized" error from codesign ([7259111](https://github.com/jimeh/build-emacs-for-macos/commit/7259111478ecb838dea9c8f50ea39eafdf47ed5a))
* **embed:** avoid potential error caused by trying to set duplicate rpath ([bb45cda](https://github.com/jimeh/build-emacs-for-macos/commit/bb45cda0231e99618571dc835348cf5c3345e277))
### [0.4.12](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.11...0.4.12) (2021-05-17)

View File

@@ -72,14 +72,15 @@ available here: https://github.com/emacs-mirror/emacs
Options:
-j, --parallel COUNT Compile using COUNT parallel processes (detected: 8)
--git-sha SHA Override detected git SHA of specified branch allowing builds of old commits
--[no-]xwidgets Enable/disable XWidgets (default: enabled if supported)
--[no-]xwidgets Enable/disable XWidgets if supported (default: enabled)
--[no-]native-comp Enable/disable native-comp (default: enabled if supported)
--[no-]native-full-aot Enable/disable NATIVE_FULL_AOT / Ahead of Time compilation (default: disabled)
--rsvg Enable SVG image support via librsvg, can yield a unstable build (default: disabled)
--[no-]rsvg Enable/disable SVG image support via librsvg (default: enabled)
--no-titlebar Apply no-titlebar patch (default: disabled)
--no-frame-refocus Apply no-frame-refocus patch (default: disabled)
--[no-]native-fast-boot DEPRECATED: use --[no-]native-full-aot instead
--[no-]launcher DEPRECATED: Launcher script is no longer used.
--[no-]github-auth Make authenticated GitHub API requests if GITHUB_TOKEN environment variable is set.(default: enabled)
--work-dir DIR Specify a working directory where tarballs, sources, and builds will be stored and worked with
--plan FILE Follow given plan file, instead of using given git ref/sha
```
Resulting applications are saved to the `builds` directory in a bzip2 compressed
@@ -111,29 +112,25 @@ All sources as downloaded as tarballs from the
to get a list of tags/branches available to install, simply check said
repository.
## Use Self-Contained Emacs.app as `emacs` CLI Tool
## Use Emacs.app as `emacs` CLI Tool
As the application bundle is self-contained, the main executable needs to be run
from within the application bundle. This means a simple symlink to
`Emacs.app/Contents/MacOS/Emacs` will not work. Instead the best approach is to
create a shell alias called `emacs` pointing to the right place.
Builds come with a custom `emacs` shell script launcher for use from the command
line. It makes sure to use the main `Emacs.app/Contents/MacOS/Emacs` executable
from the correct path, ensuring it finds all the relevant dependencies within
the Emacs.app bundle.
Personally I use something similar to this:
To use it, simply add `Emacs.app/Contents/MacOS/bin` to your `PATH`. For
example, if you place Emacs.app in `/Applications`:
```bash
if [ -f "/Applications/Emacs.app/Contents/MacOS/Emacs" ]; then
export EMACS="/Applications/Emacs.app/Contents/MacOS/Emacs"
alias emacs="$EMACS -nw"
fi
if [ -f "/Applications/Emacs.app/Contents/MacOS/bin/emacsclient" ]; then
alias emacsclient="/Applications/Emacs.app/Contents/MacOS/bin/emacsclient"
if [ -d "/Applications/Emacs.app/Contents/MacOS/bin" ]; then
export PATH="/Applications/Emacs.app/Contents/MacOS/bin:$PATH"
alias emacs="emacs -nw" # Always launch "emacs" in terminal mode.
fi
```
Setting the `EMACS` variable to the binary path seems to be a good idea, as some
tools seems to use it to figure out the path to Emacs' executable, including
[doom-emacs](https://github.com/hlissner/doom-emacs)' `doom` CLI tool.
If you want `emacs` in your terminal to launch a GUI instance of Emacs, don't
use the alias from the above example.
## Native-Comp
@@ -142,9 +139,9 @@ _Note: On 2021-04-25 the `feature/native-comp` branch was
into `master`._
The build script will automatically detect if the source tree being built
supports native-compilation, and enable it if available. You can override this
to force it on/off by passing `--native-comp` or `--no-native-comp`
respectfully.
supports native-compilation, and enable it if available. You can override the
auto-detection logic to force enable or force disable native-compilation by
passing `--native-comp` or `--no-native-comp` respectfully.
By default `NATIVE_FULL_AOT` is disabled which ensures a fast build by native
compiling as few elisp source files as possible to build Emacs itself. Any
@@ -152,32 +149,39 @@ remaining elisp files will be dynamically compiled in the background the first
time they are used.
To enable native full Ahead-of-Time compilation, pass in the `--native-full-aot`
option, which will native-compile all of Emacs' elisp as built-time. On my
option, which will native-compile all of Emacs' elisp at built-time. On my
machine it takes around 10 minutes to build Emacs.app with `NATIVE_FULL_AOT`
disabled, and around 20-25 minutes with it enabled.
### Configuration
Add the following near the top of your `early-init.el` or `init.el`:
```elisp
(setq comp-speed 2)
```
#### Native-Lisp Cache Directory
By default natively compiled `*.eln` files will be cached in
`~/.emacs.d/eln-cache/`. If you want to customize that, simply set a new path as
the first element of the `comp-eln-load-path` variable. The path string must end
with a `/`.
the first element of the `native-comp-eln-load-path` variable. The path string
must end with a `/`.
Below is an example which stores all compiled `*.eln` files in `cache/eln-cache`
within your Emacs configuration directory:
```elisp
(when (boundp 'comp-eln-load-path)
(setcar comp-eln-load-path
(when (boundp 'native-comp-eln-load-path)
(setcar native-comp-eln-load-path
(expand-file-name "cache/eln-cache/" user-emacs-directory)))
```
#### Compilation Warnings
By default any warnings encountered during async native compilation will pop up
a warnings buffer. As this tends to happen rather frequently with a lot of
packages, it can get annoying. You can disable showing these warnings by setting
`native-comp-async-report-warnings-errors` to `nil`:
```elisp
(setq native-comp-async-report-warnings-errors nil)
```
### Issues
Please see all issues with the
@@ -188,7 +192,7 @@ types of issues and or behavior you can expect.
### Known Good Commits/Builds
A list of known "good" commits which produce working builds is tracked in:
[#6 Known good commits of feature/native-comp branch](https://github.com/jimeh/build-emacs-for-macos/issues/6)
[#6 Known good commits for native-comp](https://github.com/jimeh/build-emacs-for-macos/issues/6)
## Credits

View File

@@ -71,9 +71,8 @@ end
class Build
include Output
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
EMACS_MIRROR_REPO = 'emacs-mirror/emacs'
DOWNLOAD_URL = 'https://api.github.com/repos/emacs-mirror/emacs/tarball/%s'
attr_reader :root_dir
attr_reader :source_dir
@@ -103,6 +102,7 @@ class Build
app = compile_source(@source_dir)
symlink_internals(app)
add_cli_helper(app)
LibEmbedder.new(app, brew_dir, extra_libs).embed
GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp]
@@ -161,8 +161,20 @@ class Build
info 'Downloading tarball from GitHub. This could take a while, ' \
'please be patient.'
result = run_cmd('curl', '-L', url, '-o', target)
err 'Download failed.' unless result
args = ['curl', '-L', url, '-o', target]
log_args = args.clone
if options[:github_auth] && ENV['GITHUB_TOKEN']
args = [args[0]] +
['-H', "Authorization: Token #{ENV['GITHUB_TOKEN']}"] + args[1..-1]
log_args = [log_args[0]] +
['-H', '"Authorization: Token $GITHUB_TOKEN"'] +
log_args[1..-1]
end
out "CMD: #{log_args.join(' ')}"
system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}")
target
end
@@ -373,6 +385,18 @@ class Build
end
end
def add_cli_helper(app)
source = File.join(__dir__, 'helper', 'emacs-cli.bash')
target = File.join(app, 'Contents', 'MacOS', 'bin', 'emacs')
dir = File.dirname(target)
info "Adding \"emacs\" CLI helper to #{dir}"
FileUtils.mkdir_p(dir)
FileUtils.cp(source, target)
FileUtils.chmod('+w', target)
end
def archive_filename
return @archive_filename if @archive_filename
@@ -429,8 +453,9 @@ class Build
ref_sha = options[:git_sha] || ref
info "Fetching info for git ref: #{ref_sha}"
url = format(LATEST_URL, ref_sha)
commit_json = http_get(url)
commit_json = github_api_get(
"/repos/#{EMACS_MIRROR_REPO}/commits/#{ref_sha}"
)
err "Failed to get commit info about: #{ref_sha}" if commit_json.nil?
commit = JSON.parse(commit_json)
@@ -443,8 +468,18 @@ class Build
@meta = meta
end
def http_get(url)
response = Net::HTTP.get_response(URI.parse(url))
def github_api_get(uri)
uri = URI.join('https://api.github.com/', uri)
http = Net::HTTP.new(uri.hostname, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Get.new(uri)
if options[:github_auth] && ENV['GITHUB_TOKEN']
request['Authorization'] = "Token #{ENV['GITHUB_TOKEN']}"
end
response = http.request(request)
return unless response.code == '200'
response.body
@@ -585,7 +620,7 @@ class AbstractEmbedder
private
def invocation_dir
File.join(app, 'Contents/MacOS')
File.join(app, 'Contents', 'MacOS')
end
def bin
@@ -628,9 +663,14 @@ class LibEmbedder < AbstractEmbedder
Pathname.new(File.dirname(exe))
).to_s
while_writable(exe) do
system('install_name_tool', '-add_rpath',
File.join('@executable_path', rel_path), exe)
rpath = File.join('@executable_path', rel_path)
rpaths = `otool -l "#{exe}" | grep -A 2 'cmd LC_RPATH' | grep 'path'`
unless rpaths.include?(rpath)
while_writable(exe) do
system('install_name_tool', '-add_rpath',
File.join('@executable_path', rel_path), exe)
end
end
`otool -L "#{exe}"`.split("\n")[1..-1].each do |line|
@@ -708,7 +748,9 @@ class GccLibEmbedder < AbstractEmbedder
FileUtils.mkdir_p(File.dirname(target_dir))
FileUtils.cp_r(source_dir, target_dir)
FileUtils.rm(Dir[File.join(target_dir, '**/.DS_Store')], force: true)
FileUtils.rm(Dir[File.join(target_dir, '**', '.DS_Store')], force: true)
FileUtils.chmod_R('u+w', target_dir)
FileUtils.mv(source_darwin_dir, target_darwin_dir)
end
private
@@ -721,9 +763,21 @@ class GccLibEmbedder < AbstractEmbedder
File.join(invocation_dir, gcc_info.relative_lib_dir)
end
def source_darwin_dir
File.join(invocation_dir, gcc_info.relative_darwin_lib_dir)
end
def target_darwin_dir
File.join(invocation_dir, gcc_info.sanitized_relative_darwin_lib_dir)
end
def source_dir
gcc_info.lib_dir
end
def relative_dir(path, root)
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
end
end
class GccInfo
@@ -763,6 +817,17 @@ class GccInfo
@relative_darwin_lib_dir ||= relative_dir(darwin_lib_dir, root_dir)
end
# Sanitize folder name with full "MAJOR.MINOR.PATCH" version number to just
# the MAJOR version. Apple's codesign CLI tool throws a "bundle format
# unrecognized" error if there are any folders with two dots in their name
# within the Emacs.app application bundle.
def sanitized_relative_darwin_lib_dir
@sanitized_relative_darwin_lib_dir ||= File.join(
File.dirname(relative_darwin_lib_dir),
File.basename(relative_darwin_lib_dir).split('.').first
)
end
def libgccjit_root_dir
@libgccjit_root_dir ||= `brew --prefix libgccjit`.chomp
end
@@ -807,10 +872,7 @@ class GccInfo
private
def relative_dir(path, root)
root += '/' unless root[-1] == '/'
return if path[0..root.size - 1] != root
path[root.size..-1]
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
end
end
@@ -820,7 +882,8 @@ if __FILE__ == $PROGRAM_NAME
native_full_aot: false,
parallel: Etc.nprocessors,
rsvg: true,
xwidgets: true
xwidgets: true,
github_auth: true
}
begin
@@ -836,7 +899,7 @@ if __FILE__ == $PROGRAM_NAME
opts.on('-j', '--parallel COUNT',
'Compile using COUNT parallel processes ' \
"(default: #{cli_options[:parallel]})") do |v|
"(detected: #{cli_options[:parallel]})") do |v|
cli_options[:parallel] = v
end
@@ -879,6 +942,13 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:no_frame_refocus] = true
end
opts.on('--[no-]github-auth',
'Make authenticated GitHub API requests if GITHUB_TOKEN ' \
'environment variable is set.' \
'(default: enabled)') do |v|
cli_options[:github_auth] = v
end
opts.on('--work-dir DIR',
'Specify a working directory where tarballs, sources, and ' \
'builds will be stored and worked with') do |v|
@@ -891,23 +961,6 @@ if __FILE__ == $PROGRAM_NAME
) do |v|
cli_options[:plan] = v
end
opts.on('--[no-]native-fast-boot',
'DEPRECATED: use --[no-]native-full-aot instead') do |v|
if v
raise Error, '--native-fast-boot option is deprecated, ' \
'use --no-native-full-aot instead'
else
raise Error, '--no-native-fast-boot option is deprecated, ' \
'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!
work_dir = cli_options.delete(:work_dir)

23
helper/emacs-cli.bash Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
resolve_link() {
"$(type -p greadlink readlink | head -1)" "$1"
}
abs_dirname() {
local path="$1"
local name
local cwd
cwd="$(pwd)"
while [ -n "$path" ]; do
cd "${path%/*}" || exit 1
name="${path##*/}"
path="$(resolve_link "$name" || true)"
done
pwd
cd "$cwd" || exit 1
}
exec "$(dirname "$(abs_dirname "$0")")/Emacs" "$@"

View File

@@ -1,10 +1,10 @@
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 4036080976..2ff8dbd74c 100644
index 8c638312b0..87af889ef4 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -4079,6 +4079,52 @@ of (commands) to run simultaneously."
@@ -4215,6 +4215,52 @@ native-compile-async
(let ((load (not (not load))))
(native--compile-async paths recursively load selector)))
(native--compile-async files recursively load selector)))
+;;;###autoload
+(defun native-compile-setup-environment-variables (&rest _args)
@@ -19,7 +19,7 @@ index 4036080976..2ff8dbd74c 100644
+ "<%= relative_lib_dir %>"
+ invocation-directory))
+ (darwin-dir (expand-file-name
+ "<%= relative_darwin_lib_dir %>"
+ "<%= sanitized_relative_darwin_lib_dir %>"
+ invocation-directory))
+ (lib-paths (list)))
+
@@ -54,4 +54,4 @@ index 4036080976..2ff8dbd74c 100644
+
(provide 'comp)
;;; comp.el ends here
;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln