Condaパッケージの作成方法

# Condaパッケージの作成方法

ユーザがホームディレクトリ以下に Anaconda Python をインストールしていれば、
 Python だけなく Conda パッケージで提供されているアプリケーションやライブラリなども簡単に利用できるようになります。

この資料は Anaconda Python でのCondaパケージの作成方法について Linux を対象にしてまとめた資料です。

## Condaパッケージ

Python のパッケージでは PyPI(Python Package Index) で配布されているパッケージが知られています。
これらは pip コマンドでインストールすることができるものです。

**pip コマンドでのインストール例**

```
$ pip install shpinx
```

PyPIのパッケージは setuptools というパッケージングツールで作成するのですが、若干クセのあるパッケージ作成方法になっているため、
使い勝手に少し難があります。

Anaconda Python では、Condaコマンドでパッケージを追加/削除することができるようになっていて、簡単なパッケージ作成方法が提供されています。

Conda パッケージは、次の場所からダウンロードされます。

  * defaults(デフォルトリポジトリ):
    - https://repo.continuum.io/pkgs/
  * Anaconda Cloud(公開されている寄贈リポジトリ):
    - https://anaconda.org/

## Condaパッケージの作成準備

Conda パッケージをビルドするためだけであれば、
miniconda で構いません。

 * miniconda のダウンロードサイト
   - https://repo.continuum.io/miniconda/

**minicondaのインストール方法**

```
$ curl -s -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
$ bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/conda/x64
$ $HOME/conda/x64/condabin/conda init bash
$ exec $SHELL -l
```

次に、Anaconda Python の root 環境に
conda-build パッケージをインストールします。

```
$ conda install -n base conda-build
```

conda-build は最新バージョンの使用が推奨されています。
インストールした後でも次のように更新することができます。

```
$ conda upgrade -n base conda
$ conda upgrade -n base conda-build
```

## conda-build のディレクトリ構成

Miniconda3 を $HOME/conda/x64 以下に Miniconda3 をインストールしている場合は、
conda-build は次のディレクトリにファイルを置きます。

```
$HOME/conda/x64/conda-bld/
├── git_cache           -- git でダウンロードしたソース
├── hg_cache            -- mercurial でダウンロードしたソース
├── linux-64            -- condaパッケージ(x86_64: システム依存)
├── linux-ppc64le       -- condaパッケージ(ppc64le: システム依存)
├── noarch              -- condaパッケージ(noarch)
├── src_cache           -- curlでダウンロードしたソース
└── svn_cache           -- subversion でダウンロードしたソース
```

レシピ(詳しくは後述)に従ってパッケージがビルドされて、パッケージをインストールすると通常次のディレクトリに展開されます。

```
$HOME/conda/x64
├── bin
├── etc
├── lib
├── include
├── man
└── share
```

conda パッケージにしておけば、ユーザのホームディレクトリ以下にユーザ権限でパッケージを追加/削除できるようになるわけです。

## 既存パッケージからCondaパッケージに変換

conda skeleton コマンドを使うことで、CPAN, CRAN, luarocks.org, PyPI にある既存のパッケージを Condaパッケージに変換することができます。

 * cpan -- Perl
   - CPAN(Perl Archive Netowkr / cpan.org)
 * cran -- R
   - CRAN(Comprehensive R Archive Network / cran.r-project.org)
 * luarocks -- LUA
   - luarocks.org
 * pypi - Python
   - Python Packaging Index (PyPI / pypi.python.org)

例えばPyPI で配布されている pyinstrument をCondaパッケージにするためには次のようにコマンドを実行します。


