mirror of
https://github.com/jimeh/build-emacs-for-macos.git
synced 2026-02-19 13:06:38 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
8f5ae8a6c2
|
|||
|
707bc9e0d1
|
|||
|
c55bf68e61
|
|||
| 26ce446226 | |||
|
ca2d4c38f6
|
|||
|
bd81870659
|
|||
|
5cd9d1c5fa
|
|||
| 6ae14b597c | |||
|
deda28e5ad
|
|||
|
3d6caac962
|
|||
| 11de27358d | |||
|
8237aa9272
|
|||
|
3ffe83c94e
|
29
CHANGELOG.md
29
CHANGELOG.md
@@ -2,6 +2,35 @@
|
||||
|
||||
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.17](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.16...0.4.17) (2021-06-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **download:** don't use GitHub API to get tarball URL ([707bc9e](https://github.com/jimeh/build-emacs-for-macos/commit/707bc9e0d13246b7cfb8d27da859a101d4a3c166))
|
||||
|
||||
### [0.4.16](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.15...0.4.16) (2021-06-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiling:** improve portability of builds ([ca2d4c3](https://github.com/jimeh/build-emacs-for-macos/commit/ca2d4c38f69c434c77c266594104bfbf34ad5221))
|
||||
* **native_comp:** crash on launch when gcc homebrew package was not installed ([bd81870](https://github.com/jimeh/build-emacs-for-macos/commit/bd8187065928b9f79de8b14222c98f8dc34bfe5f))
|
||||
|
||||
### [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)
|
||||
|
||||
|
||||
|
||||
65
README.md
65
README.md
@@ -74,10 +74,12 @@ Options:
|
||||
--git-sha SHA Override detected git SHA of specified branch allowing builds of old commits
|
||||
--[no-]xwidgets Enable/disable XWidgets if supported (default: enabled)
|
||||
--[no-]native-comp Enable/disable native-comp (default: enabled if supported)
|
||||
--[no-]native-march Enable/disable -march=native CFLAG(default: disabled)
|
||||
--[no-]native-full-aot Enable/disable NATIVE_FULL_AOT / Ahead of Time compilation (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-]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
|
||||
```
|
||||
@@ -111,29 +113,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 +140,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 +150,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 +193,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
|
||||
|
||||
|
||||
@@ -71,9 +71,8 @@ end
|
||||
class Build
|
||||
include Output
|
||||
|
||||
EMACS_MIRROR_REPO = 'emacs-mirror/emacs'
|
||||
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
|
||||
|
||||
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
|
||||
@@ -255,7 +267,7 @@ class Build
|
||||
"-I#{File.join(gcc_info.root_dir, 'include')}",
|
||||
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
|
||||
'-O2',
|
||||
'-march=native',
|
||||
(options[:native_march] ? '-march=native' : nil),
|
||||
ENV['CFLAGS']
|
||||
].compact.join(' ')
|
||||
|
||||
@@ -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
|
||||
@@ -617,11 +652,35 @@ class LibEmbedder < AbstractEmbedder
|
||||
FileUtils.cd(File.dirname(app)) do
|
||||
copy_libs(binary)
|
||||
copy_extra_libs(extra_libs, binary) if extra_libs.any?
|
||||
if eln_files.any?
|
||||
info "Embedding libraries for #{eln_files.size} *.eln files " \
|
||||
'within Emacs.app'
|
||||
rel_path = Pathname.new(lib_dir).relative_path_from(
|
||||
Pathname.new(File.dirname(binary))
|
||||
).to_s
|
||||
eln_files.each { |f| copy_libs(f, rel_path) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def eln_files
|
||||
@eln_files ||= Dir[
|
||||
File.join(
|
||||
app, 'Contents', 'Resources', 'native-lisp', '**', '*.eln'
|
||||
),
|
||||
File.join(
|
||||
app, 'Contents', 'MacOS', 'lib', 'emacs', '**',
|
||||
'native-lisp', '**', '*.eln'
|
||||
),
|
||||
File.join(
|
||||
app, 'Contents', 'MacOS', 'libexec', 'emacs', '**',
|
||||
'eln-cache', '**', '*.eln'
|
||||
)
|
||||
]
|
||||
end
|
||||
|
||||
def copy_libs(exe, rel_path = nil)
|
||||
exe_file = File.basename(exe)
|
||||
rel_path ||= Pathname.new(lib_dir).relative_path_from(
|
||||
@@ -845,9 +904,11 @@ if __FILE__ == $PROGRAM_NAME
|
||||
cli_options = {
|
||||
work_dir: File.expand_path(__dir__),
|
||||
native_full_aot: false,
|
||||
native_march: false,
|
||||
parallel: Etc.nprocessors,
|
||||
rsvg: true,
|
||||
xwidgets: true
|
||||
xwidgets: true,
|
||||
github_auth: true
|
||||
}
|
||||
|
||||
begin
|
||||
@@ -885,6 +946,12 @@ if __FILE__ == $PROGRAM_NAME
|
||||
cli_options[:native_comp] = v
|
||||
end
|
||||
|
||||
opts.on('--[no-]native-march',
|
||||
'Enable/disable -march=native CFLAG' \
|
||||
'(default: disabled)') do |v|
|
||||
cli_options[:native_march] = v
|
||||
end
|
||||
|
||||
opts.on('--[no-]native-full-aot',
|
||||
'Enable/disable NATIVE_FULL_AOT / Ahead of Time compilation ' \
|
||||
'(default: disabled)') do |v|
|
||||
@@ -906,6 +973,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|
|
||||
|
||||
23
helper/emacs-cli.bash
Executable file
23
helper/emacs-cli.bash
Executable 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" "$@"
|
||||
Reference in New Issue
Block a user