2020年2月19日水曜日

ゲームプログラマのお仕事

ゲーム専用機やモバイル向けのゲームプログラマとして10年ほどやってきて,ゲームプログラマの仕事ってこういうのだったなぁ,という記録です.


  1. ゲームを作る
    当たり前の話ですが,ゲームプログラマの仕事の1つはゲームを作ることです.
    ただ,ゲームを作る,と言っても最近は色々な知識が必要なため,専門家に分かれていたりします.

    例えば,プレイヤーを作る人,ノンプレイヤーを作る人,UIの挙動を実装する人,カメラの動きを制御する人,AIを実装する人などなどです.

    プレイヤーやノンプレイヤーを作る人の場合,3Dモデルの読み込みや表示の制御,モーションの制御,モーションに合わせたサウンドの制御,移動による衝突の制御,など色々な知識が必要になったりもします.

    小規模なチームの場合,一人で色々なことをしなければならない場合もあります.

    最近は,ゲームエンジンが細かい部分はサポートしてくれますが,それでも,その機能はどういった機能で,どういったことが出来るのか,どう設定すれば良いのか,といった知識は必要なので,日々の学習は必須です.
  2. 仕様を決める
    仕様を決めるのは,プロデューサーだったり,ディレクターだったり,ゲームデザイナーだったり,プランナーだったり,そういった人たちの仕事だと思うかもしれませんが,最終的な仕様はソースコードに実装されたものなので,仕様を決めるのもプログラマの仕事になります.

    もちろん好き勝手に,こっちの方が面白そうだから,と変えたりするわけではありません.

    他の職種の人は,言った仕様がどれくらい実装が大変なのか,正確には分かりません.また,実現したいことと仕様が合致しているとも限りません.よくよく聞いてみると,別の方法で実装した方が楽だし,実現したいことも出来る,という場合もよくあります.

    プログラマからすると簡単な実装に思えることが,他の職種からは大変そうなことに思えるので,頼むのは申し訳ない,なんて思っている場合もあるのです.その逆もあります.

    ですので,お互いに足りていない情報を確認し合い,少なくともプレイ感覚を確認できる形まで実装するのに必要な仕様を固めるのもプログラマの仕事なのです.
  3. PCトラブルシューティング
    これは,ある程度規模の大きな会社だと,別途ヘルプデスクなどあるかもしれませんが,ちょっとしたPCのトラブル,例えば電源が付かないとか,そういった簡単なトラブルの解決も求められたりします.

    電池切れとか,電圧や電流が足りない,といった物理的な問題の場合もあるので,この辺は,ソフトウェアの問題ばかり調べていてドツボにはまることもあるかもしれません.
  4. ワークフローの構築
    どういうデータを作って,どういうフォーマットで,どこに提出するのか,というワークフローを構築するのもプログラマの仕事です.

    これは仕様を決めるのと似ていて,データを提出するアーティストやプランナーが作業しやすく,かつ,プログラマとしてもなるべく扱いやすいデータをどうするか決める必要があります.

    また,ミスしやすいデータがあるのであれば,手動でチェックする機能を用意したり,バージョン管理に載せる前に自動でチェックするための仕組みを用意するのもプログラマの仕事です.
  5. CI
    昨今流行りのCI環境の構築もプログラマの仕事です.なので,サーバーやファイヤーウォールなどに関する知識が必要になったりします.

    もちろん,大規模なプロジェクトや会社になれば専門家もいるでしょうが,小さい規模だと自分でやる必要があったりします.

    普段はデバッグ機能ありの状態でゲームを作っていて,いざ本番向けの状態のゲームをビルドしようとしたら,コンパイルエラーだらけ,という事態を避けるためにも,自動ビルドによるチェックなどは重要です.
  6. ライセンスチェック
    色々なミドルウェアを使ったり,組み込みたいという話になった場合の,最初の段階でのライセンスチェックもプログラマの仕事です.もちろん,最終的には法律の専門家にお任せするのが良いのですが,原則利用してはいけないライセンスのミドルウェアなどもあります.そういったものが要望に上がった場合,その時点で弾くのはプログラマの役目です.

    また,たまに拾ってきたソースコードを組み込んでしまうようなプログラマもいます.そういった人がいないか気にするためにも,多少はソフトウェアライセンスやオープンソースに関する知識も必要になります.
  7. エンジンの選定,改造,実装
    昨今,多くの企業がゲームエンジンを利用しているので,どのゲームエンジンを利用するのか,選定する作業が必要になります.エンジンによって得意なこと,不得意なことがあるので,ある程度色々なエンジンに関する知識が求められます.

    また,エンジンによっては改造可能な部分があったりするので,必要に応じて改造することも求められます.

    企業によっては,自社エンジンを持っている場合があり,そういった企業にいる場合は,エンジンの開発側に回ることもあります.
  8. 技術的なアドバイス
    例えば,モバイルであれば,今度出る端末はどんな特徴があって,作っているゲームのチェックのために購入する必要があるのか無いのか,といった相談をされることがあります.

    ゲーム専用機であれば,最近はマルチプラットフォームだったりするので,こういう仕様ってどのハードでも実現できるのか,といった相談を受けることがあります.
  9. スケジュールを立てる
    実装する内容が決まったら,どれくらいの期間で出来そうか,というスケジュールを立てる必要があります.これは,プログラマの経験や知識によって大きく変わるので,実際に担当者に予想を出してもらうのが重要です.
  10. スケジュールを調整する
    これは,全てのゲームプログラマがやるわけではないですが,他の職種の作業スケジュールに合わせて,実装する内容をいつまでに実装するのか,出来なさそうであれば,他の職種の作業タイミングをズラしてもらうのか,担当者を変えるのか,といったスケジュール調整も必要です.

    リードプログラマや,各専門分野のリードプログラマになると,こういったことも求められます.
  11. チーム内のコミュニケーションツールの整備
    最近は,Microsoft TeamsやSlackなどコラボレーションツールが充実してきていますが,利用できない場合には,自分たちでSlackクローンを用意したり,その他のコミュニケーションツールを導入する必要があったりします.
  12. ドキュメントの整備
    ゲームプログラマの仕事は,ゲームを作るだけではありません.開発環境を構築するためのドキュメント,ワークフローに関するドキュメント,セーブや課金に関する資料整備,開発中の便利機能やQAを楽にするための機能に関するドキュメントなど,思っている以上に文章を書くことがあります.

    このドキュメントを読むのはプログラマだけでなく,他の職種向けだったりする場合もあるので,これくらいは分かるだろう,という前提が間違っていることも多々あります.

    例えば,コマンドラインを実行してください,と書いても,プログラマ以外はそもそもコマンドラインって何なのか,ということだってあり得ます.

    プログラマ以外にも通じる文章の書き方を学ぶ必要があるわけです.
  13. バグの原因調査
    最終的に,プログラマ以外の作業が原因と判明することも多々ありますが,だいたいの原因不明のバグの調査は,まずプログラマがやることになります.

    例えば,キャラクターがおかしな動きをする,という話になったとき,そもそもモーションのデータがおかしいのか,モーションの指定がおかしいのか,はたまた特定の条件の場合のみモーションの計算がおかしいのか,と色々と原因が考えられます.

    データがおかしい,ということになった場合でも,じゃあどう直すのが良いのか,ということが分からない場合もあります.

    そのためにも,ゲームプログラマは,データの直し方,もある程度知っている必要があるのです.MayaやBlenderといったDCCツールの使い方は分からなくても,この関節の回転のデータがおかしいので,そのデータを直してみてください,というくらいなら出来るはずです.
  14. ツールの開発
    開発中に問題のあるデータが見つかった場合,それを一括で修正するツールを実装する場合があります.

    CIのために,自動でデータをチェックするツールを実装する場合もあります.

    他にも,開発中にはいろいろな理由で色々なツールを作ることがあります.

    プログラマしか使わないツールであれば,コマンドラインで作ってしまうのも手ですが,他の職種も扱うツールの場合,GUIがあった方が良いこともあります.その場合,さっとC#などでツールを作れる知識も必要になります.

    他にも,例えばddsの画像をpngに変換する必要がある,というようなデータフォーマットの変換ツールを作ることもあります.この辺はややこしいので、既存のツールを内包する形にすることが多いと思いますが,その場合,どういった既存のツールがあって,利用できそうか,という知識が必要になります.

    Excelなどを改造してツールにすることもあるので,VBAなんかの知識もあると役立ったりします.
  15. 流行りのゲームやアニメに関する情報源
    ふわっと,何かこういうイメージのゲームってあるか,という質問だったり,こういうアニメの表現って出来るか,であったり,何か他のものを参照するための情報を求められることもあります.

    この辺は,ゲームプログラマに限らないのですが,実装が絡んできそうな内容の場合,やはりプログラマに質問が来たりするので,実際に詳しく知っているわけではなくても良いのですが,特徴的なゲームだったり,アニメだったりは名前くらいは押さえておいたほうが良かったりします.
  16. 処理時間の改善
    FPS(1秒当たりの画面の更新回数)が低いと,カクカクとした動きに見えたり,反応が悪いように感じたりするので,時間がかかっている処理を改善するのもプログラマの仕事です.

    処理時間を短くするには,原因を調査するためのプロファイラの使い方の知識であったり,原因が分かった際の対処方法に関する知識が必要だったりします.

    例えば,特定のAPIの呼び出しがブロックしていて時間がかかっている場合,非同期に呼び出せるAPIが無いか,呼び出せるなら,その部分を非同期にできないか,といったことを考えたりします.

    他にも,そもそもアルゴリズムが悪い場合もあるので,ある程度,その分野の基本的なアルゴリズムは知っておいた方が良いでしょう.例えば,単純な幅優先探索に置き換えるだけで劇的な改善をしたこともあります.

    また,処理時間を短くするのは,何もゲームの中だけの話ではありません.ツールの起動にやたらと時間がかかったり,キャラクターの設定に関するデータの出力にやたらと時間がかかったり,といった場合を改善するのもプログラマの仕事です.

    それまで1分ほどかかっていた作業が数秒程度になった,なんてこともあります.