```
$ conda skeleton pypi autopep8
Using url https://pypi.python.org/packages/0a/fc/c541b2fa1b244e0484216076b95468dc011ae90016b8f37333a24a11e468/autopep8-1.3.2.tar.gz (105 KB) for autopep8.
Downloading autopep8
INFO:fetch.start:('autopep8-1.3.2', 107915)
INFO:fetch.update:16384
INFO:fetch.update:32768
INFO:fetch.update:49152
INFO:fetch.update:65536
INFO:fetch.update:81920
INFO:fetch.update:98304
INFO:fetch.update:107915
INFO:fetch.stop:None
Unpacking autopep8...
done
working in /tmp/tmptgwzsstsconda_skeleton_autopep8-1.3.2.tar.gz

The following NEW packages will be INSTALLED:

    openssl:    1.0.2l-0           
    pip:        9.0.1-py35_1       
    python:     3.5.3-1            
    pyyaml:     3.12-py35_0   hpcs 
    readline:   6.2-2         local
    setuptools: 27.2.0-py35_0      
    sqlite:     3.13.0-0           
    tk:         8.5.18-0           
    wheel:      0.29.0-py35_0      
    xz:         5.2.2-1            
    zlib:       1.2.8-3            

Applying patch: '/tmp/tmptgwzsstsconda_skeleton_autopep8-1.3.2.tar.gz/pypi-distutils.patch'
patching file core.py
Hunk #1 succeeded at 167 with fuzz 2 (offset 1 line).
Writing recipe for autopep8
INFO:conda_build.config:--dirty flag not specified.  Removing build folder after successful build/test.
```

実行するとカレントディレクトリにパッケージ名 sphinx のディレクトリが作成されて必要なファイルが作成されます。

```
$ ls autopep8/
bld.bat  build.sh  meta.yaml
```

これらのファイルは Conda パッケージのレシピと呼ばれます。

conda build コマンドにレシピが格納されているディレクトリを与えると、
Condaパッケージを作成することができます。

```
conda build autopep8
```

これを実行するとパッケージファイル(実はtarball)が作成されます。

```
/home/iisaka/conda/x64/conda-bld/linux-64/autopep8-1.3.2-py35_0.tar.bz2
```

## Condaパッケージの命名規則

Condaパッケージでは、今のような命名規則でパッケージファイルを作成します。

```
 パッケージ名-バージョン-ビルドタイプ_ビルド番号.tar.bz2
```

 * ビルドタイプ
   - py27: Python2.7用のパッケージ
   - py35: Python3.5用のパッケージ
   - py36: Python3.6用のパッケージ
   - py37: Python3.7用のパッケージ
   - py38: Python3.8用のパッケージ
   - py39: Python3.9用のパッケージ
   - noarch: アーキテキチャに依存しないパッケージ
   - なし: バイナリパッケージ
 * ビルド番号
   - 任意の数字: 通常は 0 から始め、リリースするたびに増加させる。

## 異なる Python バージョン用のCondaパッケージ

Miniconda3-4.3.14 をインストイールすると
デフォルトのPython のバージョンは 3.6 になります。
このプラットフォームで、
Python 2.7 用のCondaパッケージを作成したいときは、
次のようにビルドします。

```
$ conda build --python=2.7 autopep8
```

ビルドした結果作成されるファイルは次のようになります

```
/home/iisaka//conda/x64/conda-bld/linux-64/autopep8-1.3.2-py27_0.tar.bz2
```

## チャネルの登録

チャネルの登録

例えばx86_64アーキテクチャのLinuxのマシンで、/home/iisaka/py3 以下にインストールした conda でパッケージをビルドすると次のディレクトリに保存されていきます。

 * '/home/iisaka/conda/x64/conda-bld/linux-64'
 * '/home/iisaka/conda/x64/conda-bld/noarch'

これをチャネルとして登録しておきましょう。

```
$ conda config --add channels file:///home/iisaka/conda/x64/conda-bld
```

## レシピ

レシピはつぎのファイルから構成されています。

 * meta.yaml -- パッケージメタデータ
 * build.sh  -- ビルドスクリプト
 * bld.bat   -- Windowsでのビルドスクリプト
 * run_test.{py, pl, sh, bat} -- テストスクリプト(省略可)
 * *.patch   -- パッチファイル

## パッケージメタデータ

パッケージメタデータは、パッケージ名やパッケージ番号、ビルド番号およびソースの入手方法などをYAMLフォーマットで記述したファイルで、ファイル名は meta.yaml になります。

```
# シャープ記号から行末までがコメント
package:
  name: パッケージ名
  version: バージョン番号

source:
  fn: 保存するファイル名
  url: ソースをダウンロードするURL
# チェックサム値はどれかひつとだけでもOK、省略してもOK
  md5: md5sum のチェックサム値
  sha1: sha1sum のチェックサム値
  sha256: sha256sum のチェックサム値

#   patches:    # パッチファイルのリスト(省略可)
#      - fix1.patch
#      - fix2.patch
build:
  number: 0       # ビルド番号

requirements:     # 依存するパッケージ名を記述する
  build:          # ビルド時に必要なパッケージ
    - python
    - setuptools

  run:            # 実行時に必要なパッケージ
    - python

about:      # パッケージの説明を記載する
  home:     # ソースを配布しているサイトやプロジェクトのURL
  license:  # ライセンスを記載  GPL2, GPL3, AGPL3, BSD, MIT など
  summary:  # 概要
  description: 説明
  license_family: BSD

```

