Compare commits

...

25 Commits

Author SHA1 Message Date
b94cb495ae chore(deps): update build-emacs-for-macos to 0.4.16
- fix(compiling): improve portability of builds
- fix(native_comp): crash on launch when gcc homebrew package was not
  installed
2021-06-07 23:45:49 +01:00
d6fb7efc3a chore(deps): update build-emacs-for-macos to 0.4.15
Makes build script itself perform authenticated GitHub API calls when
GITHUB_TOKEN environment variable is set.
2021-05-31 23:27:59 +01:00
cf0c1d0d07 chore(deps): update build-emacs-for-macos to 0.4.14
Adds a "emacs" CLI launcher script next to the "emacsclient" executable
in Emacs.app/Contents/MacOS/bin.
2021-05-22 21:11:14 +01:00
4ce0cf69d5 chore(deps): update build-emacs-for-macos to 0.4.13
Nothing new from a user-point of view. But this introduces the first
changes to the build script required to sign and notarize builds.
2021-05-22 18:54:29 +01:00
831bb394af docs(readme): add CLI usage section 2021-05-21 11:40:49 +01:00
7a6e5b52ef docs(readme): Minor tweaks to features list 2021-05-18 01:53:04 +01:00
7ffbd12e87 docs(readme): update features list and badges 2021-05-18 01:47:55 +01:00
4e22cf33ee chore(deps): update build-emacs-for-macos to 0.4.12
This fixes the issues with SVG rendering, and re-enables librsvg
support, meaning builds can render SVG images finally.
2021-05-17 23:17:21 +01:00
628092755e docs(readme): update release badge 2021-05-17 12:38:32 +01:00
27bcad6052 fix(dylib-tree): command name in help output had the old link-tree name 2021-05-17 01:22:59 +01:00
ff22622f87 chore(deps): fix Go module path in go.mod 2021-05-17 01:19:14 +01:00
ee642683c4 feat(tools): add dylib-tree tool to list/filter linked dynamic libraries 2021-05-17 01:14:46 +01:00
56d9178919 ci(test-builds): fix workflow name 2021-05-16 17:36:27 +01:00
29f5577efe ci(test-builds): add test builds GitHub Actions workflow
This will allow creating test builds using any branch of
build-emacs-for-macos or emacs-builds repos, so experimental changes can
be verified without affecting the nightly builds.
2021-05-16 17:34:13 +01:00
8544a650ab test(builds): add test build options to github-release tool
This will allow me to run test builds against experimental branches of
the build-emacs-for-macos build script, and publish them under a
pre-release "Test Builds" GitHub Release, rather than a normal nightly
release.
2021-05-16 17:33:57 +01:00
31a12fc502 docs(readme): add mention of where Emacs source is fetched from 2021-05-12 00:54:24 +01:00
cec5748301 docs(readme): add link to build script in Features section
Also fix some typos.
2021-05-12 00:49:13 +01:00
f5ccfd297a docs(readme): add mention of Known Good Nightly Builds issue 2021-05-12 00:43:21 +01:00
6d95b9e550 docs(readme): add link to GitHub Actions workflow source 2021-05-12 00:42:55 +01:00
3072334b7f feat(builds): change nightly schedule from 0:30 UTC to 0:00 UTC 2021-05-12 00:42:55 +01:00
813835a540 docs(readme): update to-do/issues section 2021-05-09 21:45:42 +01:00
52ec1c6a6b docs(readme): add system requirements, and reword some areas 2021-05-09 19:45:54 +01:00
3a96925657 docs(readme): improve styling and wording 2021-05-09 19:38:35 +01:00
aaa4aa947d feat(builds): change nightly schedule from 2:35 UTC to 0:30 UTC 2021-05-09 19:38:09 +01:00
c6b1e95f4c fix(builds): default releases to not be marked as pre-release 2021-05-09 19:34:48 +01:00
10 changed files with 549 additions and 70 deletions

View File

