Compare commits

..

55 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
2d1c5d47d9 chore(release): 0.4.12 2021-05-17 23:14:50 +01:00
30a71c423e Merge pull request #40 from jimeh/fix-svg
fix(svg): fix SVG rendering crash and enable SVG support by default
2021-05-17 23:12:44 +01:00
5c48445397 chore(cli): improve CLI help output 2021-05-17 23:12:12 +01:00
bf7c4d5deb fix(svg): enable SVG by default via librsvg 2021-05-17 23:12:12 +01:00
3ffeb4854c chore(shared-libraries): add @executable_path/lib to @rpath for good measure 2021-05-17 23:12:12 +01:00
0a22d8393c fix(shared-libraries): stop aggressive dylib re-linking
This seems to be the cause of SVG rendering crashing, as it re-links
libiconv.2.dylib from /usr/lib/libiconv.2.dylib to
@executable_path/lib/lib/libiconv.2.dylib within libintl.8.dylib. When
this re-linking does not happen, SVG rendering works without crashing
Emacs.

Some further testing is needed by installing brew dependencies by
building them from source, in an attempt to get various libraries all
linking to homebrew-built versions, to get as many shared libraries as
possible embedded into the application bundle.

Fixes #12
2021-05-17 23:11:51 +01:00
ac8348323d chore(release): 0.4.11 2021-05-08 19:56:42 +01:00
59f52b65ee Merge pull request #39 from jimeh/emacs-builds
feat(builds): prepare for automated builds in jimeh/emacs-builds repo
2021-05-08 19:51:26 +01:00
81a96f4d60 chore(builds): remove github-release tool
This now lives in the jimeh/emacs-builds repo, which focuses on building
and publishing binary releases, using the build-emacs-for-macos script.
2021-05-08 19:10:46 +01:00
1df39fafe6 feat(builds): update build script for new plan.yml format 2021-05-08 19:07:13 +01:00
14a8d1aaaf chore(release): enable full native-compilation AoT 2021-05-07 09:15:14 +01:00
272a3000a1 fix(release): attempt to fix issue with talking to GitHub API 2021-05-07 01:12:57 +01:00
d684cf560f ci(build): fix typo 2021-05-06 23:39:16 +01:00
ea189a6713 Merge pull request #38 from jimeh/automatic-builds
feat(release): automatic builds
2021-05-06 23:37:20 +01:00
63289216d7 feat(release): initial attempt at providing automatic builds 2021-05-06 23:36:12 +01:00
2054c8c0aa chore(release): 0.4.10 2021-04-26 00:07:30 +01:00
ca09d1a95f docs(readme): update readme about native-comp being merged to master 2021-04-26 00:07:07 +01:00
f1e60e31d9 chore(makefile): add next-version target to preview new-version 2021-04-25 23:09:18 +01:00
8d197aea73 chore: ensure file mode is restored in case of error 2021-04-25 23:07:54 +01:00
844df73c8f fix(cli): correctly default to master branch if no git ref is given
Previously it would build master, but not include "master" in the
final output archive's file name.
2021-04-25 23:04:03 +01:00
f1fc68c8f5 chore(release): 0.4.9 2021-04-08 12:03:41 +01:00
e19a6a7bc2 fix(cli): default to "master" if no git ref is given
Fixes #35
2021-04-08 12:02:45 +01:00
1000999eb2 fix(native_comp): skip symlink creation for recent builds which do not need symlinks
Recent builds places the native-lisp cache folder within
Contents/Resources on macOS, and correctly deals with finding them. This
means the Contents/lisp and Contents/native-lisp symlinks are no longer
needed.

Hence we skip their creation altogether if we find any
Contents/Resources/native-lisp/**/*.eln files.
2021-04-08 11:54:01 +01:00
a75047fb3a chore(release): 0.4.8 2021-02-27 23:09:58 +00:00
a1641946e4 chore(native_comp): don't set full AOT env vars if not using native-comp 2021-02-27 23:08:15 +00:00
581594da3c fix(native_comp): add support for new --with-native-compilation flag 2021-02-27 23:07:22 +00:00
bdad382e7f chore(release): 0.4.7 2021-02-21 15:24:31 +00:00
e25ceaa7e2 fix(native_comp): add libgccjit include dir during build stage
Also used existing `CFLAGS` and `LDFLAGS` environment variable values,
so a user can easily set these when running the build script to add more
paths. Previously they were set to explicit values ignoring any existing
value.

This might help resolve issues where libgccjit.h is not found as
reported in issue #20. Though I have not been able to reproduce this
myself, it seems adding the libgccjit's include dir has solved the issue
for some.
2021-02-21 15:22:07 +00:00
03ae8750b8 chore(release): 0.4.6 2021-02-15 11:43:58 +00:00
269dbdb1dd chore(build): use File.join wherever relevant
Ensures paths are correctly joined and no double and/or missing slash
errors can occur.
2021-02-15 11:42:49 +00:00
713c970da4 Merge pull request #30 from jimeh/improve-native-comp-env-setup-patch
fix(native_comp): improve env setup patch fixing potential issues
2021-02-15 11:41:52 +00:00
dca023daec fix(native_comp): improve env setup patch fixing potential issues
The old patch would dynamically glob within
Emacs.app/Contents/MacOS/lib/gcc using the full absolute path to
Emacs.app. If there are obsure characters like "[]" and others in the
absolute path, it can cause glob search within the
native-compile-setup-environment-variables function to fail, in turn
preventing native-comp from working.

