From 2293c87fc99ef0fb932e54912d6f2e719e7b60e9 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 27 Oct 2021 03:10:24 +0100 Subject: [PATCH 1/4] refactor(build): turn add_cli_helper function into a embedder class --- build-emacs-for-macos | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/build-emacs-for-macos b/build-emacs-for-macos index e1c5bf5..6978ee0 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -105,8 +105,8 @@ class Build build_dir, app = create_build_dir(app) handle_native_lisp(app) - add_cli_helper(app) + CLIHelperEmbedder.new(app).embed CSourcesEmbedder.new(app, @source_dir).embed LibEmbedder.new(app, brew_dir, extra_libs, options[:relink_eln]).embed GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp] @@ -506,18 +506,6 @@ 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 build_name return @build_name if @build_name return @build_name = options[:build_name] if options[:build_name] @@ -787,6 +775,10 @@ class AbstractEmbedder File.join(invocation_dir, 'Emacs') end + def bin_dir + File.join(invocation_dir, 'bin') + end + def lib_dir File.join(invocation_dir, 'lib') end @@ -796,6 +788,20 @@ class AbstractEmbedder end end +class CLIHelperEmbedder < AbstractEmbedder + def embed + source = File.join(__dir__, 'helper', 'emacs-cli.bash') + target = File.join(bin_dir, '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 +end + class CSourcesEmbedder < AbstractEmbedder PATH_PATCH = '(setq source-directory (expand-file-name ".."))' From ef4f2ad930e389f41ede014751e501f3c84bda49 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 27 Oct 2021 03:14:06 +0100 Subject: [PATCH 2/4] refactor: use site-start.el instead of abusing subdirs.el Set source-directory in site-start.el instead of subdirs.el which we were basically abusing to execute Elisp before the user config is loaded. --- build-emacs-for-macos | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/build-emacs-for-macos b/build-emacs-for-macos index 6978ee0..a12e94e 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -803,7 +803,10 @@ class CLIHelperEmbedder < AbstractEmbedder end class CSourcesEmbedder < AbstractEmbedder - PATH_PATCH = '(setq source-directory (expand-file-name ".."))' + PATH_PATCH = <<~ELISP + ;; Allow Emacs to find bundled C sources. + (setq source-directory (expand-file-name "..")) + ELISP attr_reader :source_dir @@ -824,17 +827,18 @@ class CSourcesEmbedder < AbstractEmbedder FileUtils.cp(f, target) end - return if File.read(subdirs_el_file).include?(PATH_PATCH) + return if File.exist?(site_start_el_file) && + File.read(site_start_el_file).include?(PATH_PATCH) - File.open(subdirs_el_file, 'a') do |f| + File.open(site_start_el_file, 'a') do |f| f.puts("\n#{PATH_PATCH}") end end private - def subdirs_el_file - @subdirs_el_file ||= File.join(resources_dir, 'lisp', 'subdirs.el') + def site_start_el_file + @site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el') end end From be326b22aa0e940d3b4e88153d01e4e9aceddc24 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 27 Oct 2021 03:17:17 +0100 Subject: [PATCH 3/4] refactor(native-comp): improve native-comp env setup patch Instead of patching emacs sources before building Emacs, we can use site-start.el instead for a much cleaner way of setting LIBRARY_PATH before the user config is loaded. --- build-emacs-for-macos | 56 +++++++++++++++++-------- patches/native-comp-env-setup.diff.erb | 57 -------------------------- 2 files changed, 39 insertions(+), 74 deletions(-) delete mode 100644 patches/native-comp-env-setup.diff.erb diff --git a/build-emacs-for-macos b/build-emacs-for-macos index a12e94e..9b264b6 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -286,8 +286,6 @@ class Build verify_native_comp gcc_info.verify_libgccjit - apply_native_comp_env_setup_patch(source) - ENV['CFLAGS'] = [ "-I#{File.join(gcc_info.root_dir, 'include')}", "-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}", @@ -607,21 +605,6 @@ class Build system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}") end - def apply_native_comp_env_setup_patch(source) - term = 'native-compile-setup-environment-variables' - file = 'lisp/emacs-lisp/comp.el' - return if `grep '#{term}' '#{file}'`.strip.size.positive? - - 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 @effective_version ||= begin case ref @@ -975,10 +958,45 @@ class GccLibEmbedder < AbstractEmbedder 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) + + env_setup = ERB.new(NATIVE_COMP_ENV_VAR_TPL).result(gcc_info.get_binding) + return if File.exist?(site_start_el_file) && + File.read(site_start_el_file).include?(env_setup) + + File.open(site_start_el_file, 'a') do |f| + f.puts("\n#{env_setup}") + end end private + NATIVE_COMP_ENV_VAR_TPL = <<~ELISP + ;; Set LIBRARY_PATH to point at bundled GCC and Xcode Command Line Tools to + ;; ensure native-comp works. + (when (and (eq system-type 'darwin) + (string-match-p "\\.app\\/Contents\\/MacOS\\/?$" + invocation-directory)) + (let* ((library-path-env (getenv "LIBRARY_PATH")) + (devtools-dir + "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib") + (gcc-dir (expand-file-name + "<%= app_bundle_relative_lib_dir %>" + invocation-directory)) + (darwin-dir (expand-file-name + "<%= app_bundle_relative_darwin_lib_dir %>" + invocation-directory)) + (lib-paths (list))) + + (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 ":")))) + ELISP + def embedded? Dir[File.join(target_dir, 'libgcc*')].any? end @@ -1002,6 +1020,10 @@ class GccLibEmbedder < AbstractEmbedder def relative_dir(path, root) Pathname.new(path).relative_path_from(Pathname.new(root)).to_s end + + def site_start_el_file + @site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el') + end end class GccInfo diff --git a/patches/native-comp-env-setup.diff.erb b/patches/native-comp-env-setup.diff.erb deleted file mode 100644 index 1c7147a..0000000 --- a/patches/native-comp-env-setup.diff.erb +++ /dev/null @@ -1,57 +0,0 @@ -diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el -index 638d4b274c..2599211936 100644 ---- a/lisp/emacs-lisp/comp.el -+++ b/lisp/emacs-lisp/comp.el -@@ -4224,6 +4224,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) -+ "Ensure LIBRARY_PATH is set correctly when libgccjit is bundled." -+ (when (and (eq system-type 'darwin) -+ (string-match-p "\.app\/Contents\/MacOS\/?$" -+ invocation-directory)) -+ (let* ((library-path-env (getenv "LIBRARY_PATH")) -+ (devtools-dir -+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib") -+ (gcc-dir (expand-file-name -+ "<%= app_bundle_relative_lib_dir %>" -+ invocation-directory)) -+ (darwin-dir (expand-file-name -+ "<%= app_bundle_relative_darwin_lib_dir %>" -+ invocation-directory)) -+ (lib-paths (list))) -+ -+ (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 -+ 'native-compile-setup-environment-variables) -+ (advice-remove 'comp--native-compile -+ 'native-compile-setup-environment-variables) -+ (advice-remove 'native-compile-async -+ 'native-compile-setup-environment-variables) -+ (advice-remove 'native--compile-async -+ 'native-compile-setup-environment-variables)) -+ -+;; Ensure environment setup runs before any native compilation. -+(advice-add 'native-compile :before -+ 'native-compile-setup-environment-variables) -+(advice-add 'comp--native-compile :before -+ 'native-compile-setup-environment-variables) -+(advice-add 'native-compile-async :before -+ 'native-compile-setup-environment-variables) -+(advice-add 'native--compile-async :before -+ 'native-compile-setup-environment-variables) -+ - (provide 'comp) - - ;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln From 7f2aba0e4e86708426b245f6d6b7f853685a197d Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 27 Oct 2021 03:20:56 +0100 Subject: [PATCH 4/4] chore(builder): add hidden sign-files command for testing purposes Useful when needing to sign singular files with same ease of signing a Emacs.app bundle. --- pkg/cli/cli.go | 1 + pkg/cli/sign.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 2e29336..007ac7d 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -46,6 +46,7 @@ func New(version, commit, date string) *CLI { Commands: []*cli2.Command{ planCmd(), signCmd(), + signFilesCmd(), notarizeCmd(), packageCmd(), releaseCmd(), diff --git a/pkg/cli/sign.go b/pkg/cli/sign.go index 4f430d2..67af187 100644 --- a/pkg/cli/sign.go +++ b/pkg/cli/sign.go @@ -112,3 +112,49 @@ func signAction(c *cli2.Context, opts *Options) error { return sign.Emacs(c.Context, app, signOpts) } + +func signFilesCmd() *cli2.Command { + signCmd := signCmd() + + var flags []cli2.Flag + for _, f := range signCmd.Flags { + n := f.Names() + if len(n) > 0 && n[0] == "plan" { + continue + } + + flags = append(flags, f) + } + + return &cli2.Command{ + Name: "sign-files", + Usage: "sign files with codesign", + ArgsUsage: " [...]", + Hidden: true, + Flags: flags, + Action: actionWrapper(signFilesAction), + } +} + +func signFilesAction(c *cli2.Context, opts *Options) error { + signOpts := &sign.Options{ + Identity: c.String("sign"), + Options: c.StringSlice("options"), + Deep: c.Bool("deep"), + Timestamp: c.Bool("timestamp"), + Force: c.Bool("force"), + Verbose: c.Bool("verbose"), + CodeSignCmd: c.String("codesign"), + } + + if v := c.StringSlice("entitlements"); len(v) > 0 { + e := sign.Entitlements(v) + signOpts.Entitlements = &e + } + + if !opts.quiet { + signOpts.Output = os.Stdout + } + + return sign.Files(c.Context, c.Args().Slice(), signOpts) +}