@@ -2,7 +2,7 @@
name: Build
on:
schedule:
- cron: "35 2 * * *"
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
gitRef:
@@ -34,7 +34,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: "0.4.11"
ref: "0.4.16"
path: builder
- uses: ruby/setup-ruby@v1
with:
@@ -75,6 +75,8 @@ jobs:
--work-dir '${{ github.workspace }}'
--native-full-aot
${{ github.event.inputs.extraReleaseArgs }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish release
if: steps.check.outcome == 'failure'
run: >-

103
.github/workflows/test-build.yml vendored Normal file
View File

@@ -0,0 +1,103 @@
---
name: Test Build
on:
workflow_dispatch:
inputs:
gitRef:
description: "Emacs git ref to build"
required: true
default: "master"
releaseToolGitRef:
description: "Git ref to checkout of emacs-builds (github-release)"
required: true
default: "main"
buildScriptGitRef:
description: "Git ref to checkout of build-emacs-for-macos"
required: true
default: "master"
testBuildName:
description: "Test build name"
required: false
default: ""
testReleaseType:
description: "prerelease or draft"
required: true
default: "prerelease"
extraPlanArgs:
Description: "Extra plan args"
required: false
default: ""
extraBuildArgs:
Description: "Extra build args"
required: false
default: ""
extraReleaseArgs:
Description: "Extra release args"
required: false
default: ""
jobs:
build-and-publish:
runs-on: macos-10.15
steps:
- name: Checkout emacs-builds repo
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.releaseToolGitRef }}
path: releaser
- name: Checkout build-emacs-for-macos repo
uses: actions/checkout@v2
with:
repository: jimeh/build-emacs-for-macos
ref: ${{ github.event.inputs.buildScriptGitRef }}
path: builder
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Compile github-release tool
run: >-
go build -o ./github-release ./cmd/github-release
working-directory: releaser
- name: Plan build
run: >-
./releaser/github-release --plan plan.yml plan
--work-dir '${{ github.workspace }}'
--test-build
--test-build-name="${{ github.event.inputs.testBuildName }}"
--test-release-type="${{ github.event.inputs.testReleaseType }}"
${{ github.event.inputs.extraPlanArgs }}
${{ github.event.inputs.gitRef }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Show plan
run: >-
cat plan.yml
- name: Check if planned release and asset already exist
id: check
continue-on-error: true
run: >-
./releaser/github-release --plan plan.yml check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
run: >-
brew bundle --file=builder/Brewfile
- name: Build Emacs
if: steps.check.outcome == 'failure'
run: >-
./builder/build-emacs-for-macos --plan=plan.yml
--work-dir '${{ github.workspace }}'
--native-full-aot
${{ github.event.inputs.extraReleaseArgs }}
- name: Publish release
if: steps.check.outcome == 'failure'
run: >-
./releaser/github-release --plan plan.yml publish
--release-sha="${{ github.event.inputs.releaseToolGitRef }}"
${{ github.event.inputs.extraReleaseArgs }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

142
README.md
View File

@@ -1,81 +1,143 @@
# Emacs Builds
<p align="center">
<img width="192px" src="https://github.com/emacs-mirror/emacs/raw/emacs-27.2/etc/images/icons/hicolor/scalable/apps/emacs.svg" alt="Logo">
</p>
<p>
<a href="https://github.com/jimeh/emacs-builds/releases">
<img src="https://img.shields.io/github/v/tag/jimeh/emacs-builds?label=nightly" alt="GitHub tag (latest SemVer)">
<h1 align="center">
Emacs Builds
</h1>
<p align="center">
<a href="https://github.com/jimeh/emacs-builds/releases/latest">
<img alt="GitHub release (latest)" src="https://img.shields.io/github/v/release/jimeh/emacs-builds?style=flat&label=nightly&color=%237F5AB6&logo=GNU%20Emacs&logoColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/issues">
<img src="https://img.shields.io/github/issues-raw/jimeh/emacs-builds.svg?style=flat&logo=github&logoColor=white"
alt="GitHub issues">
<img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/jimeh/emacs-builds?style=flat&logo=github&colorColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/pulls">
<img src="https://img.shields.io/github/issues-pr-raw/jimeh/emacs-builds.svg?style=flat&logo=github&logoColor=white" alt="GitHub pull requests">
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr-raw/jimeh/emacs-builds?style=flat&logo=github&colorColor=white">
</a>
<a href="https://github.com/jimeh/emacs-builds/releases">
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/jimeh/emacs-builds/total?style=flat&logoColor=white&logo=data%3Aimage%2Fpng%3Bbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAEsmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjE0IgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTQiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSIKICAgdGlmZjpJbWFnZVdpZHRoPSIxNCIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTQiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJwcm9kdWNlZCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWZmaW5pdHkgRGVzaWduZXIgMS45LjMiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMDUtMThUMDE6MjU6NTQrMDE6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI%2FPnP7qIwAAAGBaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRzytEURTHP2aIGBEWFhaThtWM%2FKiJjTLSUJM0RhlsZp55M2rezOu9N2myVbaKEhu%2FFvwFbJW1UkRKdsqa2KDnPKNGMud27vnc773ndO%2B54IplFc2s7gUtZxnRcMg7G5%2Fz1j5SQwvQzEBCMfWRqakIFe3thionXgWcWpXP%2FWsNiylTgao64WFFNyzhceHIsqU7vCncpmQSi8LHwn5DLih87ejJEj85nC7xh8NGLDoKrmZhb%2FoXJ3%2BxkjE0YXk5Pi1bUH7u47zEk8rNTEvsFO%2FAJEqYEF4mGGOUIH0MyRwkQD89sqJCfu93%2FiR5yVVk1ilisESaDBZ%2BUQtSPSVRFT0lI0vR6f%2FfvprqQH%2BpuicENQ%2B2%2FdIFtRvwuW7b7%2Fu2%2FXkA7ns4y5Xz83sw%2BCr6elnz7ULTKpycl7XkFpyuQfudnjAS35Jb3KWq8HwEjXFovYT6%2BVLPfvY5vIXYinzVBWzvQLecb1r4AjtZZ9JRQIRfAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAhUlEQVQokb3QsQnDMBRF0Y9J6QGylCt7GI%2BRPdJ4BIMXyA4pM0KKk0YCYawogZAHH4Tuvw%2BhiEowY67xarBirfHu68afijjXFvesK8AQEXeMB9KU2HDU2GPDE2P%2BHEzpbkNfe04pP9K8lw7knLa0k69pPpP%2BFyzaWfL%2BqXAvEXFr9K%2F58AJFIbDLRt48DAAAAABJRU5ErkJggg%3D%3D&color=blue&label=total%20downloads">
</a>
</p>
Nightly binary builds of Emacs for macOS, with native-compilation enabled, as a
completely self-contained Emacs.app application bundle.
<p align="center">
<strong>
Nightly binary builds of Emacs for macOS as a self-contained Emacs.app,
with native-compilation.
</strong>
</p>
## Features
- Self-contained Emacs.app application, with no external dependencies.
- Native-compilation is enabled in nightly builds from the `master` branch of
Emacs, and should just work without the need to install GCC, libgccjit, or any
other dependencies.
- Self-contained Emacs.app application bundle, with no external dependencies.
- Native-compilation ([gccemacs][]).
- Native JSON parsing via libjansson.
- SVG rendering via librsvg.
- Various image formats are supported via macOS native image APIs.
- Xwidget-webkit support is enabled, allowing access to a embedded WebKit-based
browser with `M-x xwidget-webkit-browse-url`.
- Native XML parsing via libxml2.
- Dynamic module loading.
- Includes the [fix-window-role][] and [system-appearance][] patches from the
excellent [emacs-plus][] project.
- Build are creation is transparent and public through the use of GitHub
Actions, allowing anyone to inspect git commit SHAs, full source code, and
exact commands used to produce a build. This is especially important right now
as builds are not yet signed and notarized.
- Emacs source is fetched from the [emacs-mirror/emacs][] GitHub repository.
- Build creation is transparent and public through the use of GitHub Actions,
allowing anyone to inspect git commit SHAs, full source code, and exact
commands used to produce a build. This is especially important right now as
builds are not yet signed and notarized.
- Uses [build-emacs-for-macos][] to build the self-contained application bundle.
[build-emacs-for-macos]: https://github.com/jimeh/build-emacs-for-macos
[gccemacs]: https://www.emacswiki.org/emacs/GccEmacs
[fix-window-role]:
https://github.com/d12frosted/homebrew-emacs-plus/blob/master/patches/emacs-28/fix-window-role.patch
[system-appearance]:
https://github.com/d12frosted/homebrew-emacs-plus/blob/master/patches/emacs-28/system-appearance.patch
[emacs-plus]: https://github.com/d12frosted/homebrew-emacs-plus
[emacs-mirror/emacs]: https://github.com/emacs-mirror/emacs
## System Requirements
- Intel-based Mac running macOS 10.15.x or later.
## Downloads
See the [Releases][] page to download latest builds.
Nightly builds of Emacs are for the part just fine, but if you don't like living
too close to the edge, see issue [#7 Known Good Nightly Builds][7] for a list of
recent nightly builds which have been actively used by a living being without
any issues.
[releases]: https://github.com/jimeh/emacs-builds/releases
[7]: https://github.com/jimeh/emacs-builds/issues/7
## Untrusted Application
Currently builds are not signed or notarized, meaning macOS cannot verify
Emacs.app came from a trusted developer, and by default you are not given an
option to trust the app and open it.
Simplest way around this is to right-click (or control-click) on the Emacs app
in Finder and select "Open". You will then be given the same warning as before,
but with a "Open" button now available to trust and open the app. After that you
can open the application like normal without any warnings.
Builds will soon be signed and notarized, progress is tracked in [Issue #1][1].
[1]: https://github.com/jimeh/emacs-builds/issues/1
## 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.
For example, this will expose both `emacs` and `emacsclient`:
```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"
fi
```
Setting the `EMACS` variable to the binary path seems to be a good idea, as some
tools seem to use it to figure out the path to Emacs' executable, including
[doom-emacs][]' `doom` CLI tool.
[doom-emacs]: https://github.com/hlissner/doom-emacs
## Build Process
Building Emacs is done using the [jimeh/build-emacs-for-macos][] build script,
executed within a GitHub Actions workflow. Full build history is available
[here][actions].
executed within a GitHub Actions [workflow][]. This is why macOS 10.15.x or
later is required, as it's the oldest version of macOS available in GitHub
Actions.
[jimeh/build-emacs-for-macos]: https://github.com/jimeh/build-emacs-for-macos
[workflow]:
https://github.com/jimeh/emacs-builds/blob/main/.github/workflows/build.yml
Full history for all builds is available on GitHub Actions [here][actions].
[actions]: https://github.com/jimeh/emacs-builds/actions
Nightly builds are scheduled for 2:35 UTC every night, based on the latest
Nightly builds are scheduled for 0:00 UTC every night, based on the latest
commit from the `master` branch of the [emacs-mirror/emacs][] repository. This
means a nightly build will only be produced if there have been new commits since
the last nightly build.
[emacs-mirror/emacs]: https://github.com/emacs-mirror/emacs
## Untrusted Application
## Issues / To-Do
Currently builds are not signed or notarized, meaning macOS cannot verify
Emacs.app came from a trusted developer, and by default you are not even given
the option to trust the app and open it anyway.
Please see [Issues][] for details of things to come, or to report issues.
Simplest way around this: Instead of double-clicking on Emacs.app in Finder,
right-click (or control-click) on Emacs and select "Open". You will then be
given the same warning as before, with a "Open" button now available to open the
app anyway. After that you can open the application like normal without any
warnings.
## To-Do
- [ ] Sign and notarize builds.
- [ ] Builds for stable versions of Emacs.
- [ ] Populate GitHub Release description with relevant info about the build,
including a link to the GitHub Actions workflow run that produced the
build.
- [ ] (Eventually) support Apple Silicon mac builds when native-compilation
actually works on Apple Silicon.
- [ ] (Eventually) support builds for Linux.
[issues]: https://github.com/jimeh/emacs-builds/issues

248
cmd/dylib-tree/main.go Normal file
View File

@@ -0,0 +1,248 @@
package main
import (
"debug/macho"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/urfave/cli/v2"
"github.com/xlab/treeprint"
)
var app = &cli.App{
Name: "dylib-tree",
Usage: "recursive list shared-libraries as a tree",
UsageText: "dylib-tree [options] <binary-file> [<binary-file>]",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "depth",
Usage: "max depth of tree (default: 0 = unlimited)",
Value: 0,
},
&cli.StringSliceFlag{
Name: "ignore",
Usage: "path patterns to ignore",
},
&cli.BoolFlag{
Name: "ignore-system",
Usage: "ignore system libraries",
},
&cli.BoolFlag{
Name: "real-path",
Usage: "show resolved full paths instead of @executable_path " +
"and @rpath",
},
},
Action: actionHandler(LinkTreeCmd),
}
type Context struct {
Root string
ExecutablePath string
Depth int
MaxDepth int
RealPath bool
Ignore []string
RPaths []string
}
func (s *Context) WithFile(filename string) *Context {
ctx := *s
ctx.Root = filename
ctx.ExecutablePath = filepath.Dir(filename)
return &ctx
}
func (s *Context) WithDepth(depth int) *Context {
ctx := *s
ctx.Depth = depth
return &ctx
}
func (s *Context) WithIgnore(ignore []string) *Context {
ctx := *s
ctx.Ignore = append(ctx.Ignore, ignore...)
return &ctx
}
func (s *Context) WithRpaths(rpaths []string) *Context {
ctx := *s
ctx.RPaths = append(ctx.RPaths, rpaths...)
return &ctx
}
func actionHandler(
f func(*cli.Context, *Context) error,
) func(*cli.Context) error {
return func(c *cli.Context) error {
ignore := c.StringSlice("ignore")
if c.Bool("ignore-system") {
ignore = append(
ignore,
"/System/Library/*",
"*/libSystem.*.dylib",
"*/libobjc.*.dylib",
)
}
ctx := &Context{
Ignore: ignore,
MaxDepth: c.Int("depth"),
RealPath: c.Bool("real-path"),
}
return f(c, ctx)
}
}
func LinkTreeCmd(c *cli.Context, ctx *Context) error {
for _, filename := range c.Args().Slice() {
ctx := ctx.WithFile(filename)
treeRoot := treeprint.New()
tree := treeRoot.AddBranch(filename)
err := processBinary(&tree, ctx, filename)
if err != nil {
return err
}
fmt.Println(treeRoot.String())
}
return nil
}
func processBinary(
parent *treeprint.Tree,
ctx *Context,
filename string,
) error {
f, err := macho.Open(filename)
if err != nil {
return err
}
ctx = ctx.WithDepth(ctx.Depth + 1).WithRpaths(getRpaths(f))
if ctx.MaxDepth > 0 && ctx.Depth > ctx.MaxDepth {
return nil
}
libs, err := f.ImportedLibraries()
if err != nil {
return err
}
for _, lib := range libs {
skip, err := ignoreLib(ctx, lib)
if err != nil {
return err
}
if skip {
continue
}
filename, err := resolveLibFilename(ctx, lib)
if err != nil {
(*parent).AddBranch(lib)
continue
}
skip, err = ignoreLib(ctx, filename)
if err != nil {
return err
}
if skip {
continue
}
displayName := lib
if ctx.RealPath {
displayName = filename
}
tree := (*parent).AddBranch(displayName)
err = processBinary(&tree, ctx, filename)
if err != nil {
return err
}
}
return nil
}
func ignoreLib(ctx *Context, lib string) (bool, error) {
for _, pattern := range ctx.Ignore {
m, err := ignoreRegexp(pattern)
if err != nil {
return false, err
}
if m.MatchString(lib) {
return true, nil
}
}
return false, nil
}
func ignoreRegexp(p string) (*regexp.Regexp, error) {
rp := "^" + regexp.QuoteMeta(p) + "$"
rp = strings.ReplaceAll(rp, `\*`, ".*")
rp = strings.ReplaceAll(rp, `\?`, ".")
return regexp.Compile(rp)
}
func resolveLibFilename(ctx *Context, lib string) (string, error) {
filename := lib
if strings.HasPrefix(lib, "@executable_path") {
filename = filepath.Join(ctx.ExecutablePath, lib[16:])
} else if strings.HasPrefix(lib, "@rpath") {
for _, r := range ctx.RPaths {
if strings.HasPrefix(r, "@executable_path") {
r = filepath.Join(ctx.ExecutablePath, r[16:])
}
rfile := filepath.Join(r, lib[6:])
_, err := os.Stat(rfile)
if err != nil {
continue
}
return rfile, nil
}
return "", fmt.Errorf("could not find %s", lib)
}
_, err := os.Stat(filename)
return filename, err
}
func getRpaths(f *macho.File) []string {
paths := []string{}
for _, i := range f.Loads {
if r, ok := i.(*macho.Rpath); ok {
paths = append(paths, r.Path)
}
}
return paths
}
func main() {
err := app.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Error())
os.Exit(1)
}
}