思い付く範囲でダラダラと書いてみたところ,結構な量になってしまった.

書いてみて,結構幅広い知識を求められるよなぁ,と.

もちろん,最初から全部知っていろというわけではないのですが,スペシャリストになるのが難しそうであれば,色々と知っていた方が選択肢は多くなるのかなぁ,という気がします.

2020年2月3日月曜日

Substance Designer入門 Lesson3-01のパラメータ

Substance Designer入門

この本を読んでいて,そのままだとサンプルと同じ感じにする方法が分からなかったので,サンプルを見ながら,この数値にすればOK,というのを抜き出してみました.

Lesson 3-01

葉っぱの筋を作る,に出てくるTransformation 2D

Specific ParametersのTransform Matrixで,Edit Matrixを選び,X1を1.6153,Y1を0,X2を0,Y2を0.7413に設定する.
Offsetは図の通りに.

Levelsは,Specific Parametersの一番右のアイコンを押して,数値を指定できる状態にして,Level Out Lowを1に(下側の黒に相当).Level Out Highを0.6717903に(下側の白に相当).

草を並べる,のところからいくつか数値が図と違うようです.Tile SamplerのX Amountは19です.

Sizeも,最終的にはXが3.85で,Yが0.8になっています.

また,ColorのColor Randomに0.3が入っています.