The fix is to hard-code the relative paths from Emacs'
invocation-directory (**/Emacs.app/Contents/MacOS) into the environment
setup function itself, making it very simple and effectively just
joining a few strings and setting an environment variable.

It did require a little bit of cleanup and better organization of the
GCC/libgccjit releated code in the build script, creating a new GccInfo
class which is the central place for determining various paths and
information about GCC and libgccjit which the build will be using.
2021-02-15 09:49:47 +00:00
e56c26d06f docs(readme): update status section 2021-01-15 02:01:13 +00:00
b2860f22c3 chore(deps): add rubocop-daemon and solargraph to Gemfile 2021-01-15 02:00:46 +00:00
d1c5e7afb1 chore(release): 0.4.5 2021-01-06 20:32:30 +00:00
ab55f5421c fix(cli): remove defunct --[no-]native-comp-macos-fixes option
The underlying patching code was removed in v0.4.1 (commit
70bf6b05d5), as it was no longer needed,
but the related CLI flag and README info was mistakenly left in place.
2021-01-06 20:31:31 +00:00
eb09d5fa49 chore(release): 0.4.4 2021-01-02 14:01:37 +00:00
a47d3e0c6a fix(deps): add autoconf to Brewfile
On a fresh install of Big Sur with only the Xcode CLI tools installed,
autoconf is not available. Hence it needs to be installed from homebrew
instead.
2021-01-02 14:00:49 +00:00
5a61a72a73 chore(release): 0.4.3 2020-12-28 11:47:11 +00:00
9cdf67e71b Merge pull request #26 from jimeh/fix-big-sur
fix(big-sur): resolve issues with building and native-comp on Big Sur
2020-12-28 11:42:45 +00:00
946856e9c2 fix(big-sur): add Xcode CLI tools lib directory to runtime LIBRARY_PATH 2020-12-25 15:59:53 +00:00
claford-v-lawrence
2247158051 fix(big-sur): added support for building on Big Sur
Curtsy of https://apple.stackexchange.com/questions/408999/gfortran-compiler-error-on-mac-os-big-sur
2020-12-25 15:59:47 +00:00
8 changed files with 548 additions and 269 deletions

View File

@@ -1,5 +1,6 @@
# frozen_string_literal: true
brew 'autoconf'
brew 'coreutils'
brew 'curl'
brew 'expat'

View File