View File

@@ -27,15 +27,15 @@ func checkAction(c *cli.Context, opts *globalOptions) error {
fmt.Printf(
"==> Checking github.com/%s for release: %s\n",
repo.String(), plan.Release,
repo.String(), plan.Release.Name,
)
release, resp, err := gh.Repositories.GetReleaseByTag(
c.Context, repo.Owner, repo.Name, plan.Release,
c.Context, repo.Owner, repo.Name, plan.Release.Name,
)
if err != nil {
if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("release %s does not exist", plan.Release)
return fmt.Errorf("release %s does not exist", plan.Release.Name)
} else {
return err
}

View File

@@ -6,11 +6,18 @@ import (
"gopkg.in/yaml.v3"
)
type Release struct {
Name string `yaml:"name"`
Title string `yaml:"title,omitempty"`
Draft bool `yaml:"draft,omitempty"`
Pre bool `yaml:"prerelease,omitempty"`
}
type Plan struct {
Commit *Commit `yaml:"commit"`
OS *OSInfo `yaml:"os"`
Release string `yaml:"release"`
Archive string `yaml:"archive"`
Commit *Commit `yaml:"commit"`
OS *OSInfo `yaml:"os"`
Release *Release `yaml:"release"`
Archive string `yaml:"archive"`
}
func LoadPlan(filename string) (*Plan, error) {

View File

@@ -40,6 +40,21 @@ func planCmd() *cli.Command {
Name: "sha",
Usage: "Override commit SHA of specified git branch/tag",
},
&cli.BoolFlag{
Name: "test-build",
Usage: "Plan a test build, which is published to a draft " +
"\"test-builds\" release",
},
&cli.StringFlag{
Name: "test-build-name",
Usage: "Set a unique name to distinguish the ",
},
&cli.StringFlag{
Name: "test-release-type",
Value: "prerelease",
Usage: "Type of release when doing a test-build " +
"(prerelease or draft)",
},
},
Action: actionHandler(planAction),
}
@@ -78,20 +93,37 @@ func planAction(c *cli.Context, opts *globalOptions) error {
cleanOS := sanitizeString(osInfo.Name + "-" + osInfo.ShortVersion())
cleanArch := sanitizeString(osInfo.Arch)
releaseName := fmt.Sprintf(
"Emacs.%s.%s.%s",
commit.DateString(), commit.ShortSHA(), cleanRef,
)
release := &Release{
Name: fmt.Sprintf(
"Emacs.%s.%s.%s",
commit.DateString(), commit.ShortSHA(), cleanRef,
),
}
archiveName := fmt.Sprintf(
"Emacs.%s.%s.%s.%s.%s.tbz",
"Emacs.%s.%s.%s.%s.%s",
commit.DateString(), commit.ShortSHA(), cleanRef, cleanOS, cleanArch,
)
if c.Bool("test-build") {
release.Title = "Test Builds"
release.Name = "test-builds"
if c.String("test-release-type") == "draft" {
release.Draft = true
} else {
release.Pre = true
}
archiveName += ".test"
if t := c.String("test-build-name"); t != "" {
archiveName += "." + sanitizeString(t)
}
}
plan := &Plan{
Commit: commit,
OS: osInfo,
Release: releaseName,
Archive: filepath.Join(buildsDir, archiveName),
Release: release,
Archive: filepath.Join(buildsDir, archiveName+".tbz"),
}
buf := bytes.Buffer{}

View File

@@ -24,12 +24,6 @@ func publishCmd() *cli.Command {
Usage: "Git SHA of repo to create release on",
EnvVars: []string{"GITHUB_SHA"},
},
&cli.BoolFlag{
Name: "prerelease",
Usage: "Git SHA of repo to create release on",
EnvVars: []string{"RELEASE_PRERELEASE"},
Value: true,
},
},
Action: actionHandler(publishAction),
}
@@ -44,7 +38,6 @@ func publishAction(c *cli.Context, opts *globalOptions) error {
}
releaseSHA := c.String("release-sha")
prerelease := c.Bool("prerelease")
assetBaseName := filepath.Base(plan.Archive)
assetSumFile := plan.Archive + ".sha256"
@@ -65,20 +58,34 @@ func publishAction(c *cli.Context, opts *globalOptions) error {
fmt.Printf(" -> Done: %s\n", assetSum)
}
fmt.Printf("==> Checking release %s\n", plan.Release)
tagName := plan.Release.Name
name := plan.Release.Title
if name == "" {
name = tagName
}
fmt.Printf("==> Checking release %s\n", tagName)
release, resp, err := gh.Repositories.GetReleaseByTag(
c.Context, repo.Owner, repo.Name, plan.Release,
c.Context, repo.Owner, repo.Name, plan.Release.Name,
)
if err != nil {
if resp.StatusCode == http.StatusNotFound {
fmt.Println(" -> Release not found, creating...")
prerelease := false
if !plan.Release.Draft && plan.Release.Pre {
prerelease = true
}
release, _, err = gh.Repositories.CreateRelease(
c.Context, repo.Owner, repo.Name, &github.RepositoryRelease{
Name: &plan.Release,
TagName: &plan.Release,
Name: &name,
TagName: &tagName,
TargetCommitish: &releaseSHA,
Prerelease: &prerelease,
Draft: &plan.Release.Draft,
},
)
if err != nil {
@@ -89,8 +96,19 @@ func publishAction(c *cli.Context, opts *globalOptions) error {
}
}
if release.GetPrerelease() != prerelease {
release.Prerelease = &prerelease
if release.GetName() != name {
release.Name = &name
release, _, err = gh.Repositories.EditRelease(
c.Context, repo.Owner, repo.Name, release.GetID(), release,
)
if err != nil {
return err
}
}
if !plan.Release.Draft && release.GetPrerelease() != plan.Release.Pre {
release.Prerelease = &plan.Release.Pre
release, _, err = gh.Repositories.EditRelease(
c.Context, repo.Owner, repo.Name, release.GetID(), release,

3
go.mod
View File

@@ -1,10 +1,11 @@
module github.com/jimeh/build-emacs
module github.com/jimeh/emacs-builds
go 1.16
require (
github.com/google/go-github/v35 v35.1.0
github.com/urfave/cli/v2 v2.3.0
github.com/xlab/treeprint v1.1.0
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

6
go.sum
View File

@@ -41,6 +41,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -121,8 +122,12 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -368,6 +373,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=