0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【electron】mac向けのbuildはuniversalにすべし

Posted at

初書:2021/11/2
mac : 11.6
node: v16.6.1
electron : v15.1.2

前置き

electron-builderを使ってmac向けにパッケージ化をした時に起こったメモ。

パッケージングする

electronで作成したプロジェクトをパッケージングするとき、大抵はelectron-builderを使用すると思う。
今回も調べたらelectron-builderが出てきたので、これを参考にパッケージングしてみる。

% npx electron-builder --mac --x64

実際にはpackage.jsonか専用ファイルを作って設定が必要だが、本趣旨とは外れるので省略。

これで無事にパッケージングでき、DMGファイルを公開することで他のmacユーザーも使用できる。

起きた問題

こちらintelのCPU使い。パッケージングしたファイルを使っても特に問題はなかった。
問題は配布先。相手はM1のCPUを使用していた。

M1のmacでも特に問題なく動くのだが、1つだけ動かないものがあった。

今回、GUI版のEmacsを開く動作が必要だったため、child_processを使用してEmacsを起動していた。
これが、M1のmacだと動かず、Emacsがクラッシュしてしまった。

クラッシュレポートを見せてもらうとだいたいこんな感じ。

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
Thread 1:: com.apple.rosetta.exceptionserver
Thread 2:
Thread 3:
Thread 4:
Thread 5:
Thread 6:
Thread 7:: com.apple.NSEventThread

Thread 0 crashed with X86 Thread State (64-bit):

なんかrosettaが悪さしているような気がしている。
ということで試行錯誤した記録を書いていく。

現在の呼び出し方法

最初書いていたコード。
execはzshとかbashとかではなくsh1を使っているので、パスが通っているか分からないので絶対パス指定。

    exec(`/Applications/Emacs.app/Contents/MacOS/Emacs "${ExecPathEscape(dirPath)}"`, callback);

intelでは正常にEmacsが開く。
M1ではここが呼び出されると、一瞬だけ開いたのち、落ち、callbackでerrorが返される。

原因特定をする

ここは試行錯誤のメモ。結論はその下。
とりあえず呼び出し方を変えてどうにかならないか考えてみる。

  1. execではどうにもならないかもしれないと思い、大元であるspawnを叩いてみる。
      const exe = spawn('/Applications/Emacs.app/Contents/MacOS/Emacs', [ExecPathEscape(dirPath)], {
        shell: true,
      });
      exe.stdout.on('data', stdoutCallback);
      exe.stderr.on('data', stderrCallback);

変化なし。

  1. この時は、自分のアプリケーションがM1で適切に動いていて、Emacsが何故かX86_64で動いていると思っていた。
    ので、シェルコマンドをX86_64で動かせば動くのでは?と思い以下のコードに変更
      exec('arch -arch x86_64 /bin/bash -c "/Applications/Emacs.app/Contents/MacOS/Emacs ' + ExecPathEscape(`"${ExecPathEscape(dirPath)}"`) + '"', callback);

-c以降が文字列になるため、ファイルパスを2重エスケープするという複雑な構造に。
もちろん変化はなかった。

  1. electronのshellを叩いてみる。
    もしかしてshell.openExternalで開けるのでは?と思い書いてみたが動くはずもなく。

  2. Emacsをrosettaで起動にチェックをつける
    Emacsを右クリックし、情報を開くから、rosettaを使用して開くにチェックを入れて起動してみた。
    まあこれでもないですよね。

他にも2,3個ためしたがどれも上手くいかなかった。とある事情でログを消してしまい何試したか覚えていないが。

解決方法の発見

M1ユーザーの方にも色々と試してもらっていて、それぞれ1つずつ解決策が見つかった。

1つは、叩いていた/Applications/Emacs.app/Contents/MacOS/Emacsファイルは、中はただのRubyなので、
読んでみると、どうやら実行環境に応じて開くファイルを変えているらしい。
これで、何故かX86_64が選択されてしまっているので、直接Arm64のEmacsを起動させるという方法。
コマンドだと/Applications/Emacs.app/Contents/MacOS/Emacs-arm64-11_2とかになるだろうか。
これで正常起動が出来た。

もう一つがタイトルにもあるように、自分のアプリケーションがintel専用で配布していることに気がつき、
universalに変更してパッケージングするというもの。
この場合は/Applications/Emacs.app/Contents/MacOS/Emacsを叩いても正常に起動できた。

ということで、上記二つから考えると、

  • M1のMacでEmacsのEmacs-x86_64-10_14が何故か起動できない。
  • M1のMacでintelのアプリケーションを起動すると、シェルはX86_64で呼び出される。
  • これにより、EmacsがチップをX86_64だと判断し、Emacs-x86_64-10_14を起動しようと試みた。
    という原因で開けないという事態が起きた。

結論

M1のMacに対応できるなら対応したものを配布した方がこんなことにならないですよね。
ということで最低でもuniversal、容量とか気にするならM1とintelそれぞれに対応したパッケージを作成しよう。

という忘備録でした。

% npx electron-builder --mac --universal
  1. これシェルと読むのだろうか、意外に詳しくないこの辺り。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?