Maskに使うShapeは,Scaleが0.86,SizeのXが0.76,Yが1になっています.

Gradient Mapは同じようにするのが大変です.


  • Position 0
    • R: 150,G: 190,B: 105,A: 255
  • Position 0.041
    • R: 22,G: 28,B: 15,A: 255
  • Position 0.204
    • R:19,G: 27,B: 3,A: 255
  • Position 0.317
    • R: 26,G: 40,B: 13,A: 255
  • Position 0.470
    • R: 76,G: 90,B: 33,A: 255
  • Position 0.641
    • R: 148,G 165,B: 92,A: 255
  • Position 0.684
    • R: 139,G: 153,B: 90,A: 255
  • Position 0.737
    • R: 159,G: 173,B: 107,A: 255
  • Position 0.782
    • R: 152,G:165,B:109,A: 255
  • Position 0.822
    • R: 217,G: 232,B: 160,A: 255
  • Position 0.865
    • R: 162,G: 173,B: 114,A: 255
  • Position 0.943
    • R: 162,G: 173,B: 114,A: 255
草を切り抜く,の部分のLevelsはLevel in Mid(上の灰色)を0.05353075に設定します.

プログラマのサガなのか,サンプルとの差があると何が原因なのか,ついつい調べてしまいますが,Substance Designerはちゃんと数値にアクセスする手段も用意されているようです.

