Pythonを爆速にする「Cython」チュートリアル：　C++のコードがライブラリに依存しているとき。まずはCMake。

## 概要
C++ で書いているコードを、どうしてもPythonで呼べる形のライブラリにしたい。
ただ、そこにはCythonという大きな壁が立ちはだかっていた。

これは、Pythonを爆速にする「Cython」チュートリアル：　C++のコードがライブラリに依存しているとき。準備編  の続きになります。

コードは「[ここのgithub](https://github.com/kenmaro3/cython_practice)」にあげてあるので、ぜひご覧ください。

ミニマムなフォルダ構成として、こんな風になっていました。

## 状況説明

```bash
(myenv) user@~/Documents/cython_practice[master]> tree .
.
├── README.md
├── cpp_library
│   ├── TestClass1.cpp
│   └── TestClass1.h
├── cython
│   ├── my_library.pxd
│   ├── my_library.pyx
│   ├── test_class1.pxd
│   └── test_class1.pyx
└── setup.py
```

さらに前回の最後に、

```bash
wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz &&\
tar xvf gmp-6.1.2.tar.xz &&\
cd gmp-6.1.2 &&\
./configure --prefix=/usr/local/gmp/6_1_2 &&\
make && make check && make install
```
として、```gmp```ライブラリをインストールしました。



## 今回何をするか
今回は、まず

1. gmpライブラリを使った簡単なコードを書き、コマンドでコンパイルできることを確かめる。
2. そもそもC++のライブラリがどのようにインストールされており、どのように参照しているのか。
3. 依存関係を持つプログラムのコンパイルはCMakeを使ってどのように実行されるのか。
4. それがcython化するときにsetup.pyにどのように書かれるのか。

の、３まで解説していきます。
４に関しては、実際にCythonを使い依存関係を持ったC++プログラムをPythonから呼べるようにコンパイルしていきますが、それは次の記事で書きます。

##C++の依存関係
### そもそもC++のライブラリがどのようにインストールされており、どのように参照しているのか。

```gmp``` ライブラリをインストールした時のコマンドですが、

```./configure --prefix=/usr/local/gmp/6_1_2```

これは、のちの```make```でコンパイルした際にできたオブジェクトファイル、またプロジェクト内の大元となっているヘッダーファイルを、```make install```の際にどこに格納するか指定しているコマンドになります。

もし指定しない場合、オブジェクトファイルは基本的には```/usr/local/lib ```に保管され、必要なヘッダーファイル(基本的にライブラリに必要なプログラムファイルを全て含んだ一つのヘッダーファイル)は```/usr/local/include ```に保管されます。

この後、```make ```によりコンパイルが行われ、```make install ```によりコンパイルされたオブジェクトファイル、ヘッダーファイルが格納されます。

ここでは、実際にgmpライブラリのオブジェクトファイル、ヘッダーファイルが所定のフォルダに格納されていることを確かめます。

```bash
root@e96f489c2395:/# ls /usr/local/gmp/6_1_2/lib/
libgmp.a  libgmp.la  libgmp.so  libgmp.so.10  libgmp.so.10.3.2
root@e96f489c2395:/# ls /usr/local/gmp/6_1_2/include/
gmp.h
```
たしかに、オブジェクトファイルが```/usr/local/gmp/6_1_2/lib``` 下に、
ヘッダーファイルが```/usr/local/gmp/6_1_2/include```下に格納されています。


##cmake
###依存関係を持つプログラムのコンパイルはCMakeを使ってどのように実行されるのか。

したがって、これらを使用するプログラムを作成し、コンパイルするためには、これらを参照するようにしてコンパイルする必要があるのです。
まずは、単純にg++を用い、簡単なプログラムを書き、それをコンパイルして見ます。

```test.cpp
#include <iostream>
#include <gmp.h>

using namespace std;

void print_test(){
    mpz_t test;
    mpz_init(test);
    mpz_set_ui(test, 1);
    gmp_printf("print : %Zd \n", test);
}

int main(){
    print_test();
}


```

gmpライブラリについて知る必要はないですが、gmpは大きな整数の計算をするライブラリなので、これは単純にtestというオブジェクトに１を代入し、プリントするだけのプログラムです。

オプションを使ってライブラリを明示し、コンパイルします。もちろん、何もライブラリについて書かずにコンパイルしようとすると、参照エラーが出ます。

``` 
root@e96f489c2395:/from_local# g++ test.cpp
/tmp/ccZnVmvP.o: In function `main':
test.cpp:(.text+0x1f): undefined reference to `__gmpz_init'
test.cpp:(.text+0x30): undefined reference to `__gmpz_set_ui'
test.cpp:(.text+0x48): undefined reference to `__gmp_printf'
collect2: error: ld returned 1 exit status
```

となります。これはもちろん依存ライブラリを明示していないからですが、それを解決することで、

```
root@e96f489c2395:/from_local# g++ test.cpp -L/usr/local/gmp/6_1_2/lib -I/usr/local/gmp/6_1_2/include -lgmp
root@e96f489c2395:/from_local# ./a.out
print : 1 
```

のようにもちろんコンパイルできます。
この場合、```-L```はライブラリ（オブジェクトファイル）へのパスを明示しているものであり、
```-I```はヘッダーファイルへのパスを明示するコンパイルオプションです。

しかしながら、依存するライブラリが複数ある時や、書いているプログラムが複数に渡る時、このように```g++```でコンパイルするのはかなり面倒なことになります。そこで、CMakeLists.txtを用意し、コンパイルを簡単に行います。


それを実行するために、以下のような``` CMakelists.txt ```を作り、
```cmake . && make ```を使ってコンパイルするのが望ましいです。

ここでは、``` CMakelists.txt ```を次のように作成し、コマンドで``` g++ ```とオプションを使ってコンパイルする代わりに、``` cmake . && make```を使ってコンパイルしてみます。

```CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

project(TEST VERSION 1.1.0 LANGUAGES CXX)

# Executable will be in ../bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
set(CMAKE_CXX_FLAGS "-g -O0 -lgmp")


add_executable(test1 
    test.cpp
    )

target_sources(test1
    PRIVATE
)

target_include_directories(test1 PRIVATE /usr/local/gmp/6_1_2/include/)
target_link_libraries(test1 gmp /usr/local/gmp/6_1_2/lib)

```

```bash
root@e96f489c2395:/from_local# cmake .
-- Configuring done
WARNING: Target "test1" requests linking to directory "/usr/local/gmp/6_1_2/lib".  Targets may link only to libraries.  CMake is dropping the item.
-- Generating done
-- Build files have been written to: /from_local
root@e96f489c2395:/from_local# make 
[100%] Built target test1
root@e96f489c2395:/from_local# ./test1
print : 1 
```





##まとめ
C++のプログラムをcython化するときに必要な知識として、以下のことを行い、C++側で依存関係をもつプログラムのcython化を達成した。

- C++のプログラムを書くときにつまづきやすい、依存関係について解説した。
- CMakeを使ったC++のコンパイルについて解説した。


次の記事では、
- 依存関係を踏まえたsetup.pyの書き方について解説します。

今回はこの辺で。


おわり。