64bit Anaconda に cvxopt をインストールする

# 概要
Windowsで 64bit版 の [Anaconda](https://www.continuum.io/) に [cvxopt](http://cvxopt.org/) をインストールしようと思ったら非常に苦労したので作業内容をまとめる．

cvxopt のドキュメントには Windows への[インストール方法](http://cvxopt.org/install/index.html#building-cvxopt-for-windows) が書かれている．しかし，32bit 版の Python を想定しているらしく，ドキュメント通りにすんなりとインストールは出来ないので注意．本稿は，このドキュメントに沿って変更すべき点をまとめる．

# 想定環境
- Windows 10 (64bit)
- Anaconda for 64bit Windows (Python2.7)
- MinGW (64bit)

これらは既にインストールされているものとする．

なお，以降の作業は専用のディレクトリを作って，その中で行うものとする．例として `D:\glpk` 内で行う場合は，次のようにすればコマンドプロンプトを開くことができる．
![84CEE4CD-2BB7-40D7-B2EA-4A2596B8E1A2.png](https://qiita-image-store.s3.amazonaws.com/0/62253/49fa3f43-9ac3-b9c9-2c65-dbf49b1bb094.png)

# 依存ライブラリの準備
これは [ドキュメント](http://cvxopt.org/install/index.html#building-cvxopt-for-windows) 通りで良い．

## BLAS
[BLAS のソースファイル](http://www.netlib.org/blas/blas.tgz) をダウンロードする．そして，コマンドプロンプトから次のコマンドを実行する．

```shell-session
$ tar -xvf blas.tgz
$ cd BLAS-3.5.0
$ sed 's/_LINUX/_WIN/' make.inc -i
$ make && cp blas_WIN.a ../libblas.a
$ cd ..
```

ただし，2行目のディレクトリ名は取得した BLAS ソースファイルのバージョンによって変わるので適宜読み替える．

## LAPACK
[LAPACK のソースファイル](http://www.netlib.org/lapack/lapack-3.5.0.tgz) をダウンロードする．そして，コマンドプロンプトから次のコマンドを実行する．

```shell-session
$ tar -xvf lapack-3.5.0.tgz
$ cd lapack-3.5.0
$ cp make.inc.example make.inc
$ make lapacklib && cp liblapack.a ..
$ cd ..
```

もし，`libquadmath-0.dll` が無いと言われたら，[ここ](https://www.dllme.com/dll/download/26099/libquadmath-0.dll) からダウンロードして `MinGW/bin`(デフォルトだと ` C:\MinGW\bin` だと思われる) に置いてから上記コマンドを実行する．

# CVXOPT のコンパイル
ここからが本番．[CVXOPT のソースファイル](http://cvxopt.org/download) をダウンロードする．そして，コマンドプロンプトから次のコマンドを実行する．ファイル名やフォルダ名はバージョンによって変わるので適宜読み替える．

```shell-session
$ tar -xvf cvxopt-1.1.8.tar.gz
$ cd cvxopt-1.1.8/src
```

`setup.py` を開いて，

- 12行目あたりにある BLAS_LIB 変数の初期化を `BLAS_LIB = ['blas','gfortran']` に変更
- 9行目あたりにある BLAS_LIB_DIR 変数の初期化を `BLAS_LIB_DIR = '.'` に変更

次に，`distutils` パッケージの `cygwinccompiler` モジュールを編集する．Anaconda が `c:\Anaconda` にある場合，`c:\Anaconda\Lib\distutils\cygwinccompiler.py` を開く．もし，このファイルに `-mno-cygwin` という文字列があればすべて削除する．(手元の環境では無かった)

## libpython27.a と libmsvcr90.a の作成
後の処理で必要な，Linux の静的ライブラリ `libpython27.a` と `libmsvcr90.a` が，デフォルトでは用意されていないので Windows 用のライブラリから変換する．

まず，変換用のツールをインストールする．

```shell-session
$ mingw-get install pexports
```

次に，Anaconda ディレクトリ（例えば `c:\Anaconda`）にある `python27.dll` と `msvcr90.dll` を cvxopt の setup.py があるディレクトリにコピーする．

`libpython27.a` の作成は次のコマンドを実行すれば良い．

```shell-session
$ pexports python27.dll > python27.def
$ dlltool --dllname python27.dll --def python27.def --output-lib libpython27.a
```

`libmsvcr90.a` の作成はもう少し複雑である．まず，

```shell-session
$ pexports msvcr90.dll > msvcr90.def
```

を実行し，できた `msvcr90.def` をテキストエディタで開く．そして，304〜314行目付近にある，

- `_decode_pointer` という行を `;_decode_pointer` に
- `_encode_pointer` という行を `;_encode_pointer` に

修正する．その後，

```shell-session
dlltool --dllname msvcr90.dll --def msvcr90.def --output-lib libmsvcr90.a
```

を実行する．出来上がった `libpython27.a` と `libmsvcr90.a` は，Anaconda の `libs` フォルダにもコピーしておく．
その際，もし `libs` ディレクトリに `python27.lib` があれば `python27.lib_` に変更しておく．

## ソースコードの修正
オリジナルのソースコードのままではエラーが出るので，次のファイルを修正する必要がある．

### src/C/cholmod.c
31行目付近の

```c:cholmod.c
/* defined in pyconfig.h */
#if (SIZEOF_INT < SIZEOF_LONG)
#define CHOL(name) cholmod_l_ ## name
#else
#define CHOL(name) cholmod_ ## name
#endif
```

を

```c:cholmod.c
/* defined in pyconfig.h */
// #if (SIZEOF_INT < SIZEOF_LONG)
#define CHOL(name) cholmod_l_ ## name
// #else
// #define CHOL(name) cholmod_ ## name
// #endif
```

に修正．

### src/C/SuiteSparse/SuiteSparse_config/SuiteSparse_config.h
155行目付近にある下記のコードを削除する．

```c:SuiteSparse_config.h
#ifndef NTIMER
#ifdef _POSIX_C_SOURCE
#if    _POSIX_C_SOURCE >= 199309L
#define SUITESPARSE_TIMER_ENABLED
#endif
#endif
#endif
```

### src/C/amd.c
27行目付近にある，

```c:amd.c
#if (SIZEOF_INT < SIZEOF_LONG)
#define amd_order amd_l_order
#define amd_defaults amd_l_defaults
#endif
```

を

```c:amd.c
//#if (SIZEOF_INT < SIZEOF_LONG)
#define amd_order amd_l_order
#define amd_defaults amd_l_defaults
//#endif
```

に修正．

## コンパイルとインストール
ここまでして，ようやく次のコマンドでコンパイルできる．

```shell-session
$ python setup.py build --compiler=mingw32
```

インストールするためには，Anaconda の `Lib/distutils` に `distutils.cfg` を作成し次の内容を記入する．

```text:distutils.cfg
[build]
compiler=mingw32
```

その後，インストールする．

```shell-session
$ python setup.py install
```