source には url の替りに
path でレシピディレクトリからの相対パスも指定することができます。

バージン番号の書式は [PEP-440](https://www.python.org/dev/peps/pep-0440/)に従います。

プラットフォーム毎に requirements や ビルド番号 を変えたい場合は、
つぎのようにセレクタを指定して記述します。

```
build:
  number: 2 # [osx]
  number: 1 # [linux]

requirements:
  build:
    - ncurses
    - dbus # [osx]
    - jpeg # [linux]
```

セレクタは ```# [値]``` の書式で与え、値にはつぎのものが指定できます。

| セレクタの値   | 内容 |
|:-------------|:-----|
| x86     | IntelやADMのCPUでx86アーキテクチャ(32bit/64bit)のときに真 |
| x86_64  | IntelやADMのCPUでx86_64アーキテクチャ(64bit)のときに真 |
| linux   | プラットフォ ームがLinuxのときに真 |
| linux32 | プラットフォームがLinuxでPythonアーキテクチャが32ビットのときに真 |
| linux64 | プラットフォームがLinuxでPythonアーキテクチャが64ビットのときに真 |
| armv6l   | プラットフォームがLinuxでPythonアーキテクチャがarmv6lのときに真 |
| armv7l    | プラットフォームがLinuxでPythonアーキテクチャがarmv7lのときに真 |
| ppc64le    | プラットフォームがLinuxでPythonアーキテクチャがppc64leのときに真 |
| osx    | プラットフォームがOS X のときに真 |
| unix   | プラットフォームがUnix(OS X もしくはLinux)のときに真 |
| win   | プラットフォームがWindowsのときに真 |
| win32 | プラットフォームがWindowsでPythonアーキテクチャが32ビットのときに真 |
| win64   | プラットフォームがWindowsでPythonアーキテクチャが64ビットのときに真 |
| py XX    | Pythonの２文字バージョン表記(例 27) を与える  CONDA_PY の値と同じ) |
| py3k     | Python のメジャーバージョンが 3 のときに真 |
| py2k    | Python のメジャーバージョンが 2 のときに真 |
| py27    | Python のバージョンが 2.7 のときに真  |
| py35    | Python のバージョンが 3.5 のときに真  |
| py36    | Python のバージョンが 3.6 のときに真  |
| py37    | Python のバージョンが 3.7 のときに真  |
| py38    | Python のバージョンが 3.8 のときに真  |
| py39    | Python のバージョンが 3.9 のときに真  |
| np XX   | NumPy のバージョンの整数表記(例 111) CONDA_NPY の値と同じ |


### buildセクション
`build`セクションには次のような値を設定できます。

* number: ビルドナンバー
  インストールでは同じバージョンでもビルドナンバーが大きい方が選択されます。
* noarch: アーキテクチャに依存しないときに指定します。
　Python などでは 通常 py27, py37 などビルド時に使用したPythonのバージョンがパッケージ名に含まれますが、`noarch: python` とするとPythonのバージョンが含まれなくなります。
* skip: ビルドをしないことを知らせる
  セレクタと組み合わせて使用します。
  例： `skip: [win]`
* binary_relocation: バイナリファイルを再配置可能にするかどうか
  TrueのときにOSXのinstall_name_tool、Linux の patchelf を使ってバイナリファイルにパッチをあてます。
  多くの場合、コンパイルしたバイナリファイルにはビルドプレフィックスが rpath などで埋め込まれますが、この値をTrueにしていればインストール時に再配置可能になります。

* include_recipe: Falseのときはレシピファイルをパッケージに含めません。
デフォルトはTrue
* script_env: ビルドを行ったプラットフォームの環境変数を指定。
インストールするプラットフォームで使用できるとは限らないので注意が必要です。
例：

```
build:
  script_env:
    - MYENV
```
* scrit: ビルド方法を指定
Pythonなど１行でビルドできるようなときは、
ここにビルド方法を記述すればビルドスクリプトは不要になります。

例：

```
build:
  script: python setup.py install --single-version-externally-managed --record=record.txt

```
## ビルドスクリプト

