🚁

【Nim】32bitバイナリにコンパイルする方法

2022/07/21に公開

背景

64bitのWindows10上で、Nimのプログラムを32bitのdllにコンパイルをしたかったんですが、意外と手間取ったのでメモを残しておきます。
ちなみに、適当に--cpu:i386とか指定するとこんなエラーがでましたw

環境

Windows 10
Nim 1.6.6
choosenim v0.8.4

手順

1 i386コンパイラをダウンロード

まず、Nimを普通に入れた段階ではmingwの64bitしかインストールしてくれていないので、mingw32をダウンロードします。
Nim公式のCompiler dependencies からmingw32.7zをダウンロードしてください。

ダウンロードした7zを、mingw64フォルダがあるディレクトリに配置して、解凍してください。
Nimをchoosenimでインストールした場合は、以下のディレクトリのはずです。

C:\Users\USER_NAME\.choosenim\toolchains\

(choosenimでない場合はわかりませんがuserディレクトリの隠しフォルダだと思われます。.nimbleとか)

2 PATHを通す

そしたらmin32/binにPATHを通してください。

3 コンパイル😎

コンパイルしましょう。

a. .exeにコンパイル

hello.nim をコンパイルしたいとすると

  • --gcc.path=に32bitコンパイラへのパスを渡す
  • --cpuでi386アーキテクチャを指定する
nim c --gcc.path=PATH_TO_MINGW32\mingw32\bin --cpu=i386 -r hello.nim

b. .dllにコンパイル
toDll.nim をコンパイルしたいとすると
エントリーポイントとしてDllMainを定義している前提(参考)

  • --gcc.path=に32bitコンパイラへのパスを渡す
  • --cpuでi386アーキテクチャを指定する
  • --nomain を指定する
  • --app=libを指定することでdllを生成することを伝える。
nim c --app=lib --nomain --gcc.path=PATH_TO_MINGW32\mingw32\bin --cpu=i386 toDll.nim

オプションを自動指定する方法

これらを毎回指定するのはめんどくさいですよね?
実はプロジェクトディレクトリにnim.cfgファイルを作って指定したいオプションを書いておくと、いちいち指定しなくてもNimが自動で参照してくれるようになります。

# nim.cfg
--app: lib # exeの場合はいらない
--nomain # exeの場合はいらない
--gcc.path: "PATH_TO_MINGW32\mingw32\bin"
--cpu: i386

この状態で以下を実行すると、32bitのtoDll.dllが生成されます。

# exeの場合は -rをつけてもよい
nim c toDll.nim

最後に

言い忘れてましたが、32bitのdllをプロセスにinjectするにはlibgccをstatic linkする必要があるらしいです。
というわけで以下のプラグマを指定してください。

{.passL: "-s -static-libgcc".}

完成品

ボイラープレート作っておいたので参考にどうぞ。
https://github.com/pseuxide/nim-dll-bp

References

https://www.reddit.com/r/nim/comments/hkrpxm/32_bit_dll_in_nim/
https://nim-lang.org/docs/packaging.html

Discussion