Substance Designer入門にはちゃんとサンプルデータが付いてきていて,そちらはコメント付きで分かりやすくなっているので,プログラマの場合,そのサンプルを見て,デフォルトから変更されている部分を抽出すれば,サンプルと同じものが出来て,安心できると思います.

2020年1月30日木曜日

CMakeのプロジェクトにGoogle Testを組み込む方法の解読

C++で単体テストをする場合の候補として,Google Testがあります.

公式ドキュメントには,CMakeを利用している既存のプロジェクトにGoogle Testを組み込む方法が書いてあるのですが,何をしているのかパッと分からなかったので,じっくり読んでみました.

まず,次のような構造を想定します.

  • CMakeLists.txt
    • srcとtestをadd_subdirectoryで追加
  • src (プロジェクトのソースコード)
  • test
    • GoogleTest.CMakeLists.txt.in
    • CMakeLists.txt
  • build (ビルド用フォルダ,バージョン管理外)
GoogleTest.CMakeLists.txt.inの内容は,ドキュメントにあるCMakeLists.txt.inと同じです.

testフォルダのCMakeLists.txtの1行目,configure_fileが解釈されると,次のような状態になります.

  • build
    • googletest-download
      • CMakeLists.txt
そして,このgoogletest-downloadの中のCMakeLists.txtは,configure_file実行時のCMAKE_CURRENT_BINARY_DIRで解釈されるので,次のような内容になります.

ExternalProject_Add(googletest
    ... 省略 ...
    SOURCE_DIR "buildへの絶対パス/googletest-src"
    BINARY_DIR "buildへの絶対パス/googletest-build"
)

次に,execute_processにより,ルートのCMakeLists.txtに対してビルド設定を生成する際に,googletest-download内のCMakeLists.txtが実行され,フォルダが次のような構造になります.

  • build
    • googletest-download
    • googletest-src
    • googletest-build
これで,googletestを組み込む準備ができたので,そのあとで単体テスト用のターゲットをadd_executableして,gtest_mainとリンクし,add_testでテストに登録しているわけです.

取り合えず,これでプラットフォーム気にせずにGoogle Testを導入しつつ,コードが書けそう.

2019年12月4日水曜日

Developer PowerShell for VS 2019をx64に切り替える方法

Visual Studio 2019から,Developer PowerShell for VS 2019,というものが付いてきます.

これで,PowerShellからcl.exeを使うためにゴニョゴニョしなくて済む,と思ったら,コンパイラが32bit環境になっていました.

次のコマンドで確認したときに,パスがHostx86のx86になっていました.

(gcm cl).Source

どうしても64bit環境が使いたいのですが,コマンドプロンプトについては,x86,x86からx64のクロスコンパイル,x64,x64からx86のクロスコンパイル,としっかり組み合わせが用意されているのに,PowerShellについては用意されていません.

