ページ 1 / 1
VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 20:27
by Ketty
こんにちは。Kettyです(^^)
VC++でのLibファイルの作り方、参照の仕方について教えてください。
http://www.geocities.jp/neo_ku_ron/HP_N ... brary.html
を参考に、Libファイルを作ってみたのですが、それを他のプロジェクトで使う(参照する)とビルドエラーになってしまいます。
環境
------------------------------------------------------
Windows7 Home Edition
Visual Studio2010 Express Edition
言語 C++
------------------------------------------------------
上記URLを参考に、LibTestというスタティックライブラリのプロジェクトを作成し、以下のように実装してビルドしました。
LibTest.h
コード:
#pragma once
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
LibTest.cpp
コード:
#include "stdafx.h"
#include "LibTest.h"
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b )
{
return a + b ;
}
}
}
これを別プロジェクトの追加のインクルードディレクトリにLibTestへのパスを通し、
ソース内で、以下のように実装してみたのですが、ビルドエラーとなります。
Main.cpp
コード:
#inlcude <LibTest.h>
/*省略*/
int test = LibTest::Calc::add( 1, 2 ) ;
エラー内容
Main.obj : error LNK2019: 未解決の外部シンボル "int __cdecl LibTest::Calc::add(int const &,int const &)" (?add@Calc@LibTest@@YAHABH0@Z) が関数 _WinMain@16 で参照されました。
1>C:\○○○.exe : fatal error LNK1120: 外部参照 1 が未解決です。
どこが誤っているのでしょう?
Libファイルの作り方でしょうか?
それとも何か手順を誤っていますか?
ご教示ください。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 20:53
by sleep
プロジェクトの「プロパティ ページ」の
「リンカ」 → 「全般」 にある
「追加のライブラリディレクトリ」 へ libファイルが置かれているディレクトリへのパスを入力するか
もしくは、
今コンパイルして実行しようとしているアプリケーションのソースファイルが置いてあるディレクトリに
libファイルを置いておく。
そして、
「リンカ」 → 「入力」 にある
「追加の依存ファイル」に libファイルの名前を追加するか、
もしくは、
プログラムのコード上に
#pragma comment(lib, "〇〇〇〇.lib")
のように、#pragma commentでライブラリファイル名を指定すれば
スタティックライブラリが認識されるようになります。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 21:25
by Ketty
>sleepさん
ご回答くださりありがとうございます。
>プロジェクトの「プロパティ ページ」の
>「リンカ」 → 「全般」 にある
>「追加のライブラリディレクトリ」 へ libファイルが置かれているディレクトリへのパスを入力
してみましたが、以下のようなビルドエラーがでました。
fatal error C1083: include ファイルを開けません。'LibTest.h': No such file or directory
プロパティページは添付画像のとおりです。
また、Libファイル自体は、C:\LibTest\LibTest.lib に配置しています。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 21:28
by sleep
インクルードファイルは
プロジェクトの「プロパティ ページ」の
「C/C++」 → 「全般」 にある
「追加のインクルードディレクトリ」へ .hファイル が置かれているディレクトリへのパスを入力するか
もしくは、
今コンパイルして実行しようとしているアプリケーションのソースファイルが置いてあるディレクトリに
.hファイルを置いておく。
で読み込めるようになります。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 21:51
by Ketty
>sleepさん
ご回答くださりありがとうございますm(__)m
>プロジェクトの「プロパティ ページ」の
>「C/C++」 → 「全般」 にある
>「追加のインクルードディレクトリ」へ .hファイル が置かれているディレクトリへのパスを入力
してみましたが、まだビルドエラーになります。
error LNK2019: 未解決の外部シンボル "int __cdecl LibTest::Calc::add(int const &,int const &)" (?add@Calc@LibTest@@YAHABH0@Z) が関数 _WinMain@16 で参照されました。
C:\○○○.exe : fatal error LNK1120: 外部参照 1 が未解決です。
プロパティページは添付画像のとおりです。
また、.hファイルは、C:\GameTestProject\LibTest\LibTest にあります。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 22:04
by sleep
スタティックライブラリを認識できていないようです。
下記のどちらか片方は設定されていますか?
sleep さんが書きました:
そして、
「リンカ」 → 「入力」 にある
「追加の依存ファイル」に libファイルの名前を追加するか、
もしくは、
プログラムのコード上に
#pragma comment(lib, "〇〇〇〇.lib")
のように、#pragma commentでライブラリファイル名を指定すれば
スタティックライブラリが認識されるようになります。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 22:34
by Ketty
>sleepさん
度重なるご回答、ありがとうございますm(__)m
>下記のどちらか片方は設定されていますか?
申し訳ないです。設定をしておりませんでした。
以下、設定することで、何やら警告(※注1)が出ましたが、ひとまずビルドすることができました。ありがとうございました。
#pragma comment(lib, "LibTest.lib")
※注1)・・・内容の吟味はまだですが、何やら.NETを使っていると指摘されているようにうかがえます(私には使ってる意識はありません)
LibTest.lib(LibTest.obj) : MSIL .netmodule または /GL を伴ってコンパイルされたモジュールが見つかりました。/LTCG を使用して再開始してください。リンカーのパフォーマンスを向上させるためには、コマンドラインに /LTCG を追加してください。
ここまでの手順をまとめますと、
(Step1)プロジェクトの「プロパティ ページ」の
「リンカ」 → 「全般」 にある
「追加のライブラリディレクトリ」 へ
libファイルが置かれているディレクトリへのパスを入力
(Step2)プロジェクトの「プロパティ ページ」の
「C/C++」 → 「全般」 にある
「追加のインクルードディレクトリ」へ
.hファイル が置かれているディレクトリへのパスを入力
(Step3)#pragma comment(lib, "Libファイル名") をソース内に記述する
となります。
追加で疑問が2つあります。
1.先の※注1)は何者なのか。
ひとまずネット検索してみますが、お分かりの方がいらっしゃったらご教示ください。
2.DXライブラリを使うときの手順に比べて煩雑なのはなぜか。(私は同じ手順で実現したいです)
プロジェクトからDxLibを使う手順は、
「追加のインクルードディレクトリ」へ、Libファイルが置かれているディレクトリへのパスを入力するだけなので、
それと同じようにしたいと考えています。
どうすれば実現できるのか、お分かりの方がいらっしゃたらご教示ください。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 23:41
by sleep
DXライブラリのことは私には分かりかねるので
ご存じの方教えてあげていただけますか。
Ketty さんが書きました:
「追加のインクルードディレクトリ」へ、Libファイルが置かれているディレクトリへのパスを入力するだけなので
恐らく、.hファイルの中に相対パス(もしくは、絶対パス)で#pragma commentが記述されています。
コード:
#pragma once
#pragma comment(lib, "C:\\LibTest\\LibTest.lib")
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
そうすれば、スタティックライブラリが置いてある場所と
スタティックライブラリファイルの名前が同時に指定されるので
それで、「追加のインクルードディレクトリ」の設定のみで大丈夫なのだと思います。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月13日(土) 23:50
by sleep
あと、
Ketty さんが書きました:
「追加のインクルードディレクトリ」へ、Libファイルが置かれているディレクトリへのパスを入力するだけなので
これは恐らく
正確には .hファイルへのパスだと思われます。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 00:36
by Ketty
>sleepさん
重ね重ねありがとうございますm(__)m
付き合わせてしまって申し訳ないです。また、つど適切にアドバイスくださり、非常にありがたく思っております。
>恐らく、.hファイルの中に相対パス(もしくは、絶対パス)で#pragma commentが記述されています。
ありがとうございます。
さっそく、DXライブラリ公式サイトで配布されているソース一式(※注2)を展開してみたところ、
#pragma commentによるLibソースの取り込みのが.hファイル内に、見受けられました。
DxLibMake\DxLib.hの77行目より抜粋
コード:
#pragma comment( lib, "DxLib.lib" ) // DXライブラリ使用指定
まさしく、sleepさんがおっしゃられることがこれだと思われますが、
何やら#ifdefで多階層的に条件分岐されているようで・・・私はこれを解析しきれておりません・・・。
また、ご提供いただいた絶対パス指定の記述ですが、
► スポイラーを表示
コード:
#pragma once
#pragma comment(lib, "C:\\LibTest\\LibTest.lib")
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
ならびに相対パス指定版
► スポイラーを表示
コード:
#pragma once
#pragma comment(lib, "LibTest.lib")
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
いずれも、試してみましたが、どちらも、参照する側のプロジェクトでビルドエラーとなりました。
エラー内容
fatal error C1083: include ファイルを開けません。'LibTest.h': No such file or directory
この質問を投稿させていただいた当初は、
自分用の共通Libをいろんなプロジェクトで簡易に再利用することが目的だったので、
簡単にLibを作って、かつ、簡単に(DxLib同様に)参照出来る方法があれば便利でいいなぁと考えていたのですが、
今のところ、これを実現するのは、私が考えていた以上に敷居の高い作業でありそうだという印象です。
そういうものなのでしょうか。
それとも、私が何か致命的に勘違いしているのでしょうか・・・。
まとめると、
・Libファイルの参照方法はsleepさんに教わった方法で実現できることを確認できました。(sleepさん、重ね重ねありがとうございます)
・Libファイルを、DxLibと同じ手順で参照可能にするには、上記の77行目に至るまでのいろいろな条件分岐マクロを、.hファイルに実装しなければならなさそう。
・え?そういうものなの??(←いまここです)
ということですm(__)m 度重なるスレッド更新、ご迷惑おかけいたします。
数日待たせていただいてこれ以上レスがつかないようであれば、ひとまず解決とさせていただきます。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 01:07
by sleep
Kettyさんが作成されたスタティックライブラリについては、
現状、ユーザー用ライブラリへのパスが何も設定されていないので
相対パスはおそらく使えませんね。
絶対パスの指定のみ可能な状況かと思われます。
Ketty さんが書きました:
いずれも、試してみましたが、どちらも、参照する側のプロジェクトでビルドエラーとなりました。
エラー内容
fatal error C1083: include ファイルを開けません。'LibTest.h': No such file or directory
これは、アプリケーションのプログラムでインクルードしている .hファイルが置いてある場所へ
パスが正しく指定できていないということですね。
要約すると、再度、以下の指定ができていないというメッセージです。
sleep さんが書きました:インクルードファイルは
プロジェクトの「プロパティ ページ」の
「C/C++」 → 「全般」 にある
「追加のインクルードディレクトリ」へ .hファイル が置かれているディレクトリへのパスを入力するか
もしくは、
今コンパイルして実行しようとしているアプリケーションのソースファイルが置いてあるディレクトリに
.hファイルを置いておく。
で読み込めるようになります。
結局のところ、
やり方は色々ありますけど、必要なのはパスとファイル名、この2つですね。
ファイルの場所と名前が分からないと、コンパイラやリンカがファイルを見つけられない、というだけのことですね。
本当にそれだけのことなんです。
ただ、やってることは単純な話なんですが、
VisualStadioで設定しようとすると、設定する場所があちこちに散っているので
皆さん最初は戸惑いますね。
この手の設定に関して、Visual Stadioはインタフェースが悪いと思います。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 09:09
by へにっくす
以下のようにしてコンパイルできることを確認しました。
(コンパイル環境:Visual Studio Express 2012 for Windows Desktop)
設定ダイアログは一切触ってません。
Visual Studio 2010でも出来るはずですが・・・
(添付したファイルは、VS2010でそのまま開けないはずですので、ツリーを参考に・・・)
一つのソリューションに、複数のプロジェクトを追加できるのは知ってますよね?
コード:
// ConsoleMain.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#include "..\LibTest\LibTest.h"
#if defined _DEBUG
#pragma comment(lib, "..\\Debug\\LibTest.lib")
#else
#pragma comment(lib, "..\\Release\\LibTest.lib")
#endif
int _tmain(int argc, _TCHAR* argv[])
{
int test = LibTest::Calc::add( 1, 2 ) ;
return 0;
}
コード:
1>------ すべてのリビルド開始: プロジェクト: LibTest, 構成: Debug Win32 ------
1> stdafx.cpp
1> LibTest.cpp
1> LibTest.vcxproj -> c:\users\***\documents\visual studio 2012\Projects\ConsoleApplication_t15689\Debug\LibTest.lib
2>------ すべてのリビルド開始: プロジェクト: ConsoleMain, 構成: Debug Win32 ------
2> stdafx.cpp
2> ConsoleMain.cpp
2> ConsoleMain.vcxproj -> c:\users\***\documents\visual studio 2012\Projects\ConsoleApplication_t15689\Debug\ConsoleMain.exe
========== すべてリビルド: 2 正常終了、0 失敗、0 スキップ ==========
このときのツリー構造は以下の通りです(余計なファイルは記述していません)。
#includeとlibの相対パス指定を確認してください。
またそのヘッダーファイルとライブラリファイルがちゃんと存在してるか確認してください。
コード:
フォルダー パスの一覧: ボリューム Windows 7
ボリューム シリアル番号は 2282-D87E です
C:.
│ ConsoleApplication_t15689.sln
│
├─ConsoleMain
│ │ ConsoleMain.cpp
│ │ ConsoleMain.vcxproj
│ │ ReadMe.txt
│ │ stdafx.cpp
│ │ stdafx.h
│ │ targetver.h
│ │
│ └─Debug
│
├─Debug
│ ConsoleMain.exe
│ ConsoleMain.ilk
│ ConsoleMain.pdb
│ LibTest.lib
│
└─LibTest
│ LibTest.cpp
│ LibTest.h
│ LibTest.vcxproj
│ ReadMe.txt
│ stdafx.cpp
│ stdafx.h
│ targetver.h
│
└─Debug
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 13:52
by Ketty
>sleepさん
ありがとうございます。
>結局のところ、
>やり方は色々ありますけど、必要なのはパスとファイル名、この2つですね。
なりほど、Libファイルとhファイル、両方とも見えなければ使えないということですね。ようやく分かりました。
てっきり、Libのパスだけ通せば使えるものだと勘違いしておりましたm(__)m 申し訳ないです。
DXライブラリもよく見てみたら、追加のインクルードディレクトリで設定しているフォルダに、Libとh両方が入っておりました。
>へにっくすさん
いつもお世話になっております(^^)
サンプルプロジェクトまで添付いただいてありがとうございました。
なるほど、同一ソリューション内でLib側プロジェクトと参照側プロジェクトを作ってしまうわけですね。
おお・・・これなら簡単ですね!
できれば、DXLibと同じ設定(追加のインクルードディレクトリに指定)だけで済ませたいという欲求がありまして、
sleepさんとへにっくすさんお二方のご助言から、以下のようにして実験してみました。
LibTest.hファイル
コード:
#pragma once
// LibTest.hファイル内でlibファイルへの絶対パスを指定(なんか変な感じがするけれど)
#if defined _DEBUG
#pragma comment(lib, "C:\\○○○\\LibTest\\Debug\\LibTest.lib")
#else
#pragma comment(lib, "C:\\○○○\\LibTest\\Release\\LibTest.lib")
#endif
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
参照側・・・追加のインクルードディレクトリにC:\\○○○\\LibTest\\LibTest を通す(LibTest.hがあるディレクトリ)
コード:
#include <DxLib.h> // DXライブラリ
#include <LibTest.h> // LibTestライブラリ
// メイン関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// 使えるか確認
int i = LibTest::Calc::add( 1, 3 ) ;
return 0 ;
}
なんだかヘンテコですが、つじつまは合っているようで動くことを確認できました。
オフトピック
自分なりに設定ミスが少なくなるような仕組みをもう少し練ってみようと思います。
DXLibの「プロジェクトに追加すべきファイル_VC用」フォルダみたいに、
Libとhを一か所に配置するようなバッチでも作って、参照側はそのフォルダパスを通す、というやり方がよさそうだと思いました。
ともあれ、sleepさん、へにっくすさんお二方のおかげでスタティックライブラリの参照の仕組みが理解できましたので、
これで解決とさせていただきますm(__)m どうもありがとうございました。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 17:56
by ISLe()
Ketty さんが書きました:できれば、DXLibと同じ設定(追加のインクルードディレクトリに指定)だけで済ませたいという欲求がありまして、
DXライブラリでも、「プロジェクトに追加すべきファイル_VC用」フォルダへのパスを、
追加のインクルード ディレクトリ (C/C++ - 全般)
追加のライブラリディレクトリ (リンカー - 全般)
の2箇所に設定する必要があります。
#pragma comment(lib, "~")
は、ソースファイルでリンクするライブラリを指定するものではなく、正確には
リンクするライブラリとして指定したパスを
生成するobjファイルに埋め込むもの
です。
派生ライブラリを作ったりしたとき元のパスが埋め込まれてずっと残っていくので元のライブラリを移動すると数珠つなぎにエラーになります。
あるいは、埋め込まれたライブラリ情報を無視するオプションを指定して、いちいち新しい位置を指定し直す必要があります。
オプションは実行形式を構成するすべてのobjに対して有効なので、他のライブラリも無視されて多くの手作業を生むかもしれません。
ソースコードに絶対パスを記述するのは避けたほうが良いと思います。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 21:18
by Ketty
>ISLeさん
いつもお世話になっております(^^)
>#pragma comment(lib, "~")
>は、ソースファイルでリンクするライブラリを指定するものではなく、正確には
>リンクするライブラリとして指定したパスを生成するobjファイルに埋め込むもの
なんと・・・。つまり、objファイルに仕込まれるように手続きする必要があるのですね?
差支えなければ以下質問させてください。
(不勉強ゆえにトンチンカンな質問であるかもしれませんが、そのときはご指摘いただければ幸いです。)
1.それは、Visual Studioではどのような作法になるのでしょうか?あるいはソースの書き方の問題でしょうか。
2.また、そういったことはいったいどこで勉強できるのでしょうか?MSDN等で公開されている既知の事実なのでしょうか。
私としては、スタティックライブラリを簡単に参照する・・・というだけのことと鷹をくくっていたために、今回の件については、とても面喰っています。
もしかして、こういったことは、知る人ぞ知る流儀とかテクニックだったりするものなのでしょうか。
(私自身は、C++というか、VC++プロジェクトを扱うのは1年半~2年くらいなので、初級者に等しいレベルです。)
>ソースコードに絶対パスを記述するのは避けたほうが良いと思います。
はい、私も絶対パスを記述したくないと考えています。
トピックを解決済みにしてしまったので、
上記質問に関しては、新たにトピックを立てるべきであればご指摘くださいm(__)m
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月14日(日) 22:19
by softya(ソフト屋)
解決チェックを外しておきました。
ちなみに#pragma はコンパイラに対して指示するもので仕様はコンパイラ毎に違います。規格書レベルでは細かい定義はありません。
>なんと・・・。つまり、objファイルに仕込まれるように手続きする必要があるのですね?
すでにやっています。
#pragma comment(lib, "C:\\○○○\\LibTest\\Debug\\LibTest.lib")
がコンパイル時にobjに埋め込まれます。ISLeさんが、これは良くないと言っているわけす。
・追加のインクルード ディレクトリ (C/C++ - 全般)
・追加のライブラリディレクトリ (リンカー - 全般)
は必ず必要です。DXライブラリも指定していますよ。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 00:28
by ISLe()
「pragma comment lib」といったキーワードでネットを検索すればMSDNのリファレンスページが見付かると思います。
あるいは、Visual Studioのコードエディタ上で、
#pragme comment
と入力してそのままF1(ヘルプ)キーを押してみてください。
コメント (C/C++)
けっこう分かりやすく書いてあると思います。
No.13の参照側のソースファイル名がMain.cppだとすると…
<<コンパイル>>
Main.cppがコンパイルされて、Main.objが作成されます。
ライブラリ検索パスはMain.objに埋め込まれます。
<<リンク>>
Main.objをリンクして実行形式(*.exe)が作成されます。
Main.objに埋め込まれたライブラリ検索パスが同時に使用されます。
というのが
#pragma comment(lib, "~")
の作用です。
作成済みのobjファイルは個別にリンクできます。
スタティックライブラリ(*.lib)は、objファイルを(複数)含むアーカイブファイルです。
C/C++言語の処理系は、コンパイルとリンクの2段階で構成されるのがふつうです。
設定が言語とリンカに分かれているのもVisual Studioに限らず一般的です。
objファイルを作成できるのがC/C++言語だけではないからです。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 13:13
by Ketty
>softyaさん
いつもお世話になっております(^^)
解決チェックを外しておきました。
ありがとうございます。お手数おかけしました。
すでにやっています。
#pragma comment(lib, "C:\\○○○\\LibTest\\Debug\\LibTest.lib")
がコンパイル時にobjに埋め込まれます。ISLeさんが、これは良くないと言っているわけす。
理解できました。
・・・ソースに書いてるのだから中間ファイルにも埋め込まれる・・・というのは自明の理でしたm(__)m
Visual Studioのプロジェクトの設定か何かで実現するのかと勘違いしておりました。
>ISLeさん
重ね重ねありがとうございます。
「pragma comment lib」といったキーワードでネットを検索すればMSDNのリファレンスページが見付かると思います。
あるいは、Visual Studioのコードエディタ上で、
#pragme comment
と入力してそのままF1(ヘルプ)キーを押してみてください。
コメント (C/C++)
けっこう分かりやすく書いてあると思います。
リファレンスも読ませていただきました。
#pragma comment(lib, "~")と
追加のライブラリディレクトリ (リンカー - 全般)は、同じ作用だという認識であってますでしょうか?
お二方のご助言をもとに、以下のようにして実験してみました。
LibTest.h
コード:
#pragma once
// Libへのパスを記述するのは撤廃しました
namespace LibTest
{
namespace Calc
{
int add( const int& a, const int& b ) ;
}
}
そして、.libと.hをひとつのフォルダに配置しました。
コード:
C:\
|___プロジェクトに追加すべきLibフォルダ
|
|___LibTest.h
|
|___LibTest.lib
最後に、参照側プロジェクトでは、添付の画像のとおり、
・追加のインクルード ディレクトリ (C/C++ - 全般)
・追加のライブラリディレクトリ (リンカー - 全般)
両方に、C:\プロジェクトに追加すべきLibフォルダを設定しました。
しかし、ビルドエラーとなります。
Main.obj : error LNK2019: 未解決の外部シンボル "int __cdecl LibTest::Calc::add(int const &,int const &)" (?add@Calc@LibTest@@YAHABH0@Z) が関数 _WinMain@16 で参照されました。
何を間違えているのか想像もつきませんm(__)m
ご教示いただければ幸いです。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 16:31
by へにっくす
間違えてはいません。
設定が足りないだけです。
ソースで
#pragma comment (lib, "LibTest.lib")
とファイル名を指定する(注意:ISLeさんは絶対パスを指定するのが問題と言ってるのです)か、
リンカー-入力-追加の依存ファイル
- ライブラリファイルの指定
に自分のライブラリファイルを指定するか
どちらかの設定が必要です。
ちなみに注意しておくと、
Debugで作成したライブラリファイルとReleaseで作成したライブラリファイルをごっちゃにしないでくださいね。
間違ったファイルを指定すると、これまたリンカエラーになるはずですので。
DXLIBでもDebugとReleaseでファイル名を別にしてあるはずです(ソースを直接みればわかると思いますが)。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 16:57
by sleep
ちょっと、まだ「理解できた」と言い切るのは厳しいですね(笑)
ketty さんが書きました:
softya(ソフト屋) さんが書きました:
すでにやっています。
#pragma comment(lib, "C:\\○○○\\LibTest\\Debug\\LibTest.lib")
がコンパイル時にobjに埋め込まれます。ISLeさんが、これは良くないと言っているわけす。
理解できました。
LibTest.lib を作成する側のプロジェクトで
#pragma comment(lib, ...) を 書いてビルドした場合と書かずにビルドした場合で
それぞれ、libファイルを作成する過程でできる LibTest.obj をテキストエディタで開いて見てみてください。
#pragma comment(lib, ...) を指定してビルドした場合、
/DEFAULTLIB:"LibTest.lib"
と書かれてますが、
#pragma comment(lib, ...) を指定しないでビルドした場合、
書かれてないと思います。
それがお二方が教えてくださってる
コンパイル時にobjに埋め込まれます。
というやつです。
オフトピック
その他にも、私の環境と設定が大して違わなければ2つ程あるのではないでしょうか?
それぞれの意味は以下のとおりです。
/DEFAULTLIB:"MSVCRTD"
マルチスレッド用DLLのlibファイル MSVCRTD.lib をリンクするように指示します。
コンパイラオプション /MDd の指定で追加されているものです。
(プロジェクトの「プロパティ ページ」→「C/C++」→「コード生成」の「ランタイムライブラリ」で指定)
/DEFAULTLIB:"OLDNAMES"
下位互換性用の libファイルです。
製品バージョンとの互換性のために、新しい名前が古い名前を割り当てます。
Ketty さんが書きました:
#pragma comment(lib, "~")と
追加のライブラリディレクトリ (リンカー - 全般)は、同じ作用だという認識であってますでしょうか?
ISLe()さんが助言くださってますが、Kettyさんはちゃんとネットを検索されましたか?
Microsoft C で、リンカー オプションを指定するのに #pragma comment(lib...) を使用することができます。
#pragma comment(lib, ...) は、link.exeに対してobjファイル経由でリンカーオプションを指示します。
リンカの「追加の依存ファイル」は、link.exeに直接リンカーオプションを指示します。
(プロジェクトの「プロパティ ページ」→「リンカ」→「入力」の「追加の依存ファイル」で指定)
「追加のライブラリディレクトリ」は、libファイルの場所を教えているだけで、
リンクする libファイルの名前を教えてません。
この違い、分かりますかね?(汗)
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 17:26
by sleep
あと、お二方が #pragma comment(lib, ...) に絶対パスを指定しておくと
何がいけないと言っているか、も説明しておきます。
絶対パスで指定しておくと、objファイルに以下のように埋め込まれます。
(以下はDesktopにLibTest.libを配置して指定する例)
コード:
/DEFAULTLIB:"C:\Users\%username%\Desktop\LibTest.lib"
時が過ぎ、ライブラリファイルの設置場所を C:\\直下に移動したとき
LibTest.lib は、C:\LibTest.lib にありますが、link.exeは
C:\Users\%username%\Desktop\LibTest.lib にファイルを探しに行って
「見つからない」と言います。
(error LNK1104: ファイル 'C:\Users\%username%\Desktop\LibTest.lib' を開くことができません。)
これを修正するためには、LibTest.lib の #pragma comment(lib, ...) を
コード:
/DEFAULTLIB:"C:\LibTest.lib"
に書き直し、再コンパイルしてあげなくてなりません。
しかし、
元々 libファイルの場所を 「追加のライブラリディレクトリ」 で指定しておけば話は変わってきます。
元から #pragma comment(lib, ...) の設定が相対パスで指定されているので
コード:
/DEFAULTLIB:"LibTest.lib"
「追加のライブラリディレクトリ」の位置を変更するだけで、全ての移動した libファイルに一括対応できます。
絶対パス指定の例が、1ファイル程度なら大した話ではないですけど
数百ファイルなどになってきたり、相対パスと絶対パスの指定の #pragma comment(lib, ...) が
入り混じっていると、整合性を保たせるために相当な時間をかけて、しらみ潰しにつじつまを合わせる
作業が待っています。
これがプライベートでの一人での作業なら、自分の時間を消費するだけで済みますが、
会社などで複数人の作業でやると、人件費も嵩みますし、何より他の方へ迷惑をかけてしまいますよね。
そういう状況に陥ってしまうので、避けましょう、ということです。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月15日(月) 17:33
by ISLe()
ライブラリファイル名の指定が必要なことは既に指摘されているので、Ketty さんのやりたいことに対する将来的なヒントを書いておきます。
Visual Studioのプロジェクトには、ビルド時に任意のコマンドを実行する機能があります。
ビルド前・リンク前・ビルド後それぞれ実行して欲しいコマンドラインを指定できます。
ビルド後に、バッチファイルを呼び出して、ビルドに成功したライブラリファイルとヘッダファイルをお好みのフォルダへ自動的にコピーするといったことができます。
マクロや環境変数を利用すれば、デバッグ版のライブラリファイル名には末尾にdを付けたり、コピー先を任意に変更できたり、便利に使えます。
プロパティページ機能を使うと、ライブラリを利用するときの
・追加のインクルード ディレクトリ (C/C++ - 全般)
・追加のライブラリディレクトリ (リンカー - 全般)
などをまとめて設定することができます。
上にも書きましたが、環境変数を利用すればライブラリの置き場所を任意に変えることもできます。
ちなみにDXライブラリを使うときの設定をまとめたプロパティページを以前この掲示板に投稿しました。
改良版がうちのブログに置いてあります。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月17日(水) 22:40
by Ketty
>へにっくすさん
具体的なアドバイスくださり、ありがとうございますm(__)m
リンカー-入力-追加の依存ファイル
に自分のライブラリファイルを指定するか
あああ・・・確かに、抜けていました・・・!!!
(sleepさんがおっしゃられていたことですね・・・)
設定してみたところ、ビルドできることを確認しました(添付ファイル)
Debugで作成したライブラリファイルとReleaseで作成したライブラリファイルをごっちゃにしないでくださいね。
はいm(__)m
ライブラリと参照側(本体)の、Debug/Releaseは統一してビルドするように決めています。
念のため確認させてください、Debugで作成したLibを、参照している本体プロジェクトがあったとして、
その際、本体プロジェクトをReleaseビルドすると、どのような問題があるのでしょうか?
LibをDebugビルドしたときの(要らない)モロモロがexeについてくる
⇒処理が遅くなるかも!
⇒配布用には不適切!
・・・というの認識であっておりますか?
>skeepさん
ちょっと、まだ「理解できた」と言い切るのは厳しいですね(笑)
す、すみませんm(__)m理解した"つもり"でおりました。不勉強でした。面目ないです(@_@ ; )
LibTest.lib を作成する側のプロジェクトで
#pragma comment(lib, ...) を 書いてビルドした場合と書かずにビルドした場合で
それぞれ、libファイルを作成する過程でできる LibTest.obj をテキストエディタで開いて見てみてください。
#pragma comment(lib, ...) を指定してビルドした場合、
/DEFAULTLIB:"LibTest.lib"
と書かれてますが、
おっしゃるとおり、実験しました。確かに、
#pragma comment(lib, ...) を指定してビルドした場合は以下がありましたが、
#pragma comment(lib, ...) を指定しないでビルドした場合は以下はありませんでした。
コード:
/DEFAULTLIB:"C:\LibTest\LibTest\Debug\LibTest.lib"
おそらく、objに記録される/されない の違いは分かったつもりであります(まだ間違ってたらごめんなさい(; _; )勉強します)
ISLe()さんが助言くださってますが、Kettyさんはちゃんとネットを検索されましたか?
Microsoft C で、リンカー オプションを指定するのに #pragma comment(lib...) を使用することができます。
いえ、検索できておりませんでした・・・m(__)m
リンク先を読ませていただいたのですが、まだ自分の中に入りきっておりません。
コード:
リンカー オプションを指定するのにには、次の新しいプラグマを使用します。
#pragma comment(linker, "<linker options>")
??
どうやら、私は#pragma comment(ほにゃらら)で指定することによる、
リンカオプションの意味、
あるいは、#pragma comment(ほにゃらら)自体の意味を理解できていないのだと想像します(@_@ ;)すみません・・。
よくわからないけれど、それにパスを書けばいいという、おまじないくらいの認識でしかなかったです。
なので、ちょっと数日かけて勉強したいと考えていますのでお時間ください。
「追加のライブラリディレクトリ」は、libファイルの場所を教えているだけで、
リンクする libファイルの名前を教えてません。
この違い、分かりますかね?(汗)
はい、わかった(つもり)ですm(__)m
フォルダ(C:\○○○\LibTest)を指定してるけど、
実態(LibTest.lib)は、ほにゃららのままで行方不明だよ、ということで合ってますでしょうか?
>ISLe()さん
これまで、ハンドルネームに"()"をつけておられることに気づかず、
長らく"ISLe"さんと誤称しておりました・・・。大変失礼しました。申し訳ないです。
ビルド前・リンク前・ビルド後それぞれ実行して欲しいコマンドラインを指定できます。
ビルド後に、バッチファイルを呼び出して、ビルドに成功したライブラリファイルとヘッダファイルをお好みのフォルダへ自動的にコピーするといったことができます。
あ・・・あー、たぶんこれだ・・・!!と思っております。
上記のとおり、もう少し自分の理解度を深めたうえで、そのあたり実践してみたいと思います。
そのうえで、不明なことが出てきた際には、是非また質問させてください。
ちなみにDXライブラリを使うときの設定をまとめたプロパティページを以前この掲示板に投稿しました。
ありがとうございます。
実は、かねてより、お断りなくそれを使わせていただいております(~~;
ですが、意味もわからず利用していたのだと気づかされましたので、この機会にプロパティページのなんたるかを一度勉強したく思います。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月17日(水) 23:29
by へにっくす
Ketty さんが書きました:
Debugで作成したライブラリファイルとReleaseで作成したライブラリファイルをごっちゃにしないでくださいね。
はいm(__)m
ライブラリと参照側(本体)の、Debug/Releaseは統一してビルドするように決めています。
念のため確認させてください、Debugで作成したLibを、参照している本体プロジェクトがあったとして、
その際、本体プロジェクトをReleaseビルドすると、どのような問題があるのでしょうか?
LibをDebugビルドしたときの(要らない)モロモロがexeについてくる
⇒処理が遅くなるかも!
⇒配布用には不適切!
・・・というの認識であっておりますか?
引用した次の一行をよく読んでください。
へにっくす さんが書きました:Debugで作成したライブラリファイルとReleaseで作成したライブラリファイルをごっちゃにしないでくださいね。
間違ったファイルを指定すると、これまたリンカエラーになるはずですので。
そもそもリンクできないので、処理が遅くなるとか配布用には不適切とか考える以前のことです。
オフトピック
ちなみにネットでもし公開するために配布する場合は、必ず「Releaseモード」で作成したものを配布してください。
Debugモードで作成したものを配布することは禁止されています。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月18日(木) 00:12
by sleep
Ketty さんが書きました:
おっしゃるとおり、実験しました。確かに、
#pragma comment(lib, ...) を指定してビルドした場合は以下がありましたが、
#pragma comment(lib, ...) を指定しないでビルドした場合は以下はありませんでした。
コード:
/DEFAULTLIB:"C:\LibTest\LibTest\Debug\LibTest.lib"
おそらく、objに記録される/されない の違いは分かったつもりであります(まだ間違ってたらごめんなさい(; _; )勉強します)
いえ、大丈夫です。
ここで押さえておきたいのは、
#pragma comment(lib, ...)
をコード内で指定すると、objファイル内に
/DEFAULTLIB:"..."
という、link.exeのオプションが追記される、ということですね。
そして、それがビルドのリンク時に使用されている、ということです。
その2つが理解できれば、十分ではないでしょうか。
あとは
「/DEFAULTLIB:"..."」が リンク時に link.exeに何を指示しているか知ってれば大丈夫です。
(link.exe が参照を解決するときに検索するライブラリを指示している、です)
Ketty さんが書きました:
リンク先を読ませていただいたのですが、まだ自分の中に入りきっておりません。
コード:
リンカー オプションを指定するのにには、次の新しいプラグマを使用します。
#pragma comment(linker, "<linker options>")
??
どうやら、私は#pragma comment(ほにゃらら)で指定することによる、
リンカオプションの意味、
あるいは、#pragma comment(ほにゃらら)自体の意味を理解できていないのだと想像します(@_@ ;)すみません・・。
よくわからないけれど、それにパスを書けばいいという、おまじないくらいの認識でしかなかったです。
なので、ちょっと数日かけて勉強したいと考えていますのでお時間ください。
いえ、こちらに関しても大丈夫です。
読みづらい日本語で書いてあって読めたもんじゃなかったと思います。
あのページは内容的には、
/DEFAULTLIB:"..."
以外のリンカーオプションを指定するにはどうしたらいいか?という質問ページです。
また、他のリンカーオプションも指定できるように
#pragma comment (linker, "...")
を新しく用意しました、という紹介ページでもありますね。
そこは、大して重要じゃないです(笑)
あのページで押さえるべきところは
・#pragma commentは、オブジェクト ファイルまたは実行可能ファイルにコメントを挿入する。
・#pragma comment(lib, ...)で、リンカーにこのコメントを渡すことができる。
ということですね。
今のKettyさんなら、もうしっかり押さえれてる情報ですけどね。
ちなみに
#pragma comment (lib, "LibTest.lib")
は、
#pragma comment (linker, "/DEFAULTLIB:LibTest.lib")
の様にも書けます。
また、#pragma comment(lib, ...)は、1度に複数の libファイルを指定することも可能です。
(区切り文字は半角スペースです)
#pragma comment (lib, "LibTest.lib AAA.lib BBB.lib CCC.lib")
一応、知識として知っておいてください。
Ketty さんが書きました:
フォルダ(C:\○○○\LibTest)を指定してるけど、
実態(LibTest.lib)は、ほにゃららのままで行方不明だよ、ということで合ってますでしょうか?
はい、合ってます。
「追加のライブラリディレクトリ」を指定すると、link.exeに
/LIBPATH:C:\プロジェクトに追加すべきLibフォルダ
というリンカーオプションが指示されます。
これ、名前のとおりパスとしてしか機能してくれないんですよね。
「追加の依存ファイル」と #pragma comment(lib, ...) で相対パスを指定した
libファイルを探すときに、「/LIBPATH:"..."」で指定したパスも基点として加えて
ファイルを探してくれるようになります。
上記は、objファイルと同じディレクトリに置いてある
logファイルに link.exe に指定されたオプションとして書かれています。
逆に、#pragma comment(lib, ...)は、link.exe に直接指示されたものでは無いので
書かれていないことも確認できます。
(objファイルに記述されているので)
私からの指摘に関しては大丈夫なのではないでしょうか。
皆さんからこの辺のことで教えを頂いたときに、それを理解する前提知識としてお役に立てれば幸いです。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月18日(木) 01:01
by Ketty
>へにっくすさん
そもそもリンクできないので、処理が遅くなるとか配布用には不適切とか考える以前のことです。
ありがとうございますm(__m)
さっそく、やってはイカンであろうことを実験して、
へにっくすさんがおっしゃることの正しさを理解してみました。
DebugビルドしたLibファイルを参照したプロジェクトを作って
Releaseビルドしてみたところ、以下のような警告が出ました。
コード:
1>LibTest.lib(LibTest.obj) : warning LNK4075: /EDITANDCONTINUE は /OPT:ICF の指定によって無視されます。
1> コード生成しています。
1> コード生成が終了しました。
1> Test.vcxproj -> C:\○○○\Test\Release\Test.exe
========== すべてリビルド: 1 正常終了、0 失敗、0 スキップ ==========
調べてみたところ、LNK4075は、「同時に指定できないリンカ オプションが指定されています」のことだそうです。
まさに、へにっくすさんがおっしゃることがこれなのだと分かりましたm(__)m
オフトピック
警告は出るけど、ビルドはとおっちゃうのですね。
Debugモードで作成したものを配布することは禁止されています。
ありがとうございます。こちらについては、過去ログで拝見して存じておりました(^^ヾ
のちのちこのトピックをご覧になった人のために、声を大にして書いておきます。
Debugモードで作成したものを配布することは禁止されています。
ゲームを作っておられるみなさん、Releaseモードでビルドしましょう!
>sleepさん
長らくお付き合いくださり、ありがとうございますm(__m)
また、#pragma comment(lib, ...)は、1度に複数の libファイルを指定することも可能です。
(区切り文字は半角スペースです)
#pragma comment (lib, "LibTest.lib AAA.lib BBB.lib CCC.lib")
一応、知識として知っておいてください。
こういう豆知識は助かります。私はたぶん検索の仕方もわからなかったと思うので・・・。
ありがとうございます。
私からの指摘に関しては大丈夫なのではないでしょうか。
皆さんからこの辺のことで教えを頂いたときに、それを理解する前提知識としてお役に立てれば幸いです。
この度は大変ありがとうございました(^^)
私の未熟さゆえ、度重なる質問でお手数おかけしました。
また貴重な時間をおかけくださって説明してくださり感謝します。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月18日(木) 05:19
by へにっくす
Ketty さんが書きました:調べてみたところ、LNK4075は、「同時に指定できないリンカ オプションが指定されています」のことだそうです。
まさに、へにっくすさんがおっしゃることがこれなのだと分かりましたm(__)m
オフトピック
警告は出るけど、ビルドはとおっちゃうのですね。
ビルド通っちゃうのですね。ライブラリの依存ファイルによっては通らないこともありますよ。
まあでも、そのまま通るわけじゃないのは理解していただけたようで、安心しました。
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月18日(木) 15:19
by Ketty
皆様のご助言のおかげで、かなりすっきりしました。
当たり前のことなのかもしれませんが、のちのちこのトピックを見る人のために、
ここまでで私が分かったことを、DXライブラリを引用してまとめておきます。
DXライブラリでは、まず、以下のように.hと.libがまとめてフォルダに入っています。
コード:
プロジェクトに追加すべきファイル_VC用
|__DxLib.h
|__DxLib.lib
|__DxLib_d.lib
ここで、.libについては、2つあって、
ファイル名に"_d"が付与されているlibと、付与されていないlibがセットです。
さらに、DxLib.h内には、
Debugビルド時、Releaseビルド時でそれぞれにリンクするlibが分岐されるように#pragma~が記述されています。
Debugビルド時は、"_d"が付与されているlibが、
Releaseビルド時は、付与されていないlibがリンクされるようになっています。
へにっくすさんが教えてくださった内容に通じますね。
Debugで作成したライブラリファイルとReleaseで作成したライブラリファイルをごっちゃにしないでくださいね。
間違ったファイルを指定すると、これまたリンカエラーになるはずですので。
DXLIBでもDebugとReleaseでファイル名を別にしてあるはずです(ソースを直接みればわかると思いますが)。
そして、ISLe()さんもアドバイスの中でヒントをくださっていました。
マクロや環境変数を利用すれば、デバッグ版のライブラリファイル名には末尾にdを付けたり、コピー先を任意に変更できたり、便利に使えます。
私も真似してみたところ、正常にリンク、およびビルドできることを確認できました。
そのときの手順を書いておきます。
Step1.
LibTest.hにて、以下のように#ifdefでDebug時にリンクすべき.libと、Release時にリンクすべき.libを分岐するように書いておく
コード:
// 絶対パスだとのちのち困るので絶対パス指定しない。あとで適当なフォルダにまとめるので相対パスとする
#ifdef _DEBUG
#pragma comment(lib, "LibTest_d.lib") // Debug用
#else
#pragma comment(lib, "LibTest.lib") // Release用
#endif
Step2.
LibTestプロジェクトをビルドする際、DebugビルドとReleaseビルド両方を行い、
Debugビルドによってつくられた.libファイルには、ファイル名にもれなく"_d"をつけておく。
Step3.
適当なフォルダを作って、その中にLibTest.h、LibTest.lib、LibTest_d.libをコピーする。
Step4.
参照側プロジェクトでは、DXライブラリを使う手順と同様に、
・追加のインクルード ディレクトリ (C/C++ - 全般)
・追加のライブラリディレクトリ (リンカー - 全般)
この2点をプロパティ設定(いずれもStep3の適当なフォルダを指定)する。
これで、めでたく完成v(^^)v ということですね。理解してみるととても単純なことでした。
あとは、上記Stepの面倒そうな部分を自動化しちゃえばいいね!ということになります。
それについては、ISLe()さんがアドバイスしてくださっています。
Visual Studioのプロジェクトには、ビルド時に任意のコマンドを実行する機能があります。
ビルド前・リンク前・ビルド後それぞれ実行して欲しいコマンドラインを指定できます。
ビルド後に、バッチファイルを呼び出して、ビルドに成功したライブラリファイルとヘッダファイルをお好みのフォルダへ自動的にコピーするといったことができます。
マクロや環境変数を利用すれば、デバッグ版のライブラリファイル名には末尾にdを付けたり、コピー先を任意に変更できたり、便利に使えます。
これにて解決とさせていただこうと思います。皆様どうもありがとうございましたm(__)m
Re: VC++でのLibファイルの作り方、参照の仕方
Posted: 2014年9月18日(木) 18:58
by ISLe()
万人向けとして、「Releaseビルドしたものを配布しましょう」というのに間違いはないのですが、「Debugビルドしたものを配布してはいけません」というと正しくなくなってしまいます。
言うとしたら「Debugビルドした実行形式を配布してはいけません」というふうに言わないといけません。
それでも厳密には正しくないですが。
配布を許可されていないのは、スタートアップルーチンなども含めマイクロソフトが提供しているデバッグ版のライブラリです。
#配布可能なファイルのリストはVisual Studioをインストールしたフォルダにあります。
それらを含まなければ配布は可能です。
DXライブラリにデバッグ版があるのにおかしいと思いませんでしたか?
ヒープメモリのチェック用などデバッグ版にしかない関数を呼び出していたりするとリンクエラーになりますが、一切ライブラリに依存していないソースファイルから生成されたオブジェクトファイルであればDebugとReleaseの差異は最適化オプションくらいにしか現れません。