ビルドスクリプトとはパッケージをビルドするために必要な
手順がかかれたスクリプトです。

```bash
#!/bin/bash

$PYTHON setup.py install

# Add more build steps here, if they are necessary.

# See
# http://docs.continuum.io/conda/build.html
# for a list of environment variables that are set during the build process.
```

メタデータに記述されているソースの入手情報に従って、
conda build コマンドがダウンロードを行って
作業ディレクトリに展開してからビルドスクリプトを呼び出します。

作業ディレクトリは $HOME/conda/x64/conda-build 以下に、
*パッケージ名-エポックタイム* のディレクトリ名で作成されます。

パッケージ作成時にインストールするときは、
作業ディレクトリ以下に、`_b_env_` で始まるディレクトリへ
にインストールされますう。

```
/home/iisaka/conda/x64/conda-bld/lftp_1485460657191
├── _b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_pl
│   ├── bin
│   ├── conda-meta
│   ├── include
│   ├── lib
│   ├── share
│   └── ssl
└── work
    └── lftp-4.7.5
```

## プリ/ポスト処理

condaパッケージがインストールされる前後で処理をさせたいときは、
次のスクリプトを作成しておきます。

 * pre-link.sh   -- パッケージがインストールされる前に実行される
 * post-link.sh  -- パッケージがインストールされた後に実行される
 * pre-unlink.sh -- パッケージがアンインストールされる前に実行される

これらのスクリプトは次の環境変数がセットされてから実行されます。

| 環境変数           | 内容 |
|:-:|:-:|
| PREFIX   |(--prefix で指定した)インストール先ディレクトリ |
| PKG_VERSION        | パッケージバージョン |
| PKG_BUILDNUM       | パッケージのビルド番号 |

プリ/ポスト処理では標準出力や標準エラー出力には何も出力されずに、
$PREFIX/.messages.txt に格納されます。

## Conda ビルド処理での環境変数

Conda では内部で次の環境変数が設定され、ビルドスクリプトなどで参照することができます。

| 環境変数           | 内容           |
|:------------------|:--------------|
| ARCH    | 32 か 64 のいずれか。   デフ ォルトは、condaが実行されたプラットフォームに依存して選ばれます。|
| CMAKE_GENERATOR | 現在のビルド環境用のCMakeジェネレータの文字列。           Unixシステムではこれは常に "Unix Makefiles" です。|
| CONDA_BUILD=1    | 常に１がセットされます。 |
| CPU_COUNT    | CPU数 (multiprocessing.cpu_count() で返される値) |
| SHLIB_EXT    | シェアードライブラリの拡張子 |
| DIRTY    | conda build コマンドに --dirty フラグが渡されれば １に設定されます。        条件付きでビルドスクリプトの一部をスキップさせるために使用できます。    (ダンロード、展開、レシピの開発のときに時間短縮のために繰り返す必要がない>ようなもの)
| HTTP_PROXY    | シェルで設定されている環境変数を継承します。|
| HTTPS_PROXY   | シェルで設定されている環境変数を継承します。|
| LANG    | あなたのシェルで設定されている環境変数を継承します。|
| MAKEFLAGS   | あなたのシェルで設定されている環境変数を継承します。         2つのCPUを使ってビルドするための -j2 など、 make に追加する引数。|
| NPY_VER    | ビルド対象のnumpyバージョン(CONDA_NPY環境変数や --nunmpy で設定) |
| PATH   | あなたのシェルで設定されている環境変数を継承します。 $PREFIX/bin が追加されます。|
| PREFIX    | (--prefix で指定した)インストール先ディレクトリ)|
| PKG_VERSION   | パッケージのバージョン |
| PYTHON   | ビルド環境内のPython実行ファイルへのパス。 |
| R   | ビルド環境内のR実行ファイルへのパス。   R はビルド要件としてリストされているときだけインストールされます) |
| RECIPE_DIR   | レシピのディレクトリ |
| SP_DIR   | Python の site-packages へのパス |
| SRC_DIR  | ソースが展開(あるいはclone)されたパス      もしソースファイルが認識できる拡張子(.zip, .tar, .tar.gz, .tar.bz2, .tar.xz ) ではないとき、ソースファイルがコピーされたディレクトリへのパスになります。 |
| STDLIB_DIR      | Python 標準ライブラリへのパス  |
| PKG_CONFIG_PATH | pkgconfig ディレクトリへのパス |
| LD_RUN_PATH     | `<build_prefix>/lib`  |

