DLLからlibファイルを作る (Windows版 TensorFlow for Cを例に)

# この記事について
Windowsの共有ライブラリであるDLLファイル(.dll)から、インポートライブラリ(.lib)を生成します。
拡張子が同じlibでも、静的リンク用の静的リンクライブラリ(.lib)と、DLLを動的リンクする際に必要なインポートライブラリ(.lib)は別物です。

## 想定するユースケース
第三者が配布しているDLLをリンクしたいが、DLLファイルしかなく、libファイルがない。そのため、「LNK1104 '*.lib'を開くことが出来ません。」といリンクエラーが発生する。そのため、DLLからlibファイルを生成する必要がある。

(ちなみに、自分でDLLをビルドした場合には、libファイルも一緒に生成されるので問題ありません)

## 本記事で対象とするライブラリ
TensorFlow for C (Google製のDeep Learning用フレームワークのC用ライブラリ) を例に、DLLからlibファイルを作ってみます。が、手順自体は他のライブラリ(DLL)でも同じです。

https://www.tensorflow.org/install/lang_c
https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.12.0.tar.gz

## 環境
- Windows 10 64-bit
- Visual Studio Community 2017 (15.9.7)

# libファイルを作る
## ライブラリを取得する
https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.12.0.tar.gz をダウンロードすると、以下のようなフォルダ構成になっています。
ポイントは、libフォルダの下にdllファイルしかない点です。このままだと、このライブラリを使用したビルドが出来なくて困ります。

```
├─include
│  └─tensorflow
│      └─c
│          └─ヘッダファイル
└─lib
│  └─tensorflow.dll
```

このフォルダを、C:\libtensorflow-cpu-windows-x86_64-1.12.0に解凍したとして、以後のコマンドを記載します。

## DLLのオブジェクト情報をダンプする
- スタートメニュ -> Visual Studio 2017 -> Developer Command Prompt for VS 2017 を開きます
- dumpbinコマンドによって、オブジェクト情報をダンプします。

```txt:コマンドプロンプト
cd C:\libtensorflow-cpu-windows-x86_64-1.12.0\lib
dumpbin /exports tensorflow.dll > tensorflow.def
```

```txt:tensorflow.def
Microsoft (R) COFF/PE Dumper Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file tensorflow.dll

File Type: DLL

  Section contains the following exports for libtensorflow.so

    00000000 characteristics
    5BDBAEF0 time date stamp Fri Nov  2 10:57:04 2018
        0.00 version
           1 ordinal base
        3078 number of functions
        3078 number of names

    ordinal hint RVA      name

          1    0 01841AA0 ??0?$MaybeStackArray@D$0CI@@icu_62@@AEAA@AEBV01@@Z
          2    1 023BC120 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@$$QEAV01@@Z
          3    2 023BC180 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@H@Z
          4    3 023BC200 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@XZ
          5    4 023C5F90 ??0Appendable@icu_62@@QEAA@AEBV01@@Z
          6    5 023C5F90 ??0Appendable@icu_62@@QEAA@XZ
          7    6 0245DC70 ??0BreakIterator@icu_62@@IEAA@AEBV01@@Z
          8    7 0245DCD0 ??0BreakIterator@icu_62@@IEAA@AEBVLocale@1@0@Z
          9    8 0245DD20 ??0BreakIterator@icu_62@@IEAA@XZ
         10    9 02399020 ??0ByteSink@icu_62@@QEAA@XZ
~略~
```

## ダンプしたオブジェクト情報から、defファイルを作る
先の手順で生成されたtensorflow.defファイルはtensorflow.dllの情報が記載されています。この中から、関数のシンボル情報だけを選びます。
具体的には、name列の関数名を矩形選択して、以下のようなdefファイルを作成します。

```txt:tensorflow.def
LIBRARY tensorflow
EXPORTS
 ??0?$MaybeStackArray@D$0CI@@icu_62@@AEAA@AEBV01@@Z
 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@$$QEAV01@@Z
 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@H@Z
 ??0?$MaybeStackArray@D$0CI@@icu_62@@QEAA@XZ
 ??0Appendable@icu_62@@QEAA@AEBV01@@Z
 ??0Appendable@icu_62@@QEAA@XZ
 ??0BreakIterator@icu_62@@IEAA@AEBV01@@Z
~略~
```

全文はこちら https://gist.github.com/take-iwiw/48f5be3365d3b2dc071db3f0f9351040

## ｄefファイルからlibファイルを作る
再度Developer Command Prompt for VS 2017 を開き、libコマンドによってlibファイルを作ります。

```txt:コマンドプロンプト
lib /def:tensorflow.def /machine:x64
```

tensorflow.libファイルが生成されたら成功です。