中規模なC++の新しいプロジェクトを作るときにやるべきこと 2016年版
C++で新しいプロジェクトを作成するときに自分が定型的にやっていることを備忘録的にまとめました。完全に我流なので「こういうやり方もあるよ」などのアドバイスは歓迎です。
この記事中では各ファイルで説明が必要な部分だけを示しますが、全てのサンプルはgithubにおいてあります。
cpp-template: https://github.com/m-mizutani/cpp-template
前提
- UNIXベースのCLIで動作するアプリケーション or ライブラリを作る
- コンパイルはcmakeを使用する
- ファイル名はソースコードが
*.cc
、ヘッダファイルが*.hpp
だとする
- サンプルでは
cpptemplate
というプロジェクト名だと仮定します
プロジェクト用ファイルの準備
CMakeList.txt
*.cc
、ヘッダファイルが*.hpp
だとするcpptemplate
というプロジェクト名だと仮定しますCMakeList.txt
cmakeでビルドするための設定ファイルです。このサンプルではCLIアプリケーションを作る場合でも、単体テストを簡単にするため共有ライブラリを作成するようにしています。
# Library
ADD_LIBRARY(cpptemplate SHARED ${BASESRCS})
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
TARGET_LINK_LIBRARIES(cpptemplate pcap pthread rt)
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
TARGET_LINK_LIBRARIES(cpptemplate pcap pthread)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
自分はよくlibpcapおよびpthreadを利用したコードを書くので、上記部分で自分が作成するライブラリ以外にリンクするライブラリを記述しています。読めばだいたいわかると思いますが、最初のIF節以下がLinuxの場合、後のELSE節以下がLinux以外の場合(主にOSXを想定)と分けて記述できます。
src/*
ライブラリを構成するソースコードをsrc
以下に格納しています。ここではライブラリのメインとなるロジックを書くcpptemplate.cc
、そのヘッダフィアルであるcpptemplate.hpp
、そして独自のexceptionを書くcpptemlate/exception.hpp
という構成になっています。これはあくまで最小限の構成なので、必要に応じてファイルなどを追加します。
CMakeList.txtのサンプルに従うと、src/cpptemplate/
以下をincludeディレクトリ(例えば/usr/local/include
)にまるっとコピーするので、複数ヘッダファイルにわけて管理したい場合などはsrc/cpptemplate/
の下に作って、以下のようにインクルードしておくと、外部から利用する別のソフトウェアはcpptemplate.hpp
だけを読みこめば必要なヘッダファイルが一括して読み込まれるようになります。
(略)
#include "./cpptemplate/exception.hpp"
(略)
test/*
作成したライブラリを単体テストするためのコードを置くディレクトリです。GoogleTestを利用しています。
gtest*ファイルはGoogleTestからそのまま拝借したものになります。この3つのファイルはプロジェクト作成後にはいじらない想定です。
ではどうやってテストを追加するのかというと、以下の様なC++ソースコードをtest
以下に置いて、cmake .
を再度実行すると勝手にtest以下の*.cc
ファイルをglobしてコンパイル・リンクし、ビルドされる./bin/cpptemplate-test
を実行するとテストが実行されます。
#include "./gtest.h"
#include "../src/cpptemplate.hpp"
TEST (MyTest, test1) {
int a = 4;
int b = 3;
EXPECT_EQ(7, a + b);
}
ライブラリ自体はCMakeList.txt
でリンクするように記述していますが、ヘッダファイルは必要に応じて読み込ませる必要があります。
GoogleTestの書き方は以下を参照してください。
cli/*
CLIのアプリケーションを作成する場合、ここでコマンドラインのパースやライブラリの読み込みを実施します。ここであまりロジックを持たないように書くことで、ライブラリ側にロジックを寄せ、テストが記述しやすくなります。
ライブラリのみの開発の場合、このソースコードの記述は不要です。
README.md, LICENSE.md
書きましょう。特にこのサンプルに従う場合、GoogleTestについては自分のライセンス外となるので、記述に注意が必要です。
.gitignore
サンプルでは、CMake利用時に自動生成されるファイルを記載しています。
ファイルの準備完了
最終的に、以下の様なファイル構成になります。
% find . -type f | grep -v ".git"
./cli/main.cc
./CMakeLists.txt
./LICENSE.md
./README.md
./src/cpptemplate/exception.hpp
./src/cpptemplate.cc
./src/cpptemplate.hpp
./test/gtest-all.cc
./test/gtest.h
./test/main.cc
また、ここまでのファイルの作成とcpptemplate
から自分のプロジェクト名へのrenameを、サンプルのレポジトリに同梱されているcopy.py
によって実行できます。
$ ./copy.py mynewproj
のように実行すると、mynewproj
というディレクトリが作成され、その中にファイル名やコード内の名前がcpptemplate
からmynewproj
に変更されたファイル群がコピーされます。(ハイフンやアンダーバーの扱いが面倒だったので、そのあたりはあまり考慮してません。。)
ビルド
正しくファイルが生成されていれば、以下の手順でビルドされます。以下、OS X 10.11.6での実行結果です。
$ cmake .
-- The C compiler identification is AppleClang 7.3.0.7030031
-- The CXX compiler identification is AppleClang 7.3.0.7030031
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- No build type selected, default to Release
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/mizutani/Dropbox/works/cpp-template
$ make
Scanning dependencies of target cpptemplate
[ 14%] Building CXX object CMakeFiles/cpptemplate.dir/src/cpptemplate.cc.o
[ 28%] Linking CXX shared library lib/libcpptemplate.dylib
[ 28%] Built target cpptemplate
Scanning dependencies of target cpptemplate-bin
[ 42%] Building CXX object CMakeFiles/cpptemplate-bin.dir/cli/main.cc.o
[ 57%] Linking CXX executable bin/cpptemplate
[ 57%] Built target cpptemplate-bin
Scanning dependencies of target cpptemplate-test
[ 71%] Building CXX object CMakeFiles/cpptemplate-test.dir/test/gtest-all.cc.o
[ 85%] Building CXX object CMakeFiles/cpptemplate-test.dir/test/main.cc.o
[100%] Linking CXX executable bin/cpptemplate-test
[100%] Built target cpptemplate-test
$ ./bin/cpptemplate-test
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[ PASSED ] 0 tests.
$ ./bin/cpptemplate
Hello, Hello, Hello!
テストは何も入っていないので0 tests
となっていますが、追加すればここが増えていきます。
インストール
コンパイルができていればあとはそのまま自分のシステムへのインストールは可能です。場合によってsudo
コマンドなどによる特権が必要です。
$ make install
[ 28%] Built target cpptemplate
[ 57%] Built target cpptemplate-bin
[100%] Built target cpptemplate-test
Install the project...
-- Install configuration: "Release"
-- Up-to-date: /usr/local/lib/libcpptemplate.dylib
-- Installing: /usr/local/include/cpptemplate.hpp
-- Installing: /usr/local/include/cpptemplate/cpptemplate.hpp
-- Installing: /usr/local/include/cpptemplate/exception.hpp
-- Installing: /usr/local/bin/cpptemplate
開発サポートツールの利用
Travis CI
いわゆるIntegrationテストが必要なケースはあまりないかもしれませんが、複数環境でのテストを自動で実施してくれるのはとてもありがたい存在です。特にC/C++などの場合、同じUNIX系でもOSが違うとコンパイルが通ったり通らなかったりということがあるので、commitのたびに一通り確認してくれると安心感があります。
Travis CIそのものの設定方法などは別サイトなどを参照してもらうとして、C++のプロジェクトに必要な点だけここで解説します。
Travis CIを利用する場合はレポジトリのトップに.travis.yml
というファイルを設置します。
language: cpp
compiler:
- clang
- gcc
os:
- osx
- linux
上記のように記述することで、まずC++プロジェクトであることを宣言し、コンパイラとOSを選択できます。ここで選んだコンパイラとOSの全組み合わせ(といってもこの例では4パターンだけですが)をテストしてくれます。
before_install:
# update packages
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq -y; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -y build-essential cmake libtool libpcap0.8 libpcap-dev ; fi
# - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update ; fi
# - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install msgpack libev ; fi
ここで事前に必要なパッケージなどのインストール用コマンドを記述します。Travis CIはあまりC/C++などの利用を想定していないため、例えばLinuxの場合、ライブラリなどはaptを叩いて自前でインストールさせる必要があります。特にLinuxは素の状態だとコンパイルに必要なツール類も入ってないので、build-essential
やcmake
も忘れずにインストールします。
$TRAVIS_OS_NAME
にOS名がセットされているので、それによって地道に処理の分岐を記述します。
before_script:
- cmake .
script:
- make
最後に上記のようにコンパイルを実行します。もしテストコマンドも実行したほうがよければ、script
の項目に追記する形にします。
script:
- make
- ./bin/cpptemplate-test
cpplint
コーディング規約に従っているかをチェックしてくれるツールのC++版です。筆者はGoogleが提供しているcpplint.py
を利用しています。Googleが提供しているため、GoogleのC++スタイルガイドに従ったものになります。必ずしもGoogleのスタイルガイドが最も良いわけではないので、必要に応じて変更などをするのが良いと思います。
cpplint.py: https://github.com/google/styleguide/blob/gh-pages/cpplint/cpplint.py
cpplint.py
は単体で動くファイルなので、個別にダウンロードして自分のプロジェクトディレクトリに入れておくのでもよいかと思います。
今回のようなプロジェクトであれば以下のコマンドでチェックをしてくれます。(レポジトリのトップディレクトリで実行するとします)
$ ./cpplint.py --extensions=hpp,cc src/**/*.hpp src/**.cc src/**.hpp
もしcommit前にこのチェックを実行し、全てパスしないとcommitできないようにするためには.git
内に以下のファイルを用意します。
./cpplint.py --extensions=hpp,cc src/**/*.hpp src/**.cc src/**.hpp
cpplint.pyのパスは自分の環境に合わせて変更してください。pre-commitスクリプトの実行時ディレクトリは、レポジトリのトップディレクトリになります。
またEmacsで開発するのであれば、Google-c-style.elを導入するとインデントなどのスタイルが一致するので、おすすめです。package.el
を利用しているのであれば、MELPAからgoogle-c-styleをインストールし、以下の設定を~/.emacs.d/init.el
に記述すれば導入できます。
(add-hook 'c-mode-common-hook 'google-set-c-style)
完成
以上で新しいC++プロジェクトの用意が一通りそろいます。良いC++ codingライフを!
Author And Source
この問題について(中規模なC++の新しいプロジェクトを作るときにやるべきこと 2016年版), 我々は、より多くの情報をここで見つけました https://qiita.com/m_mizutani/items/e51e9f17c1a29dbf5669著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .