Quantcast
Channel: 自習室
Viewing all articles
Browse latest Browse all 50

Visual c++ の同一ソリューション内ライブラリ参照と、ライブラリプロジェクトへの静的リンクライブラリのリンクの仕方。

$
0
0

概要

Visual Studioはエディターとして超優秀だけど、ビルド時の「追加の依存ファイル(静的リンクライブラリなど)」の指定や、インクルードパスの指定をする「プロジェクトプロパティ」がとてもわかりにくいし、それをわかりやすくしようとした結果生まれた .propsファイルによるプロジェクトプロパティのファイル定義がまたややこしいってんで、なにかちょっと不慣れなことをしようとしたり、古いOSSを新しいVSで使おうとすると痛い目に遭いがち。

今回はそれげな話の一つとして、実務で遭遇した以下の2件についてメモを残しておきます。

  1. スタティックリンクライブラリを作るプロジェクト(PrjS1)と、それを使って動く .exe を作るプロジェクト(PrjE)、の2プロジェクトを持つVisual Studioの一つのソリューション(Sln1)において、PrjEがPrjS1.libを使うケース
  2. 単独のスタティックリンクライブラリを作るプロジェクト(Sln2/PrjS2) を用意し、PrjS1.libが PrjS2.lib を使うケース

図にまとめるとこんな感じ

f:id:AMANE:20190606222454p:plain

それそれどのように "参照"やリンクを行うのか、についてまとめておこうと思います。

前提知識

私も記憶喪失になりがちなので、大事な前提知識として、DLLやLIBってなんやねん?を詳細に説明して下さっている記事へのリンクを貼らせていただきます。

kamino.hatenablog.com

(1) ソリューション内の参照

ソリューション内のプロジェクト参照とは何か。

こちらに記載があります。

プロジェクト内の参照の管理 - Visual Studio | Microsoft Docs

Visual Studioは、プロジェクトへのパスが指定されると、アセンブリを見つけることができます。

とありますが、.libファイルをビルドするプロジェクトを参照した場合は、結果の .libファイルを見つけることが出来る、と言う意味ですね。

ソリューション内の別のプロジェクトへの参照の仕方

  • プロジェクトを右クリック → 追加 → 参照 → ソリューション内の .libファイルを作るプロジェクト名にチェック
    • 参照右クリック→参照の追加、でも同じ

f:id:AMANE:20190606224220p:plain

似たような項目で、プロジェクトの依存関係というのがあります。

  • ソリューションを右クリック → プロパティ → 共通プロパティ → プロジェクトの依存関係

f:id:AMANE:20190606224330p:plain

こちらは、同一ソリューション内のプロジェクト間のビルド順を定義するための設定です。試しに PrjEPrjS1に依存するよう指定すると、ビルド順こそ最適化されますが、 PrjS1中のコードの header を持ってきて使おうとすると、 未解決の外部シンボルが参照されましたのようなエラーが出ます。これは無論、 PrjS1.libがリンクできていないからです。

方法: プロジェクトの依存関係を作成および削除する - Visual Studio | Microsoft Docs

逆に、先にPrjEからPrjS1を参照すると、自動的に PrjEPrjS1を依存することもプロパティに追記されます。

ソリューションの構成とプラットフォームの自動反映

このようにプロジェクト参照で引いている .libは、構成(Debug/Release)やプラットフォーム(x86/x64) をソリューション全体で変えたとしても、利用する側の PrjEに対し、適切な構成・プラットフォームで作られた PrjS1.libを渡してくれます。

それを確認するために、以下の手順で意地悪をしてみます。

  • 一旦ソリューションをクリーン
  • Debug/x86PrjS1をプロジェクトのみビルド
  • Debug/x86PrjEをプロジェクトのみビルド → 正しくビルドされる( PrjS1.libデバッグビルド物を引けている)
  • Release/x86PrjEを再度プロジェクトのみビルド → ビルド完了出来ない(この時点ではPrjS1.lib** のリリースビルドが存在しないため)
  • Release/x86PrjS1.libをプロジェクトのみビルド、Debug/x86でビルドした PrjS1.libを削除
  • Release/x86PrjEを再度プロジェクトのみビルド → 正しくビルドされる

その間、プロジェクトプロパティ類は一切編集しませんでしたがこのように、適切な .libファイルを引いてくれることがわかります。

ちなみに細かい話ですが、ソリューションエクスプローラ上で PrjE / 参照 / PrjS1を選択してプロパティウィンドウを見ると、構成が Debugの時に Release\PrjS1.libが完全パスとして指定されていたり、その逆だったりすることがあります。これはおそらく Visual Studioの表示上のバグで、実際、Visual Studioを再起動すると、正しい .libファイルのパスが記載されています。

f:id:AMANE:20190606224523p:plain

(2) ソリューション外のビルド物である .libファイルを、自分のライブラリ(.libを出力する)プロジェクトに追加する

他所のリリース物を自分のプロジェクトに取り込んで使う場合、こちらの方が良くあると思います。特に、 PrjE(.exeを作るプロジェクト)PrjS2(.lib)をリンクする場合は、 プロジェクトプロパティ / リンカー / 追加のライブラリディレクトリ入力 / 追加の依存ファイル(.libファイル)を指定する、という「VSおきまりの」手続になります。

qiita.com

今回やりたいのは、静的リンクライブラリを出力するプロジェクトに外部の静的リンクライブラリをリンクする、ことです。基本的には上記と同じなのですが、 .exeを出力するプロジェクトと .libを出力するプロジェクトで、若干プロジェクトプロパティの構成が異なっています。 .hファイルのインクルードに関しては、 .exeのプロジェクトの場合と同様に、 C/C++ / 全般 / 追加のインクルードディレクトリに使いたい .hファイルのあるディレクトリを指定します。

ライブラリファイルの指定は、ライブラリアン / 全般タブ中の 追加の依存ファイル追加のライブラリディレクトリを、それぞれ構成・プラットフォーム毎に正しく設定する必要があります。これにより、構成・プラットフォームを変えても、PrjS1はそれ毎に正しい .libファイルをビルドしてくれ、最終的に PrjEは正しくビルドされることになります。

f:id:AMANE:20190606231518p:plain

所感

昔ながらの静的リンクライブラリのロードの仕方として、 #pragma comment(lib, "filename.lib") 式もありますが、その他の dll ファイルの置き場などすべてプロジェクトのプロパティから指定しているので、.lib` ファイルもプロジェクトプロパティの指定でやりきりたいなぁと私は考えています。コード中に書く方がマルチプラットフォーム開発では良いことも多いかも知れませんが、それはそのときに。

[VC++] リンクするライブラリファイルをソースコード内に記述する | あみだがみねのもろもろ備忘録

これまでかなり適当にやって、何となくビルドできればおっけーって感じで通ってきてた内容を一通り整理できて良かったです。


Viewing all articles
Browse latest Browse all 50

Trending Articles