## git での環境変数

source に `git_url` や `path` で git リポジトリを指定したときは、次の環境変数も設定されます。

| 環境変数           | 内容               |
|:------------------|:------------------|
| GIT_BUILD_STR     | GIT_DESCRIBE_NUMBER と GIT_DESCRIBE_HASH を下線(_)でつなげた文字列。 |
| GIT_DESCRIBE_HASH   | git describe --tags で表示される現在のコミットショートハッシュ値 |
| GIT_DESCRIBE_NUMBER  | 直近のタグからのコミット数を示す文字列 |
| GIT_DESCRIBE_TAG  | 現在のコミットからの最新のタグを表す文字列        (git describe --tags の出力) |
| GIT_FULL_HASH   | 現在のHEADの完全なSHA1値を示す文字列 |


## mercurial での環境変数

source に mercurial リポジトリを指定したときは、
次の環境変数も設定されます。


| 環境変数           | 内容                     |
|:------------------|:------------------------|
| HG_BRANCH  | 現在のアクティブブランチを示す文字列 |
| HG_BUILD_STR   | HG_NUM_ID と HG_SHORT_ID を下線(_)でつなげた文字列 |
| HG_LATEST_TAG   | 現在のコミットからの最新のタグを示す文字列 |
| HG_LATEST_TAG_DISTANCE   | 最新のタグからのコミット数を示す文字列 |
| HG_NUM_ID   | レビジョン番号を示す文字列 |
| HG_SHORT_ID   | コミットハッシュを示す文字列 |

## 環境変数の継承

Linuxのプラットフォームでは、上記以外に conda build を呼び出した環境で、
継承される変数はありません。 meta.yaml に追加することで、
継承させる環境変数を追加することができます。

```
build:
  script_env:
   - TMPDIR
   - LD_LIBRARY_PATH # [linux]
```

継承する変数がビルド時のシェル環境から欠落していた場合、
その変数は未割り当てのままですが、
値が未設定ということを示す警告が表示されます。

注：環境変数を継承すると、
他の人がレシピを使ってソースからバイナリを再現することが困難になることがあります。
この機能は慎重に使用するか、まったく使用しないようにしください。


## ビルド処理に影響を与える環境変数

| 環境変数           | 内容                  |
|:------------------|:---------------------|
| CONDA_PY   | 27, 34 または 35 を与えます。      パッケージをビルドするためのPython のバージョンです。|
| CONDA_NPY   | 19, 110 または 111 を与えます。     パッケージをビルドするときに使われる numpy のバージョンです。|
| CONDA_PREFIX   | /path/to/conda/env のようにパッケージを構築するときに使用されるconda環境へのパス    |

## ビルドフィーチャーでの環境変数

フィーチャーは同じ名前とバージョンが同じでも、
パッケージの違いを登録できる仕組みです。
track_features で指定されたパッケージが合わせてインストールされます。

フィーチャーはパッケージそのものではなく、
パッケージがインストールされている環境の特徴といったものです。
たとえば、mklが track_features で指定されていると、
通常の numpy は削除されて、mkl フィーチャーされた numpy パッケージがインストール
されるなど、conda が指定されたフィーチャーに応じて自動的に変更するためにです。

| 環境変数           | 内容 |
|:------------------|:------|
| FEATURE_NOMKL | パッケージをビルドするときに nomkl フィーチャーを与える。0 でオフ、１でオン |
| FEATURE_DEBU | パッケージをビルドするときに debug フィーチャーを与える。0 でオフ、１でオン|
| FEATURE_OPT | パッケージをビルドするときに opt フィーチャーを与える。0 でオフ、１でオン| 

## ビルドでのコツ

あるパッケージをビルドしようとすると依存関係のある複数のパッケージを
ビルドする必要がでてくる場合がありきます。

レシピのディレクトリ名をメタファイルで指定したパッケージ名と同じしておきます。

こうすると、パッケージビルドをしたときに
依存関係のあるパッケージと同じディレクトリが
カレントディレクトリにあれば、
自動的にこのパッケージをビルドしてくれます。

## PGIコンパイラをCondaパッケージにしてみよう

PGIコンパイラは2016年からコミュニティー版は無償で使えるようになったので、
これをCondaパッケージにしてみましょう。

### numactl パッケージ

はじめに、PGIコンパイラで必要になる numactl パッケージを作ります。

パッケージ名 numactl と同じディレクトリを作成して、
そこにメタデータファイルとブルドスクリプトを配置します。


```
$ mkdir numactl 
```

**メタデータファイル**

```
package:
    name: numactl
    version: 2.0.11

source:
    fn:  numactl-2.0.11.tar.gz
    url: https://github.com/numactl/numactl/archive/v2.0.11.tar.gz
    md5: b56d2367217cde390b4d8087e00773b8

requirements:
    build:
      - m4
      - autoconf
      - automake
      - libtool
      - pkg-config
    run:

about:
    home: http://oss.sgi.com/projects/libnuma/
    summary: NUMA support for Linux
    license: GPL2.0
```

**ビルドスクリプト**

```bash
#!/bin/bash

export CFLAGS="${CFLAGS} -I${PREFIX}/include"
export CXXFLAGS="${CFLAGS}"
export CPPFLAGS="-I${PREFIX}/include"
export LDFLAGS="${LDFLAGS} -L${PREFIX}/lib"

bash autogen.sh

./configure --help
./configure \
    --prefix="${PREFIX}"   \
    --enable-static

make -j${CPU_COUNT}
make install
```

numactl パッケージのビルド

```
$ conda build numactl
```

## PGIコンパイラ

メタファイルには jinja2 の表記が使えるので、
次のようにビルド時の環境変数の値によっで生成する
パッケージを切り替えるようにしています。

```
 依存パッケージのデフォルト値を設定

{% set require1 = "" %}
{% set require2 = "" %}
{% set numactl  = "" %}

# 環境変数HOMEの値を保持
{% set home = environ.get("HOME") %}

# 環境変数 PGI_COMPOMENT の値を保持
{% set component = environ.get("PGI_COMPONENT") %}

# PGI_COMPONENT で与えられた値によってパッケージ対象を分けている
{% if component == "openmpi" %}
{% set name = "pgi-openmpi" %}
{% set require1 = "- pgi-compiler" %}
{% elif component == "cuda80" %}
{% set name = "pgi-cuda80" %}
{% set require1 = "- pgi-compiler" %}
{% set require2 = "- pgi-java" %}
{% elif component == "cuda75" %}
{% set name = "pgi-cuda75" %}
{% set require1 = "- pgi-compiler" %}
{% set require2 = "- pgi-java" %}
{% elif component == "examples" %}
{% set name = "pgi-examples" %}
{% set require1 = "- pgi-compiler" %}
{% elif component == "java" %}
{% set name = "pgi-java" %}
{% else %}
{% set name = "pgi-compiler" %}
# コンパイラのときだけ numactl のパッケージを要求するようにする
{% set numactl = "- numactl" %}
{% endif %}

package:
  name: {{ name }}
  version: 17.4

source:
# 事前にPGI のサイトからダウンロードしたTARボールを$HOMEに保存しておく
  url: file://{{ home }}/pgilinux-2017-174-x86_64.tar.gz
patch:
  - fix-install.patch

build:
  number: 0
  binary_relocation: false

requirements:
  build:
    - perl
    {{ numactl }}
  run:
    {{ numactl }}
    {{ require1 }}
    {{ require2 }}

about:
  home: http://www.pgroup.com/products/community.htm
  license: PGI Eng-User License
  license_file: LICENSE.txt
  summary: "A no-cost license to a recent release of the PGI Fortran, C and C++ compilers and tools for multicore CPUs and NVIDIA Tesla GPUs, including all OpenACC, OpenMP and CUDA Fortran features."

```

ビルドスクリプトは次のようになります。

```bash
#!/bin/bash

# install スクリプトのパラメタを設定
export PGI_SILENT=true
export PGI_ACCEPT_EULA=accept
export PGI_INSTALL_DIR=${PREFIX}/pgi
export PGI_INSTALL_NVIDIA=false
export PGI_INSTALL_AMD=false
export PGI_INSTALL_JAVA=false
export PGI_INSTALL_MPI=false
export PGI_MPI_GPU_SUPPORT=false
export PGI_INSTALL_MANAGED=false

# インストール先ディレクトリを作成
[ -d ${PREFIX}/pgi ] || mkdir ${PREFIX}/pgi

# post-link.sh / pre-unlink.sh がレシピディレクトリにあれば削除しておく
[ -f ${RECIPE_DIR}/post-link.sh ]  && rm -f ${RECIPE_DIR}/post-link.sh
[ -f ${RECIPE_DIR}/pre-unlink.sh ] && rm -f ${RECIPE_DIR}/pre-unlink.sh
 パッケージ名に応じたファイルを展開する
case "${PKG_NAME}" in
*-cuda75)
    tar -zxvf install_components/linux86-64.pgicuda.tar.gz \
              -C ${PREFIX}/pgi
    rm -rf ${PREFIX}/pgi/linux86-64/2017/cuda/8.0
    exit 0
;;
*-cuda80)
    tar -zxvf install_components/linux86-64.pgicuda8.0-libnvvp.tar.gz \
              -C ${PREFIX}/pgi
    tar -zxvf install_components/linux86-64.pgicuda.tar.gz \
              -C ${PREFIX}/pgi
    rm -rf ${PREFIX}/pgi/linux86-64/2017/cuda/7.5
    exit 0
;;
*-compiler)
    export PGI_INSTALL_MANAGED=true
    export PGI_INSTALL_AMD=true
    # コンパイラのときだけ post-link.sh / pre-unlink.sh を有効にする
    [ -f ${RECIPE_DIR}/scripts/post-link.sh ]  && \
         cp ${RECIPE_DIR}/scripts/post-link.sh ${RECIPE_DIR}/post-link.sh
    [ -f ${RECIPE_DIR}/scripts/pre-unlink.sh ] && \
         cp ${RECIPE_DIR}/scripts/pre-unlink.sh ${RECIPE_DIR}/pre-unlink.sh
;;
*-openmpi)
    export PGI_INSTALL_MPI=true
    mkdir -vp workdir
    tar -zxvf install_components/openmpi-1.10.2_2017_x86_64.tar.gz \
              -C workdir
    tar -zxvf workdir/linux86-64.openmpi-1.10.2.tar.gz \
              -C ${PREFIX}/pgi/
    tar -zxvf install_components/scalapack-2.0.2_2017_x86_64.tar.gz \
              -C ${PREFIX}/pgi/

    mkdir -vp ${PREFIX}/pgi/modulefiles
    perl workdir/openmpi.pl \
         -libdir ${PREFIX}/pgi/linux86-64/2017/mpi/openmpi-1.10.2 \
         -openmpiver 1.10.2 \
         -install ${PREFIX}/pgi/modulefiles/ \
         -release 2017
    exit 0
;;
*-java)
    export PGI_INSTALL_JAVA=true
    mkdir -vp ${PREFIX}/pgi/linux86-64/17.4/java
    tar -zxvf install_components/common/jre-8u112-linux-x64.tar.gz \
       -C ${PREFIX}/pgi/linux86-64/17.4/java

    mkdir -vp ${PREFIX}/pgi/linux86-64/17.4/bin
    cp install_components/linux86-64/17.4/bin/*.jar \
       ${PREFIX}/pgi/linux86-64/17.4/bin
    cp install_components/linux86-64/17.4/bin/pgtjavarc \
       ${PREFIX}/pgi/linux86-64/17.4/bin
    exit 0
;;
*-example)
    tar -zxvf install_components/linux86-64.examples.tar.gz \
              -C ${PREFIX}/pgi
    exit 0
;;
esac

./install

# 不要なファイルを削除
rm -rf ${PREFIX}/pgi/linux86-64/17.4/cray
rm -rf ${PREFIX}/pgi/linux86-64/2017/cray
rm -rf ${PREFIX}/pgi/linux86-64/2017/examples/

[ "${PGI_INSTALL_MPI}" != "true" ] && \
    rm -rf ${PREFIX}/pgi/linux86-64/17.4/lib/scalapack

[ "${PGI_INSTALL_MPI}" != "true" ] && {
    rm -rf ${PREFIX}/pgi/linux86-5/17.4/bin/*.jar
    rm -rf ${PREFIX}/pgi/linux86-5/17.4/bin/pgtjavarc
}
```

レシピのディレクトリに `scripts/post-link.sh` と 
`scripts/pre-unlink.sh`  を作成しておきます。

**scripts/post-link.sh**

```bash
#!/bin/bash

mkdir -p ${PREFIX}/etc/conda/deactivate.d
mkdir -p ${PREFIX}/etc/conda/activate.d

cat <<EOF > ${PREFIX}/etc/conda/deactivate.d/${PKG_NAME}.sh
export PATH=\${PATH_pgi}
export MANPATH=\${MANPATH_pgi}
export LD_LIBRARY_PATH=\${LD_LIBRARY_PATH_pgi}
unset PATH_pgi
unset MANPATH_pgi
unset LD_LIBRARY_PATH_pgi
EOF

cat <<EOF > ${PREFIX}/etc/conda/activate.d/${PKG_NAME}.sh
export PGI=${PREFIX}/pgi/linux86-64/${PKG_VERSION}
export CC=\${PGI}/bin/pgcc
export FC=\${PGI}/bin/pgfortran
export F90=\${PGI}/bin/pgf90
export F77=\${PGI}/bin/pgf77
export CPP="\${PGI}/bin/pgcc -E"
export CXX=\${PGI}/bin/pgc++
#
export PATH_pgi=\${PATH}
export PATH=\${PGI}/bin:\${PATH}
#
export MANPATH_pgi=\${MANPATH}
export MANPATH=\${PGI}/man:\${MANPATH}
#
export LD_LIBRARY_PATH_pgi=\${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=\${PGI}/lib:\${LD_LIBRARY_PATH}
EOF

```

**scripts/pre-unlink.sh**

```bash
#!/bin/sh

rm -f ${PREFIX}/etc/conda/deactivate.d/${PKG_NAME}.sh
rm -f ${PREFIX}/etc/conda/activate.d/${PKG_NAME}.sh
```

メタデータファイルで指定した patch ファイル

**fix-install.patch**

```
diff -Nru pgilinux-2017-174-x86_64.orig/install_components/install pgilinux-2017-174-x86_64/install_components/install
--- pgilinux-2017-174-x86_64.orig/install_components/install	2017-04-22 02:16:31.000000000 +0900
+++ pgilinux-2017-174-x86_64/install_components/install	2017-06-01 14:30:18.902018374 +0900
@@ -739,27 +739,7 @@
             cd ..
             rm -rf scalapack
 
-            numa_lib=""
-            if test -e /usr/lib64/libnuma.so ; then
-                numa_lib=/usr/lib64/libnuma.so
-            elif test -e /usr/lib64/libnuma.so.1 ; then
-                numa_lib=/usr/lib64/libnuma.so.1
-            elif test -e /lib64/libnuma.so ; then
-                numa_lib=/lib64/libnuma.so
-            elif test -e /lib64/libnuma.so.1 ; then
-                numa_lib=/lib64/libnuma.so.1
-            elif test -e /usr/lib/x86_64-linux-gnu/libnuma.so ; then
-                numa_lib=/usr/lib/x86_64-linux-gnu/libnuma.so
-            elif test -e /usr/lib/x86_64-linux-gnu/libnuma.so.1 ; then
-                numa_lib=/usr/lib/x86_64-linux-gnu/libnuma.so.1
-            fi
-            if test "numa_lib" != "" ; then
-                ln -sf $numa_lib $INSTALL_DIR/linux86-64/$REL_VERSION/mpi/openmpi-${OMPI_VERSION}/lib/libnuma.so
-            else
-                echo "WARNING: libnuma.so was not found on your system!"
-                echo "Open MPI requires libnuma.so to function correctly."
-                echo "Please install libnuma.so from your Linux distribution onto this system."
-            fi
+            numa_lib="${PREFIX}/lib/libnuma.so"
 
             if test "$ans" != "y" -a "$ans" != "yes" ; then
                 mpi_wrapper="$INSTALL_DIR/linux86-64/$REL_VERSION/mpi/openmpi-${OMPI_VERSION}/bin/env.sh"
```

> 注意：
Anaconda/Miniconda は 2020年9月30日に[ライセンスを改版](https://legal.anaconda.com/policies/en/#terms-of-service)していて、商業利用の場合は anaconda リポジトリを利用することができなくなりました。
miniconda の代わりにコミュニティーベースで運営されている conda-forge リポジトリを参照する [miniforge](https://github.com/conda-forge/miniforge) を使用するようにしてください。


## 参考資料

* Anaconda Python
  - https://repo.continuum.io/
* Conda building package
  - https://conda.io/docs/building/build.html
* PGI Compiler Community Edition
  - http://www.pgroup.com/products/community.htm