そこで,Developer PowerShell for VS 2019のリンクのプロパティを見て,実際に何をやっているのか確認してみました.

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll""";Enter-VsDevShell インスタンスID}"

インスタンスIDの部分は,たぶん環境によって変わります.

どうやら,Enter-VsDevShellというものを呼び出しているようです.取り合えずヘルプを見てみましょう.

Get-Help -Detailed Enter-VsDevShell

非常に簡単なことしか書いていませんが,-DevCmdArgumentsというものがあることに気付きます.これに -help を渡してみます.

Enter-VsDevShell インスタンスID -DevCmdArguments -help

すると,どうやらvsdevcmd.batを裏で呼んでいるようです.これについても情報が少ないのですが,あれこれ調べた結果,-arch=x64を指定してやれば良さそうです.

Developer PowerShell for VS 2019のリンクのプロパティからリンク先を書き換えてみましょう.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll""";Enter-VsDevShell インスタンスID -DevCmdArguments -arch=x64}"

書き換えたら,そのリンクからPowerShellを起動します.そして,もう一度次のコマンドを実行します.

(gcm cl).Source

無事,Hostx64のx64が選択されています.

やってやりました!

via GIFMAGAZINE



ちなみにインスタンスIDは,書いてあるものを使えば良いのですが,間違えて消してしまったりした場合,vswhereというものを使えば見れるようです.

注意点として,どうもリンク先の長さに上限があるらしく,書き換え方次第では入りきらなくなるようです.

2019年12月3日火曜日

CMakeで生成したVisual C++のプロジェクトで例外を無効にする方法

CMake 3.15.5でVisual Studio 2019向けに生成したプロジェクトで,次のようなCMakeのコマンドを実行して確認する.

message("${CMAKE_CXX_FLAGS}")

すると,/EHscが入っていることが分かる.これを次のように削除する.

