Platform SDK の DirectShow サンプルをビルドするには

DirectShow はもともと DirectX の一部でしたが、その後分離され、Platform SDK の機能になりました。

継子扱いってわけでもないでしょうが、Platform SDK にあるサンプルをそのまま nmake でビルドすると、ヘッダファイルが見つからないとエラーが出ます。
なぜなら、Makefile で、インクルードファイルパスとして DirectX のInclude しか見ていないから。

このサンプルは、Makefile がサブディレクトリ下で再帰的に次々と nmake を呼ぶため、単純に最下層の Makefile を全部手修正してたら、精魂尽き果てます。

そこで、環境変数を以下のように再設定します。

set DXSDK=%DXSDK_DIR%
set MSSDK=C:\Program Files\Microsoft Platform SDK
set DXSDK_DIR=$(DXSDK)Include" /I"$(MSSDK)

DXSDK_DIR を再設定するのがミソ。
下層の Makefile で、「/I"$(DXSDK_DIR)\Include"」 となってる部分が、これによって「/I":\Program Files\Microsoft DirectX SDK (November 2008)\Include" /I"C:\Program Files\Microsoft Platform SDK\Include"」と展開されて、ccが通ります。

ただし! これだけではライブラリパスが通らないのでリンクで失敗する。Makefile は lflags を見るので、「nmake makeopts=lflags=/LIBPATH:"%MSSDK%\Lib"」とするのが常套手段ですが、これがうまくいかない。
再帰で呼ばれた nmake には、コマンドラインがないから。

そこでtools.ini と 環境変数 INIT を設定してやります。

C:\Program Files\Microsoft Platform SDK\Samples\tools.ini

[nmake]
makeopts=lflags=/LIBPATH:"%MSSDK%\Lib" 
set INIT=$(MSSDK)\Samples

これで、nmake はまず設定ファイル tools.ini を読み込むようになり、下層で実行される nmake にも lflags の設定が効きます。

……これでうまく行くと思っただろう! だが大間違い!

nmake が何を思ったか " を抜いてしまうため、こんなエラーになる。

LINK : fatal error LNK1104: ファイル 'Files\Microsoft.obj' を開くことができませ
ん。
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 8\VC\BIN\l
ink.EXE"' : リターン コード '0x450'
Stop.

さて困った。Platform SDK を c:\MSSDK とかに再インストールしなくちゃならんのか? しかしそれでは今までのVisual Studioのプロジェクトを全部修正しなくちゃならんぞ?

そこでいいことを思いついた。

まず、"C:\Program Files\Microsoft Platform SDK\Lib" フォルダをまるごと、 c:\MSSDK_Lib にコピーする。そしてさっきのtools.iniを下のように修正。

[nmake]
makeopts=lflags=/LIBPATH:C:\MSSDK_Lib

これでOK! といいたいところだが、*.ax を作るところはいいんだけど、*.exe を作るところで失敗する。

こればっかりは仕方がない、失敗する Makefile をメモ帳で開いて、リンカのコマンドラインに $(conlflags) を追加する。
たとえばこんなふう。

$(OUTDIR)\memfile.exe:	$(OUTDIR)\memfile.obj 
	$(link) $(ldebug) /OUT:$(OUTDIR)\memfile.exe $(conlflags) /LIBPATH:"..\base\$(OUTDIR)" /NODEFAULTLIB /PDB:$(OUTDIR)\memfile.pdb /SUBSYSTEM:CONSOLE /MACHINE:$(CPU) $(STRMBASE) strmiids.lib winmm.lib odbc32.lib odbccp32.lib $(MSVCRT) kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib $(ATLS) asynbase.lib bufferoverflowu.lib "$(OUTDIR)\memfile.obj"

これでコンパイルは通るだろう。でもこれだけやってもまだ足りない。
マニフェストを埋めてないから。つづく。