@@ -2,6 +2,107 @@
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)
### Bug Fixes
* **shared-libraries:** stop aggressive dylib re-linking ([0a22d83](https://github.com/jimeh/build-emacs-for-macos/commit/0a22d8393c53305354c4c6d8e784e7d59caa039a)), closes [#12](https://github.com/jimeh/build-emacs-for-macos/issues/12)
* **svg:** enable SVG by default via librsvg ([bf7c4d5](https://github.com/jimeh/build-emacs-for-macos/commit/bf7c4d5debf32980dbbabc1ea99b58b266390011))
### [0.4.11](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.10...0.4.11) (2021-05-08)
### Features
* **builds:** update build script for new plan.yml format ([1df39fa](https://github.com/jimeh/build-emacs-for-macos/commit/1df39fafe62ada385aa1d92e6b7f591c16c0a80c))
* **release:** initial attempt at providing automatic builds ([6328921](https://github.com/jimeh/build-emacs-for-macos/commit/63289216d70e496d664a7e3078dea5a82eb8f65d))
### Bug Fixes
* **release:** attempt to fix issue with talking to GitHub API ([272a300](https://github.com/jimeh/build-emacs-for-macos/commit/272a3000a1f96d8f131e684736127b923513a205))
### [0.4.10](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.9...0.4.10) (2021-04-25)
### Bug Fixes
* **cli:** correctly default to master branch if no git ref is given ([844df73](https://github.com/jimeh/build-emacs-for-macos/commit/844df73c8fa8440e657f7900ec89cdedb7c4c312))
### [0.4.9](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.8...0.4.9) (2021-04-08)
### Bug Fixes
* **cli:** default to "master" if no git ref is given ([e19a6a7](https://github.com/jimeh/build-emacs-for-macos/commit/e19a6a7bc24379292ee06ae4c805b8c5365f2d97)), closes [#35](https://github.com/jimeh/build-emacs-for-macos/issues/35)
* **native_comp:** skip symlink creation for recent builds which do not need symlinks ([1000999](https://github.com/jimeh/build-emacs-for-macos/commit/1000999eb2673dc207a390ff3f902b9987b99173))
### [0.4.8](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.7...0.4.8) (2021-02-27)
### Bug Fixes
* **native_comp:** add support for new --with-native-compilation flag ([581594d](https://github.com/jimeh/build-emacs-for-macos/commit/581594da3cfbf1dd2fa28e91710b767e21ff75d2))
### [0.4.7](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.6...0.4.7) (2021-02-21)
### Bug Fixes
* **native_comp:** add libgccjit include dir during build stage ([e25ceaa](https://github.com/jimeh/build-emacs-for-macos/commit/e25ceaa7e25b0e1b9947401597845b5ba43e6cd1)), closes [#20](https://github.com/jimeh/build-emacs-for-macos/issues/20)
### [0.4.6](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.5...0.4.6) (2021-02-15)
### Bug Fixes
* **native_comp:** improve env setup patch fixing potential issues ([dca023d](https://github.com/jimeh/build-emacs-for-macos/commit/dca023daecd8704f197cbc391380aa194bc47d62))
### [0.4.5](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.4...0.4.5) (2021-01-06)
### Bug Fixes
* **cli:** remove defunct --[no-]native-comp-macos-fixes option ([ab55f54](https://github.com/jimeh/build-emacs-for-macos/commit/ab55f5421c81dc629e487bf4b8bb402657cb1bc4))
### [0.4.4](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.3...0.4.4) (2021-01-02)
### Bug Fixes
* **deps:** add autoconf to Brewfile ([a47d3e0](https://github.com/jimeh/build-emacs-for-macos/commit/a47d3e0c6a8ea8161a3bad0eafdac2401cf53129))
### [0.4.3](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.2...0.4.3) (2020-12-28)
### Bug Fixes
* **big-sur:** add Xcode CLI tools lib directory to runtime LIBRARY_PATH ([946856e](https://github.com/jimeh/build-emacs-for-macos/commit/946856e9c242d4a6fb5f839d8cae0acfafecdfc6))
* **big-sur:** added support for building on Big Sur ([2247158](https://github.com/jimeh/build-emacs-for-macos/commit/2247158051d0f59933569b6974b2b5269f13c79e))
### [0.4.2](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.1...0.4.2) (2020-12-09)

View File

@@ -5,4 +5,6 @@ source 'http://rubygems.org/'
group :development do
gem 'byebug'
gem 'rubocop'
gem 'rubocop-daemon'
gem 'solargraph', '~> 0.39.17'
end

View File

@@ -1,9 +1,12 @@
.PHONY: new-version
new-version:
$(if $(shell which npx),,\
$(error No npx found in PATH, please install NodeJS))
$(if $(shell which standard-version),,\
$(error No standard-version found in PATH, install with: \
npm install -g standard-version))
new-version: check-npx
npx standard-version
.PHONY: next-version
next-version: check-npx
npx standard-version --dry-run
.PHONY: check-npx
check-npx:
$(if $(shell which npx),,\
$(error No npx execuable found in PATH, please install NodeJS))

111
README.md
View File

@@ -1,7 +1,8 @@
# build-emacs-for-macos
My personal hacked together script for building a completely self-contained
Emacs.app application on macOS, from any git branch, tag, or ref.
Emacs.app application on macOS, from any git branch, tag, or ref. With support
for native-compilation.
Use this script at your own risk.
@@ -18,7 +19,7 @@ Use this script at your own risk.
## Status
As of writing (2020-10-04) it works for me on my machine. Your luck may vary.
As of writing (2021-04-25) it works for me on my machine. Your luck may vary.
I have successfully built:
@@ -29,8 +30,8 @@ I have successfully built:
For reference, my machine is:
- 13-inch MacBook Pro (2020), 10th-gen 2.3 GHz Quad-Core Intel Core i7 (4c/8t)
- macOS 10.15.6 (19G2021)
- Xcode 12.0
- macOS Big Sur 11.2.3 (20D91)
- Xcode 12.4 (12D4e)
## Limitations
@@ -71,16 +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)
--[no-]native-comp-macos-fixes
Enable/disable fix based on feature/native-comp-macos-fixes branch (default: enabled if native-comp supported)
--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
@@ -94,8 +94,8 @@ trash the corresponding directory from the `sources` directory.
### Examples
To download a tarball of the `master` branch (Emacs 28.x as of writing) and
build Emacs.app from it:
To download a tarball of the `master` branch (Emacs 28.x with native-compilation
as of writing) and build Emacs.app from it:
```
./build-emacs-for-macos
@@ -112,77 +112,76 @@ 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
Building a Emacs.app with native-comp support
([gccemacs](https://akrl.sdf.org/gccemacs.html)) from the `feature/native-comp`
branch is now supported without much hassle thanks to the newly released
`libgccjit` Homebrew formula.
_Note: On 2021-04-25 the `feature/native-comp` branch was
[merged](http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=289000eee729689b0cf362a21baa40ac7f9506f6)
into `master`._
Changes from the `feature/native-comp-macos-fixes` branch are also applied
through a custom patch process which should be more future-proof compared to a
regular git diff patch.
To build a Emacs.app with native compilation enabled, simply run:
```
./build-emacs-for-macos feature/native-comp
```
The build script will automatically detect if the source tree being built
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 lisp source files as possible to build the app. Any remaining
lisp files will be dynamically compiled in the background the first time you use
them. To enable native full AoT, pass in the `--native-full-aot` option.
compiling as few elisp source files as possible to build Emacs itself. Any
remaining elisp files will be dynamically compiled in the background the first
time they are used.
On my machine it takes around 10 minutes to build Emacs.app with
`NATIVE_FULL_AOT` disabled. With it enabled it takes around 20-25 minutes.
To enable native full Ahead-of-Time compilation, pass in the `--native-full-aot`
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
@@ -193,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

@@ -10,7 +10,9 @@ require 'json'
require 'net/http'
require 'optparse'
require 'pathname'
require 'time'
require 'uri'
require 'yaml'
class Error < StandardError; end
@@ -21,9 +23,9 @@ module Output
def out(msg, newline: true)
if newline
puts "==> #{msg}"
warn "==> #{msg}"
else
print "==> #{msg}"
STDERR.print "==> #{msg}"
end
end
@@ -69,24 +71,27 @@ 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
attr_reader :ref
attr_reader :options
attr_reader :gcc_info
def initialize(root_dir, ref = nil, options = {})
@root_dir = root_dir
@ref = ref
@ref = ref || 'master'
@options = options
@gcc_info = GccInfo.new
end
def build
load_plan(options[:plan]) if options[:plan]
unless meta[:sha] && meta[:date]
err 'Failed to get commit info from GitHub API.'
err 'Failed to get commit info from GitHub.'
end
tarball = download_tarball(meta[:sha])
@@ -97,15 +102,27 @@ 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_dir).embed if options[:native_comp]
GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp]
archive_app(app)
end
private
def load_plan(filename)
plan = YAML.safe_load(File.read(filename), [:Time])
@meta = {
sha: plan.dig('commit', 'sha'),
ref: plan.dig('commit', 'ref'),
date: plan.dig('commit', 'date')
}
@archive_filename = plan['archive']
end
def tarballs_dir
@tarballs_dir ||= File.join(root_dir, 'tarballs')
end
@@ -122,19 +139,11 @@ class Build
@brew_dir ||= `brew --prefix`.chomp
end
def gcc_dir
@gcc_dir ||= `brew --prefix gcc`.chomp
end
def libgccjit_dir
@libgccjit_dir ||= `brew --prefix libgccjit`.chomp
end
def extra_libs
@extra_libs ||= [
"#{brew_dir}/opt/expat/lib/libexpat.1.dylib",
"#{brew_dir}/opt/libiconv/lib/libiconv.2.dylib",
"#{brew_dir}/opt/zlib/lib/libz.1.dylib"
File.join(brew_dir, 'opt/expat/lib/libexpat.1.dylib'),
File.join(brew_dir, 'opt/libiconv/lib/libiconv.2.dylib'),
File.join(brew_dir, 'opt/zlib/lib/libz.1.dylib')
]
end
@@ -152,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
@@ -186,14 +207,20 @@ class Build
@configure_help
end
def supports_native_comp?
@supports_native_comp ||= !!configure_help.match(/\s+--with-nativecomp\s+/)
end
def supports_xwidgets?
@supports_xwidgets ||= !!configure_help.match(/\s+--with-xwidgets\s+/)
end
def supports_native_comp?
@supports_native_comp ||= !native_comp_configure_flag.nil?
end
def native_comp_configure_flag
@native_comp_configure_flag ||= configure_help.match(
/\s+(--with-native(?:comp|-compilation))\s+/
)&.[](1)
end
def detect_native_comp
info 'Detecting native-comp support: ', newline: false
options[:native_comp] = supports_native_comp?
@@ -206,30 +233,6 @@ class Build
err 'This emacs source tree does not support native-comp'
end
def verify_libgccjit
err 'gcc not installed' unless Dir.exist?(gcc_dir)
err 'libgccjit not installed' unless Dir.exist?(libgccjit_dir)
if Dir["#{libgccjit_dir}/lib/**/libgccjit.so*"].empty?
err "Detected libgccjit (#{libgccjit_dir}) does not have any " \
'libgccjit.so* files. Please try reinstalling libgccjit: ' \
'brew reinstall libgccjit'
end
dirs = Dir["{#{gcc_dir},#{libgccjit_dir}}/lib/gcc/*"]
return if dirs.map { |dir| File.basename(dir) }.uniq == %w[10]
err 'Detected gcc and libgccjit library paths do not belong to the ' \
"same major version. Detected paths:\n - #{dirs.join(' - ')}"
end
def gcc_library_paths
@gcc_library_paths ||= Dir[
"{#{gcc_dir},#{libgccjit_dir}}/lib/gcc/*",
"{#{gcc_dir},#{libgccjit_dir}}/lib/gcc/*/gcc/*apple-darwin*/*"
].sort_by { |p| [p.size, p] }
end
def autogen
FileUtils.cd(source_dir) do
if File.exist?('autogen/copy_autogen')
@@ -241,10 +244,10 @@ class Build
end
def compile_source(source)
target = "#{source}/nextstep"
emacs_app = "#{target}/Emacs.app"
target = File.join(source, 'nextstep')
emacs_app = File.join(target, 'Emacs.app')
if File.exist?("#{target}/Emacs.app")
if File.exist?(emacs_app)
info 'Emacs.app already exists in ' \
"\"#{target.gsub(root_dir + '/', '')}\", attempting to use."
return emacs_app
@@ -256,49 +259,62 @@ class Build
if options[:native_comp]
info 'Compiling with native-comp enabled'
verify_native_comp
verify_libgccjit
gcc_info.verify_libgccjit
apply_native_comp_env_setup_patch(source)
ENV['CFLAGS'] = [
"-I#{gcc_dir}/include",
"-I#{File.join(gcc_info.root_dir, 'include')}",
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
'-O2',
'-march=native'
'-march=native',
ENV['CFLAGS']
].compact.join(' ')
ENV['LDFLAGS'] = [
gcc_library_paths.map { |path| "-L#{path}" },
"-I#{gcc_dir}/include",
"-I#{libgccjit_dir}/include"
].flatten.compact.join(' ')
"-L#{gcc_info.lib_dir}",
"-L#{gcc_info.darwin_lib_dir}",
"-L#{gcc_info.libgccjit_lib_dir}",
"-I#{File.join(gcc_info.root_dir, 'include')}",
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
ENV['LDFLAGS']
].compact.join(' ')
ENV['LIBRARY_PATH'] = [
gcc_library_paths,
gcc_info.lib_dir,
gcc_info.darwin_lib_dir,
gcc_info.libgccjit_lib_dir,
ENV['LIBRARY_PATH']
].flatten.compact.join(':')
].compact.join(':')
end
ENV['CC'] = 'clang'
ENV['PKG_CONFIG_PATH'] = [
"#{brew_dir}/lib/pkgconfig",
"#{brew_dir}/share/pkgconfig",
"#{brew_dir}/opt/expat/lib/pkgconfig",
"#{brew_dir}/opt/libxml2/lib/pkgconfig",
"#{brew_dir}/opt/ncurses/lib/pkgconfig",
"#{brew_dir}/opt/zlib/lib/pkgconfig",
"#{brew_dir}/Homebrew/Library/Homebrew/os/mac/pkgconfig/#{OS.version}",
File.join(brew_dir, 'lib/pkgconfig'),
File.join(brew_dir, 'share/pkgconfig'),
File.join(brew_dir, 'opt/expat/lib/pkgconfig'),
File.join(brew_dir, 'opt/libxml2/lib/pkgconfig'),
File.join(brew_dir, 'opt/ncurses/lib/pkgconfig'),
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']
].compact.join(':')
ENV['PATH'] = [
"#{brew_dir}/opt/make/libexec/gnubin",
"#{brew_dir}/opt/coreutils/libexec/gnubin",
"#{brew_dir}/opt/gnu-sed/libexec/gnubin",
"#{brew_dir}/bin",
"#{brew_dir}/opt/texinfo/bin",
File.join(brew_dir, 'opt/make/libexec/gnubin'),
File.join(brew_dir, 'opt/coreutils/libexec/gnubin'),
File.join(brew_dir, 'opt/gnu-sed/libexec/gnubin'),
File.join(brew_dir, 'bin'),
File.join(brew_dir, 'opt/texinfo/bin'),
ENV['PATH']
].compact.join(':')
ENV['LIBRARY_PATH'] = [
ENV['LIBRARY_PATH'],
'/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib'
].compact.join(':')
configure_flags = [
'--with-ns',
'--with-modules',
@@ -309,8 +325,8 @@ class Build
if options[:xwidgets] && supports_xwidgets?
configure_flags << '--with-xwidgets'
end
configure_flags << '--with-nativecomp' if options[:native_comp]
configure_flags << '--without-rsvg' unless options[:rsvg]
configure_flags << native_comp_configure_flag if options[:native_comp]
configure_flags << '--without-rsvg' if options[:rsvg] == false
run_cmd './configure', *configure_flags
@@ -325,17 +341,17 @@ class Build
make_flags = []
make_flags += ['-j', options[:parallel].to_s] if options[:parallel]
if options[:native_full_aot]
info 'Using NATIVE_FULL_AOT=1'
make_flags << 'NATIVE_FULL_AOT=1'
ENV.delete('NATIVE_FAST_BOOT')
else
ENV.delete('NATIVE_FULL_AOT')
ENV['NATIVE_FAST_BOOT'] = '1'
end
if options[:native_comp]
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'
ENV.delete('NATIVE_FAST_BOOT')
else
ENV.delete('NATIVE_FULL_AOT')
ENV['NATIVE_FAST_BOOT'] = '1'
end
end
run_cmd 'make', *make_flags
@@ -350,41 +366,70 @@ class Build
def symlink_internals(app)
return unless options[:native_comp]
info 'Creating symlinks within Emacs.app needed for native-comp'
FileUtils.cd(File.join(app, 'Contents')) do
# Skip creation of symlinks if *.eln files are located under
# Resources/native-lisp. Emacs is capable of finding lisp sources and
# *.eln cache files without symlinks.
return if Dir['Resources/native-lisp/**/*.eln'].any?
info 'Creating symlinks within Emacs.app needed for native-comp'
FileUtils.ln_s('Resources/lisp', 'lisp') unless File.exist?('lisp')
source = Dir['MacOS/libexec/emacs/**/eln-cache',
'MacOS/lib/emacs/**/native-lisp'].first
err 'Failed to find native-lisp cache directory for symlink creation.'
target = File.basename(source)
FileUtils.ln_s(source, target) unless File.exist?(target)
end
end
def archive_app(app)
FileUtils.mkdir_p(builds_dir)
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
metadata = [
meta[:ref]&.gsub(/\W/, '-'),
meta[:date],
meta[:date]&.strftime('%Y-%m-%d'),
meta[:sha][0..6],
"macOS-#{OS.version}",
OS.arch
].compact
filename = "Emacs.app-[#{metadata.join('][')}].tbz"
target = "#{builds_dir}/#{filename}"
@archive_filename = File.join(builds_dir, filename)
end
def archive_app(app)
filename = File.basename(archive_filename)
target_dir = File.dirname(archive_filename)
relative_target_dir = target_dir.gsub(root_dir + '/', '')
FileUtils.mkdir_p(target_dir)
app_base = File.basename(app)
app_dir = File.dirname(app)
if !File.exist?(target)
info "Creating #{filename} archive in \"#{builds_dir}\"..."
FileUtils.cd(app_dir) { system('tar', '-cjf', target, app_base) }
if !File.exist?(archive_filename)
info "Creating #{filename} archive in \"#{relative_target_dir}\"..."
FileUtils.cd(app_dir) do
system('tar', '-cjf', archive_filename, app_base)
end
else
info "#{filename} archive exists in " \
"#{builds_dir.gsub(root_dir + '/', '')}, skipping archving."
"#{relative_target_dir}, skipping archving."
end
end
@@ -407,22 +452,34 @@ class Build
return @meta if @meta
ref_sha = options[:git_sha] || ref
url = format(LATEST_URL, ref_sha)
commit_json = http_get(url)
info "Fetching info for git ref: #{ref_sha}"
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)
meta = {
sha: commit['sha'],
date: Date.parse(commit['commit']['committer']['date'])
date: Time.parse(commit['commit']['committer']['date'])
}
meta[:ref] = ref if ref && ref[0..6] != meta[:sha][0..6]
@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
@@ -438,10 +495,14 @@ class Build
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
template = File.read(
File.join(__dir__, 'patches/native-comp-env-setup.diff.erb')
)
patch = ERB.new(template).result(gcc_info.get_binding)
patch_file = File.join(source, 'macos_patches/native-comp-env-setup.diff')
File.write(patch_file, patch)
apply_patch({ file: patch_file }, source)
end
def effective_version
@@ -515,7 +576,7 @@ class Build
patch_dir = "#{target}/macos_patches"
run_cmd('mkdir', '-p', patch_dir)
patch_file = "#{patch_dir}/patch-{num}.diff"
patch_file = File.join(patch_dir, 'patch-{num}.diff')
num = 1
while File.exist?(patch_file.gsub('{num}', num.to_s.rjust(3, '0')))
num += 1
@@ -558,16 +619,16 @@ class AbstractEmbedder
private
def invocation_dir
File.join(app, 'Contents', 'MacOS')
end
def bin
"#{app}/Contents/MacOS/Emacs"
File.join(invocation_dir, 'Emacs')
end
def lib_dir
"#{app}/Contents/MacOS/#{lib_dir_name}"
end
def lib_dir_name
'lib'
File.join(invocation_dir, 'lib')
end
end
@@ -591,7 +652,6 @@ class LibEmbedder < AbstractEmbedder
FileUtils.cd(File.dirname(app)) do
copy_libs(binary)
copy_extra_libs(extra_libs, binary) if extra_libs.any?
self_ref_libs(binary)
end
end
@@ -603,6 +663,16 @@ class LibEmbedder < AbstractEmbedder
Pathname.new(File.dirname(exe))
).to_s
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|
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
next unless match && match[1].start_with?(lib_source)
@@ -610,18 +680,18 @@ class LibEmbedder < AbstractEmbedder
while_writable(exe) do
if match[2] == exe_file
system('install_name_tool', '-id',
"@executable_path/#{rel_path}/#{match[2]}", exe)
File.join('@executable_path', rel_path, match[2].to_s), exe)
else
system('install_name_tool', '-change', match[1],
"@executable_path/#{rel_path}/#{match[2]}", exe)
File.join('@executable_path', rel_path, match[2].to_s), exe)
end
end
next if match[2] == exe_file || File.exist?("#{lib_dir}/#{match[2]}")
next if match[2] == exe_file || File.exist?(File.join(lib_dir, match[2]))
FileUtils.mkdir_p(lib_dir)
FileUtils.cp(match[1], lib_dir)
copy_libs("#{lib_dir}/#{match[2]}", rel_path)
copy_libs(File.join(lib_dir, match[2].to_s), rel_path)
end
end
@@ -640,52 +710,28 @@ class LibEmbedder < AbstractEmbedder
while_writable(target) do
system('install_name_tool', '-id',
"@executable_path/#{rel_path}/#{lib_file}", target)
File.join('@executable_path', rel_path, lib_file), target)
end
copy_libs(target, rel_path)
end
end
def self_ref_libs(exe)
rel_path = Pathname.new(lib_dir).relative_path_from(
Pathname.new(File.dirname(exe))
).to_s
lib_paths ||= Dir.glob("#{lib_dir}/*").select { |f| File.file?(f) }
libs = lib_paths.map { |f| File.basename(f) }
([exe] + lib_paths).each do |bin_path|
`otool -L "#{bin_path}"`.split("\n")[1..-1].each do |line|
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
next unless match
next if match[1].start_with?('@executable_path/')
next unless libs.include?(match[2])
while_writable(bin_path) do
system(
'install_name_tool', '-change', match[1],
"@executable_path/#{rel_path}/#{match[2]}",
bin_path
)
end
end
end
end
def while_writable(file)
mode = File.stat(file).mode
File.chmod(0o775, file)
yield
ensure
File.chmod(mode, file)
end
end
class GccLibEmbedder < AbstractEmbedder
attr_reader :gcc_dir
attr_reader :gcc_info
def initialize(app, gcc_dir)
def initialize(app, gcc_info)
super(app)
@gcc_dir = gcc_dir
@gcc_info = gcc_info
end
def embed
@@ -695,44 +741,149 @@ class GccLibEmbedder < AbstractEmbedder
end
info 'Embedding libgccjit into Emacs.app'
if gcc_version.empty?
err "No suitable GCC lib with libgccjit found in #{gcc_dir}"
if gcc_info.lib_dir.empty?
err "No suitable GCC lib dir found in #{gcc_info.root_dir}"
end
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.chmod_R('u+w', target_dir)
FileUtils.mv(source_darwin_dir, target_darwin_dir)
end
private
def embedded?
Dir[File.join(target_dir, 'libgccjit.so*')].any?
Dir[File.join(target_dir, 'libgcc*')].any?
end
def target_dir
File.join(lib_dir, 'gcc', gcc_version)
File.join(invocation_dir, gcc_info.relative_lib_dir)
end
def gcc_version
@gcc_version ||= Dir[File.join(gcc_dir, 'lib', 'gcc', '*', 'libgcc*')]
.map { |path| File.basename(File.dirname(path)) }
.select { |path| path.match(/^\d+$/) }
.uniq.map(&:to_i).max.to_s
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
@source_dir ||= File.join(gcc_dir, 'lib', 'gcc', gcc_version)
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
include Output
def root_dir
@root_dir ||= `brew --prefix gcc`.chomp
end
def major_version
@major_version ||= File.basename(lib_dir)
end
def lib_dir
@lib_dir ||= Dir[File.join(root_dir, 'lib/gcc/*/libgcc*')]
.map { |path| File.dirname(path) }
.select { |path| File.basename(path).match(/^\d+$/) }
.max_by { |path| File.basename(path).to_i }
end
def relative_lib_dir
@relative_lib_dir ||= relative_dir(lib_dir, root_dir)
end
def darwin_lib_dir
@darwin_lib_dir ||= Dir[
File.join(lib_dir, 'gcc/*apple-darwin*/*')
].max_by do |path|
[
File.basename(File.dirname(path)).match(/darwin(\d+)$/)[1].to_i,
File.basename(path).split('.').map(&:to_i)
]
end
end
def relative_darwin_lib_dir
@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
def libgccjit_major_version
@libgccjit_major_version ||= File.basename(libgccjit_lib_dir.to_s)
end
def libgccjit_lib_dir
@libgccjit_lib_dir ||= Dir[
File.join(libgccjit_root_dir, 'lib/gcc/*/libgccjit.so*')
]
.map { |path| File.dirname(path) }
.select { |path| File.basename(path).match(/^\d+$/) }
.max_by { |path| File.basename(path).to_i }
end
def verify_libgccjit
err 'gcc not installed' unless Dir.exist?(root_dir)
err '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'
end
return if major_version == libgccjit_major_version
err <<~TEXT
Detected GCC and libgccjit library paths do not belong to the same major
version of GCC. Detected paths:
- #{lib_dir}
- #{libgccjit_lib_dir}
TEXT
end
def get_binding
binding
end
private
def relative_dir(path, root)
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
end
end
if __FILE__ == $PROGRAM_NAME
cli_options = {
macos_fixes: true,
work_dir: File.expand_path(__dir__),
native_full_aot: false,
parallel: Etc.nprocessors,
rsvg: false,
xwidgets: true
rsvg: true,
xwidgets: true,
github_auth: true
}
begin
@@ -752,14 +903,15 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:parallel] = v
end
opts.on('--git-sha SHA', 'Override detected git SHA of specified ' \
'branch allowing builds of old commits') do |v|
opts.on('--git-sha SHA',
'Override detected git SHA of specified ' \
'branch allowing builds of old commits') do |v|
cli_options[:git_sha] = v
end
opts.on('--[no-]xwidgets',
'Enable/disable XWidgets ' \
'(default: enabled if supported)') do |v|
'Enable/disable XWidgets if supported ' \
'(default: enabled)') do |v|
cli_options[:xwidgets] = v
end
@@ -775,15 +927,10 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:native_full_aot] = v
end
opts.on('--[no-]native-comp-macos-fixes',
'Enable/disable fix based on feature/native-comp-macos-fixes ' \
'branch (default: enabled if native-comp supported)') do |v|
cli_options[:macos_fixes] = v
end
opts.on('--rsvg', 'Enable SVG image support via librsvg, ' \
'can yield a unstable build (default: disabled)') do
cli_options[:rsvg] = true
opts.on('--[no-]rsvg',
'Enable/disable SVG image support via librsvg ' \
'(default: enabled)') do |v|
cli_options[:rsvg] = v
end
opts.on('--no-titlebar', 'Apply no-titlebar patch (default: disabled)') do
@@ -795,25 +942,29 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:no_frame_refocus] = true
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
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('--[no-]launcher',
'DEPRECATED: Launcher script is no longer used.') do |_|
raise Error, '--[no-]launcher option is deprecated, launcher ' \
'script is no longer used.'
opts.on('--work-dir DIR',
'Specify a working directory where tarballs, sources, and ' \
'builds will be stored and worked with') do |v|
cli_options[:work_dir] = v
end
opts.on(
'--plan FILE',
'Follow given plan file, instead of using given git ref/sha'
) do |v|
cli_options[:plan] = v
end
end.parse!
Build.new(File.expand_path(__dir__), ARGV.shift, cli_options).build
work_dir = cli_options.delete(:work_dir)
Build.new(work_dir, ARGV.shift, cli_options).build
rescue Error => e
warn "ERROR: #{e.message}"
exit 1

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 25e2de9..bcedd31 100644
index 8c638312b0..87af889ef4 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -2801,6 +2801,53 @@ queued with LOAD %"
(comp-run-async-workers)
(message "Compilation started."))))
@@ -4215,6 +4215,52 @@ native-compile-async
(let ((load (not (not load))))
(native--compile-async files recursively load selector)))
+;;;###autoload
+(defun native-compile-setup-environment-variables (&rest _args)
@@ -13,25 +13,24 @@ index 25e2de9..bcedd31 100644
+ (string-match-p "\.app\/Contents\/MacOS\/?$"
+ invocation-directory))
+ (let* ((library-path-env (getenv "LIBRARY_PATH"))
+ (gcc-base-dir (concat invocation-directory "lib/gcc"))
+ (gcc-version (car (seq-filter
+ (lambda (dir) (string-match-p "^[0-9]+$" dir))
+ (directory-files gcc-base-dir))))
+ (gcc-dir (concat gcc-base-dir "/" gcc-version))
+ (darwin-base-dir (car (file-expand-wildcards
+ (concat gcc-dir "/gcc/*apple-darwin*"))))
+ (darwin-version (car (seq-filter
+ (lambda (dir)
+ (string-match-p
+ "^[0-9]+\\(\.[0-9]+\\(\.[0-9]+\\)?\\)?$" dir))
+ (directory-files darwin-base-dir))))
+ (darwin-dir (concat darwin-base-dir "/" darwin-version))
+ (lib-paths (append
+ (list gcc-dir darwin-dir)
+ (if library-path-env (list library-path-env) (list)))))
+ (devtools-dir
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib")
+ (gcc-dir (expand-file-name
+ "<%= relative_lib_dir %>"
+ invocation-directory))
+ (darwin-dir (expand-file-name
+ "<%= sanitized_relative_darwin_lib_dir %>"
+ invocation-directory))
+ (lib-paths (list)))
+
+ (when (and gcc-dir darwin-dir)
+ (setenv "LIBRARY_PATH" (mapconcat 'identity lib-paths ":")))))
+ (if library-path-env
+ (push library-path-env lib-paths))
+ (if (file-directory-p devtools-dir)
+ (push devtools-dir lib-paths))
+ (push darwin-dir lib-paths)
+ (push gcc-dir lib-paths)
+
+ (setenv "LIBRARY_PATH" (mapconcat 'identity lib-paths ":"))))
+
+ ;; Remove advice, as it only needs to run once.
+ (advice-remove 'native-compile
@@ -55,4 +54,4 @@ index 25e2de9..bcedd31 100644
+
(provide 'comp)
;;; comp.el ends here
;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln