この記事は、Crystal Forum の記事をChatGPTを用いて日本語に翻訳した上で注釈をつけたものです。オリジナルの内容を知りたい場合は下記のリンクからソースに当たってください。
Mac上でCrystalアプリを配布する
静的リンクを用いずにMacOS上でCrystalアプリを配布する場合、必要な共有ライブラリと依存関係をアプリケーションにバンドルする必要があります。また、アプリケーションが実行時にこれらのライブラリを見つけられるようにするスクリプトを作成する必要があります。以下に一般的な手順を示します:
-
Crystalプログラムのコンパイル: 必要な共有ライブラリと依存関係を含めて、Crystalアプリケーションを
crystal build
コマンドを使用してビルドします。 -
依存関係の特定: バイナリが依存する動的ライブラリを調査するためにotoolのようなツールを使用します。以下のコマンドをコンパイルしたバイナリで実行します:
otool -L your_executable
これにより、実行ファイルがリンクされている共有ライブラリが一覧表示されます。
-
共有ライブラリのバンドル: 必要な共有ライブラリをアプリケーションと共に配布するディレクトリにコピーします。これらをアプリのバンドル内の
libs
フォルダに配置する場合があります。 -
ライブラリパスの更新:
install_name_tool
コマンドを使用して、バイナリ内の共有ライブラリへのパスを変更します。それをあなたが配布にバンドルしたライブラリの場所を指すようにします。以下のようなコマンドを各共有ライブラリに対して使用します:install_name_tool -change old_path new_path your_executable
old_path
はライブラリへの現在のパスであり、new_path
はアプリのバンドル内のライブラリへの相対パスまたは絶対パスです。kojix2注:4の手順と、5の環境変数を設定する手順はやや矛盾するようにも見えます。次のサイトなどを参考にすると、うまくいくと5の手順を使わずにすむかもしれません install_name_tool to update a executable to search for dylib in Mac OS X
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp install_name_tool -add_rpath "@loader_path/../lib" myapp
-
スタートアップスクリプトの作成:
DYLD_LIBRARY_PATH
環境変数を設定して、バンドルした共有ライブラリのディレクトリを含めるスタートアップスクリプトを作成します。このスクリプトはその後、あなたのCrystalバイナリを実行します。基本的な例はこちら:#!/bin/bash export DYLD_LIBRARY_PATH="./libs:$DYLD_LIBRARY_PATH" ./your_executable
-
アプリケーションのパッケージング: コンパイルされたバイナリ、共有ライブラリ、スタートアップスクリプトを一緒にバンドルし、.dmgや.tar.gzファイルなどの配布可能な形式にまとめます。
-
アプリケーションの配布: パッケージ化されたアプリケーションを、あなたのウェブサイトからの直接ダウンロード、アプリストアなど、適切なチャネルを通じてユーザーと共有します。
この手順に従えば、Crystalアプリが依存する共有ライブラリがアプリに含まれ、実行時に正しく位置付けられることが保証されます。これは、バイナリに静的にリンクされていなくてもです。これは共有ライブラリの慎重な管理を必要としますが、macOS上での配布を可能にします。
参考Makefile
APP_NAME = your_executable
LIBS_DIR = ./libs
SRC_DIR = ./src
BUNDLE_DIR = ./bundle
STARTUP_SCRIPT = startup.sh
# Build your application
build:
crystal build $(SRC_DIR)/main.cr -o $(BUNDLE_DIR)/$(APP_NAME)
# Copy and update library paths
libs:
mkdir -p $(BUNDLE_DIR)/$(LIBS_DIR)
# Use otool to identify and copy the required libraries, then update their paths
otool -L $(BUNDLE_DIR)/$(APP_NAME) | awk '/path_to_required_lib/ { system("cp " $$1 " $(BUNDLE_DIR)/$(LIBS_DIR)"); system("install_name_tool -change " $$1 " $(LIBS_DIR)/" $$1 " $(BUNDLE_DIR)/$(APP_NAME)"); }'
# Create startup script
startup-script:
echo '#!/bin/bash' > $(BUNDLE_DIR)/$(STARTUP_SCRIPT)
echo 'export DYLD_LIBRARY_PATH="$(LIBS_DIR):$$DYLD_LIBRARY_PATH"' >> $(BUNDLE_DIR)/$(STARTUP_SCRIPT)
echo './$(APP_NAME)' >> $(BUNDLE_DIR)/$(STARTUP_SCRIPT)
chmod +x $(BUNDLE_DIR)/$(STARTUP_SCRIPT)