9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Artifactory / Conan を使った C++ のパッケージ管理

Posted at

はじめに

社内で開発しているプログラムのソースコードは GitHub や Bitbucket を使ってバージョン管理をすることが多いと思いますが、C++ などのプログラムをコンパイルしてできる成果物のライブラリについても同様にバージョン管理をしたくなることがあります。その際に弊社がどのようなやり方でそれを実現しているのかについて、まとめてみようと思います。

ライブラリのバージョン管理

ライブラリのバージョン管理を行う際は概ね次のような要件を満たす必要があります。

  1. バージョン番号に紐づけてライブラリをリポジトリに登録・取得ができること
  2. ライブラリを取得する際、それが依存するライブラリも同時に取得ができること
  3. 各言語のパッケージマネージャと連携が取れること

オープンソースにおける Python, Java 開発の場合、これらの要件は下記のように整理されています。

言語 成果物 リポジトリ パッケージマネージャ
Python wheel PyPI pip
Java JAR Maven Repository Maven

成果物リポジトリはプログラム言語だけでなく OS のパッケージ管理でも利用されています。

ツール/OS 成果物 リポジトリ パッケージマネージャ
CentOS rpm 各種 rpm リポジトリ yum
Ubuntu deb 各種 deb リポジトリ apt

オープンソースであればこれらを使用すればよいですが、社内限定で公開したいライブラリの場合は下記のような問題を考える必要があります。

  • プライベートリポジトリを作りたい
  • そもそも C++ にはデファクトの成果物リポジトリとパッケージマネージャがない

以前は成果物リポジトリを使ってなかったため、ライブラリの配布方法がチームによってまちまちになってしまい、共有しづらいという問題が起こっていました。このような問題を解消するために JFrog 社が提供している Artifactory を導入することにしました。

Artifactory とは

Artifactory は成果物をバージョン管理するためのリポジトリが作れるツールです。各言語のパッケージマネージャとも連携が可能で Python 向けのリポジトリを作り、pip で取得するといったことが可能になります。また JFrog 社は C++ のライブラリも Artifactory で管理できるように Conan という C++ 向けのパッケージマネージャを開発しているため、C++ 開発でも問題なく使用できます。

Artifactory は有料版と無料版がありますが、無料版で作れるのは C++, Java 用のリポジトリだけになります。以下で Artifactory の構築方法と Conan を使ったパッケージの作り方について簡単に説明します。

Artifactory のインストール

Artifactory は Docker イメージが提供されているので試しにコンテナを使って構築してみます。下記の通り、使用できる言語ごとにコンテナイメージが分かれています。

C++用のArtifactoryを構築する場合
$ docker run --name artifactory -d -p 8081:8081 docker.bintray.io/jfrog/artifactory-cpp-ce
Java用のArtifactoryを構築する場合
$ docker run --name artifactory -d -p 8081:8081 docker.bintray.io/jfrog/artifactory-oss

今回は C++ 用の Artifactory を使用することにします。起動には少し時間がかかるため、コンテナのログを確認しておくといいでしょう。

$ docker logs -f artifactory
...
2019-09-22 07:27:37,809 [art-init] [INFO ] (o.j.s.c.EncryptionWrapperFactory:33) - createArtifactoryKeyWrapper  EncryptionWrapperBase{ encodingType=ARTIFACTORY_MASTER, topEncrypter=BytesEncrypterBase{ Cipher='AES128',  keyId='33jpX'}, formatUsed=DotFormat, decrypters=[BytesEncrypterBase{ Cipher='AES128',  keyId='33jpX'}]}
2019-09-22 07:27:37,840 [art-init] [INFO ] (o.a.s.a.AccessServiceImpl:1590) - Successful register of Artifactory serviceId jfrt@01dnbxwq6mpcga0f7wdng10pmk in Access Federation
2019-09-22 07:27:37,859 [art-init] [INFO ] (o.a.w.s.ArtifactoryContextConfigListener:215) -
###########################################################
### Artifactory successfully started (13.921 seconds)   ###
###########################################################