string(REPLACE " /EHsc" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

すると,プロパティページの「C/C++」の「コード生成」の「C++の例外を有効にする」が空欄になる.合わせて,「_HAS_EXCEPTIONS=0」をtarget_compile_definitionsで定義してやれば,例外を無効にできる.

他に何か良い方法があれば教えて欲しい.

コマンドラインからVisual Studioの仕組みを学ぶ2

前回はこちら
コマンドラインからVisual Studioの仕組みを学ぶ

マクロによるDebug版とRelease版の切り替え


さて,次のように_DEBUGの有無でデバッグ時とそれ以外で処理を変える,といったコードを書いたことはあるでしょうか?

#include <iostream>
using namespace std;

int main()
{
#if defined(_DEBUG)
    cout << "Debug" << endl;
#else
    cout << "Release" << endl;
#endif
}

この例だとあまり意味はないですが,例えば開発中のみデバッグ機能を有効にしたり,特別にログを出力するようにするなど,こういった書き方をすることは良くあります.

ところで,この _DEBUG というマクロはどこで定義されているのでしょうか? また,定義されていたとすると,デバッグ機能を無効にしたい場合は,わざわざ消さないといけないのでしょうか?

そんな面倒なことはしません.コマンドラインのオプションでマクロを定義することができます.これにより,コンパイル時にデバッグ有り版とデバッグ無し版を切り替えることができます.

マクロの定義には "/D マクロ" という書き方をします.

次のコマンドでは,_DEBUGが定義された状態でコンパイルします.
cl /EHsc /D _DEBUG main.cpp

一方,次のコマンドでは,_DEBUGが定義されていない状態でコンパイルします.
cl /EHsc main.cpp

ソースコードを読んでいて,どこにも定義されていないマクロに遭遇したことがあるかもしれません.そういったマクロは,このようにコンパイル時に定義されているのです.

Visual Studioのプロパティとしては,C/C++のプリプロセッサのプリプロセッサの定義になります.このプロパティは ; 区切りでマクロが定義されていて,コンパイル時にはそれを分解して,それぞれを /D と一緒にコンパイラに渡しているわけです.

プロパティの左上にある構成をDebugやReleaseで切り替えると,このプリプロセッサの定義,が変わることが分かります.

Visual Studioでは,DebugやReleaseといった目的やx64などのプラットフォームの組み合わせ毎に,こういった定義を設定することができて,その設定に合わせてコンパイラにマクロを渡してくれているわけです.

clangの場合,-D でマクロが定義できます.似ていますね.そして,clangを使っているXcodeでも,同じようにマクロを定義する項目があります.

まとめ

/D マクロ,でコンパイル時にマクロを定義した状態でコンパイルすることができます.
DebugやReleaseといった構成やx64などのプラットフォームを切り替えると,プロパティのプリプロセッサの定義が切り替わり,/D の形にしてコンパイラに渡してくれます.

おまけ

Windows.hを開いてみると,色々とコードを変更するためのマクロが書いています.特に,NOMINMAXは,次のようなコードがちゃんとコンパイルできるようにするために必要です.

#include <iostream>
#include <cmath>

int main()
{
 std::cout << std::min(1, 2) << endl;
}

どうしてNOMINMAXが必要なのか,実際に確かめてみると理解が深まるかもしれません.

ついでに,_USE_MATH_DEFINESについても調べておくと,役立つときがあるかもしれません.

2019年12月2日月曜日

コマンドラインからVisual Studioの仕組みを学ぶ



Visual Studioそのものについて解説した本や,Visual C++について解説した本はいくつかあります.ただ,Visual Studioの場合,C#前提だったり,Visual C++についての本でもC++のコードを書くことが前提だったりして,自分でライブラリを作ったり,他のライブラリを利用したりする場合の方法についてはあまり詳しくなかったりします.

このツイートの後に,コマンドラインを覚えれば,色々なIDEの設定などが分かるのでは,という話になったものの,そういった解説って無いよね,という話になったので,ちょっと書いてみようかと.

前提として,Visual Studio 2019でC++の開発環境が入っている前提とします.
また,cdやmkdirなど基本的なコマンドラインの機能についてはこの解説には含めないので,必要に応じて調べてみてください.

コマンドラインを使えるようにする

スタートメニューからVisual Studio 2019のフォルダを探し,Developer Command Prompt for VS 2019かDeveloper PowerShell for VS 2019を起動します.

起動したら,次のコマンドを実行してみましょう.

cl /?

この,cl というのがC++のコンパイラで,/?を渡すことで指定できるオプションの一覧を表示したわけです.

Visual C++の設定の多くは,このclに渡すオプションを生成するために使われます.

そして,ここが肝心なポイントなのですが,色々なC++コンパイラでコマンドラインから指定できるオプションには,共通の機能を提供するものが多々あるのです.

つまり,コマンドラインのオプションが分かっていれば,このオプションを設定するIDEの設定項目はどれか,という探し方ができるので,普段Visual Studioを使っていて,突然Xcodeを使うことになったとしても,何となく設定する方法が分かってしまうのです.

コンパイルしてみる

よくあるHello, Worldをコンパイルしてみましょう.

// main.cpp
#include <iostream>
using namespace std;

int main()
{
    cout << "Hello, World!" << endl;
}
cl main.cpp

コンパイルすると,何やら警告が出ます.着目するポイントは,warning(警告)という単語の直後のC4530という警告の番号です.これをGoogleなどで検索すると,Microsoftのドキュメントが表示されます.

他にもエラーや警告が出た場合,必ずその直後にこういったエラーの種類を示す番号が出ているので,Microsoftのドキュメントで検索してみましょう.エラーや警告の理由が分かれば,修正もしやすくなります.

詳細については省くとして,取り合えず/EHscを指定しろ,ということなので,次のように指定してみましょう.

cl /EHsc main.cpp

これで,問題なくコンパイルできました.同じフォルダにmain.exeとmain.objというファイルができているはずです.

さて,このobjってなんでしょう? これは,C++のソースコードをコンパイルした結果です.これに,標準ライブラリなどの機能をリンクさせて,最終的に実行可能ファイル(exe)になるのです.

簡単なソースコードの場合,コンパイルも一瞬で終わるので気になりませんが,大規模になってくるとコンパイル時間は数十分,数時間,場合によっては一晩かかったりするかもしれません.

できれば,変更した部分だけコンパイルするようにしたいところですよね.IDEは,objとcppを比較して,更新されている場合だけコンパイルする,といったことをすることで,コンパイル時間を短くする手助けをしてくれています.

単純に比較しているわけではなく,ヘッダファイルを書き換えた場合,そのヘッダファイルをインクルードしているcppも変更の対象にしてくれたり,と色々と賢くやってくれています.

ちなみに,この/EHscというのは,プロジェクトのプロパティのC/C++のコード生成のC++の例外を有効にする,で設定できる値です.

インクルードパスを指定する


さて,続いてインクルードパスについて解説します.まずは,次のような構造で必要なファイルを用意してください.

main.cppがあって,subフォルダがあって,その中にheader.hとsub.cppがある状態です.

|- main.cpp
|- sub
|   |- header.h
|   |- sub.cpp

それぞれのファイルの中身は次のようになります.

// sub/header.h
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED

int f();

#endif // HEADER_H_INCLUDED

// sub/sub.cpp
#include "header.h"

int f()
{
    return -1;
}

// main.cpp
#include <iostream>
#include "sub/header.h"

using namespace std;

int main()
{
    cout << f() << endl;
}

これをコンパイルしてみましょう.

cl /EHsc main.cpp sub/sub.cpp

いくつか注目するポイントがあります.

1つ目は,#includeの後の書き方に2種類あることです.一般的に,<と>で囲まれている場合,コンパイラが定義したパスからの相対パスでインクルードするファイルを探し,"で囲まれている場合,コンパイルしているファイルのある場所からの相対パスでインクルードするファイルを探した後に,コンパイラが定義したパスからの相対パスでインクルードするファイルを探します.

2つ目は,sub/header.hという書き方です.1つ目の説明でも書いたように,インクルードするファイルの指定は相対パスになるので,フォルダを指定して,そのフォルダ以下にあるファイルを指定することも可能なのです.

さて,先ほどからコンパイラが定義した場所から,と言っていますが,それを追加する方法があります.まずは,main.cppを次のように書き換えてみましょう.

// main.cpp
#include <iostream>
#include 
using namespace std; int main() { cout << f() << endl; }

次のように,/I subを追加すると,コンパイルできます.

cl /EHsc /I sub main.cpp sub/sub.cpp

/I の後にパスを書くことで,コンパイラがインクルードするファイルを探すパスのリストに追加することができます.

一般的には,他のライブラリを利用する場合,そのライブラリのヘッダファイルなどは一か所にまとまっていて,そのルートフォルダへのパスを/Iで指定することで利用できるようにします.

これは,プロジェクトのプロパティでは,C/C++の全般の追加のインクルードディレクトリに当たります.この項目に ; 区切りで設定したパスは,区切りで分けられ,それぞれ/I に指定されます.

同様の設定は,Xcodeにも存在しますし,Xcodeが利用しているclangというコンパイラにも同様の設定があります.clangの場合 -I で指定します.そう,似ているんですよ.

まとめ

コマンドラインのコンパイラへの理解を深めることで,IDEの設定項目についての理解を深め,プロジェクトの環境を整えることができるようになります.

まだまだ説明したいことはありますが,長くなるのでまた分けて書こうと思います.

考えている話題は,こんな感じです.

  • 警告レベルの変更
  • 警告やエラーの抑制
  • 警告をエラーに
  • 最適化レベルの変更
  • リンク関係の設定
  • ソースコードからコンパイラに指示を出す方法
  • ビルドイベント
  • C++言語仕様の選択