2019-09-22 07:27:38,002 [art-exec-3] [INFO ] (o.a.c.CentralConfigServiceImpl:615) - Reloading configuration... old revision 0, new revision 1
2019-09-22 07:27:38,049 [art-exec-3] [INFO ] (o.a.c.CentralConfigServiceImpl:352) - Force updating new descriptor (old descriptor doesn't support diff). Old descriptor revision 0
2019-09-22 07:27:38,057 [art-exec-3] [INFO ] (o.a.c.CentralConfigServiceImpl:374) - New configuration with revision 1 saved.
2019-09-22 07:27:38,057 [art-exec-3] [INFO ] (o.a.s.ArtifactoryApplicationContext:515) - Artifactory application context set to NOT READY by reload
2019-09-22 07:27:38,185 [art-exec-3] [INFO ] (o.a.s.ArtifactoryApplicationContext:515) - Artifactory application context set to READY by reload
2019-09-22 07:27:38,185 [art-exec-3] [INFO ] (o.a.c.CentralConfigServiceImpl:633) - Configuration reloaded.

上記のようなログを確認したら http://localhost:8081 にアクセスすることで Web UI が表示されます。Web UI にアクセスしたら管理者アカウントを求められるので下記を入力してください。

ユーザ名 パスワード
admin password

ログインするとダイアログが表示されるので下記のように入力します。

  1. Welcome to JFrog Artifactory! : Next をクリック
  2. Configure a Proxy Server : Skip をクリック
  3. Create Repositories : Conan を選択して Create をクリック
  4. Artifactory on-boarding complete! : Finish をクリック

これで Artifactory の構築は完了です。ダイアログのフローで conan-local という Conan のリポジトリが作成されます。

Conan のインストール

続いて Conan をインストールします。Conan は Python で書かれているため pip でインストールします。

$ pip install conan

Conan が Artifactory にアクセスできるように Artifactory の URL を登録します。

$ conan remote add conan-local http://localhost:8081/artifactory/api/conan/conan-local

パッケージを作成する

下記のような C++ プログラムを Conan でパッケージにしてみます。

hello.h
# ifndef HELLO_H_
# define HELLO_H_

void Hello();

# endif  // HELLO_H_
hello.cpp
# include "hello.h"

# include <iostream>

void Hello() {
    std::cout << "Hello, World!" << std::endl;
}

Conan の設定ファイルを作成します。

$ conan new libhello/1.0.0

libhello/1.0.0 というのはパッケージ名が libhello でバージョンが 1.0.0 のパッケージを作成するという意味になります。

conanfile.py というファイルが生成されるので、下記のように編集します。

conanfile.py
from conans import ConanFile


class LibhelloConan(ConanFile):
    name = "libhello"
    version = "1.0.0"
    settings = "os", "compiler", "build_type", "arch"

    def package(self):
        self.copy("*.h", dst="include")
        self.copy("*.a", dst="lib", keep_path=False)

編集が終わったら下記コマンドでパッケージを作成します。

$ g++ -c hello.cpp
$ ar rcs libhello.a hello.o
$ conan export-pkg . admin/stable

パッケージは ~/.conan/data/libhello/1.0.0/admin/stable/package/<hash> 配下に作成されます。下記コマンドでもパッケージの存在を確認できます。

$ conan search libhello
Existing package recipes:

libhello/1.0.0@admin/stable

admin/stable というのはそれぞれ次のような値になります。

項目 意味
admin パッケージを作成するときのユーザ名
stable チャンネル名(stable, testing などのパッケージの属性を示す任意の文字列)

ユーザ名は本来であれば admin ではなく新規にユーザを作成したほうがいいです。作成方法については Artifactory ドキュメント を参考にしてください。

パッケージをアップロードする

パッケージができたらそれを Artifactory にアップロードしてみます。アップロードする前に Artifactory にはまだパッケージが存在してないことを確認しておきます。

$ conan search -r conan-local libhello
There are no packages matching the 'libhello' pattern

下記コマンドで Artifactory にアップロードします。

$ conan user -p password -r conan-local admin                   # ユーザを admin にする
$ conan upload libhello/1.0.0@admin/stable -r conan-local --all # パッケージをアップロード

成功したら Artifactory の左のアイコンから Artifacts を選択して conan-local 内のツリーを見ると libhello パッケージが登録されていると思います。conan search コマンドでも確認できます。

$ conan search -r conan-local libhello
Existing package recipes:

libhello/1.0.0@admin/stable

パッケージを使用する

libhello パッケージを使用する新たな conanfile.py を作成します。

$ conan new hello/1.0.0

conanfile.py を下記のように編集します。

conanfile.py
from conans import ConanFile


class HelloConan(ConanFile):
    name = "hello"
    version = "1.0.0"

    requires = (
        "libhello/1.0.0@admin/stable",
    )

    def imports(self):
        self.copy("*.h", src="include", dst="include")
        self.copy("*.a", src="lib", dst="lib")

requires フィールドに依存パッケージを記述します。ただし依存パッケージを書いてもパッケージの取得先は ~/.conan 配下になるので、ワークスペースにコピーするために imports() という関数でコピーしておく必要があります(ちょうど package() と逆の挙動になります)。

conanfile.py を作成したら libhello パッケージをインストールします。

$ conan install .

これで include, lib 配下にヘッダとライブラリが取り込まれます。次に下記のようなソースコードを用意します。

main.cpp
# include <hello.h>

int main() {
    Hello();
    return 0;
}

これをコンパイルすれば Hello, World! と出力されるプログラムができます。

$ g++ -Iinclude -Llib main.cpp -lhello -o hello
$ ./hello
Hello, World!

さいごに

今回はコンパイルは g++ を直接実行しましたが Conan は CMake と連携してコンパイルを行うこともできるため、プロジェクトを CMake で管理しておくことをおすすめします。

Artifactory / Conan を導入することで C++ 開発環境が劇的に改善できるのでぜひお試しください。もちろん他言語のパッケージ管理を目的に Artifactory を導入するのもおすすめです。弊社では JAR パッケージの管理でも Artifactory を導入しています。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?