Visual Studio 関連のインストーラはよくisoファイルで配布されることがあります。
しかも実際にインストールしてみるとなんらかの不都合に気づき、やはりアンインストールしたり他のバージョンを試すなどといったことも結構おきます。
(特に今回のような最小限インストールなどを目指しているとおきます)。
Windows 2000でインストールできるOperaの最終バージョンは12.02です。
またこれについては Firefox からであれば https://ftp.opera.com/pub/opera/win/1202/int よりダウンロードできます。
(IE5ではうまくいきません)。
Opera Ver12.02では、TLS1.2についてはデフォルトでは無効となっています。
「設定」⇒「詳細設定」⇒「セキュリティ」⇒「セキュリティプロトコル」から一応 TLS1.2を有効にできるようにはなっています。
しかしこれを有効にしても github の閲覧や 7-Zip をダウンロードしようとするとエラーが表示され残念ながらうまくいきません。
デフォルトで無効となっていることから、おそらくTLS1.2の実装はまだ完全ではなく実験的なものなのでしょう。
その他、もっと単純に wget for Windows や lynx for Windows なども思いつくかもしれませんが、これもダメです。
これらのサイトからダウンロードする場合、osdn や sourceforge などへリダイレクトされますが、こちらがTLS1.2となっており、
結局ダウンロードできません。
最後にダメ押ししましょう。
IEやFirefoxではもはやGoogleすらまともに動作しないのです。
ググることすらままなりません。
Windows 2000 の初期の状態は想像以上に過酷な環境ですね。
Windows 2000に最初から入っているIE5からでもダウンロード可能な所がポイントです。
見てのとおり、初めが「http://」で始まっております(つまり通信にHTTPSを使っておりませんので今回の問題は発生しません)。
またダウンロード可能なファイルだけが並んだシンプルなサイトですので、
IE5のような超古いブラウザからでも特に問題なく表示されます。
URLのドメインがmicrosoft.comとなっておりませんが、visualstudio.comもMSの公式サイトです。
qオプションで検索キーワードを指定できるらしく、visual studio 2017 がキーワードに含まれる項目を表示するようになっていると思われます。
それでも結構多くの項目が出て来て大変ですが、「Build Tools for Visual Studio 2017」とあるものがあるはずなので探しましょう。
そのようなものが二つ以上存在する場合は、横にバージョン番号が書かれていると思いますので、バージョンの新しい方(番号が大きい方)を選びましょう。
不具合等が修正されているため、このように複数のバージョンが存在している可能性が高いです。
私が確認した2021年12月時点では最も新しいものはBuild Tools for Visual Studio 2017 (version 15.9)でした。
Downloadボタンを押し、vs_BuildTools.exe (1.4MB)なるファイルをダウンロードします。
ファイルサイズからみてこれは単なるトリガーでしょう。
このバージョンは https://en.wikipedia.org/wiki/Microsoft_Windows_SDK によれば Last version with VC6 support and latest version with Windows 95 and Windows 98 support. とあります。
ただ、これより新しいSDKのインポートライブラリを使うと、その瞬間ただちにWindows 98では動作しない exe になるかといえばそんなことはなく、
MSが公式としてのサポートするものとしてはこれが最終であるということだと思います。
Windows 98でしかサポートされていないWindows APIのみを使ってコードを書いた上でコンパイルさえ通せば原理的には大丈夫というわけです。
ではこれより新しい、例えば「Microsoft Windows SDK for Windows 7 and .NET Framework 4」はどうでしょうか?
これはWindows SDKのバージョンとして言えば、いわゆる7.1、もっと正確に言えば 7.1.7600 となります。
因みに「C++ に関する Windows XP サポート」でインストールされるものは Windows SDK 7.1A ですが、これはより正確には 7.1.51106、つまり 7.1より少しだけ古いものとなります。
このバージョンは https://en.wikipedia.org/wiki/Microsoft_Windows_SDK によれば It is the latest version that officially supports Windows XP target. とあります。
では、これより新しいSDKのインポートライブラリを使うと、その瞬間Windows XPでは動作しない exe になるかといえばやはりそんなことはなく、MSが公式としてのサポートするものとしてはこれが最終であるということですね。
実際、Visual Studio 2008においてWindows SDK 8.1を使ってコンパイルしたバイナリが、Windows 2000(SP4)上で動作することを私は確認しております。
上記の項目3を選んだ方はこの項目4は不要です。
つまり上記の項目(C++ に関する Windows XP サポート)を選んだ方はこちらは不要ですし、
逆にこちら(Windows SDK 8.1)を選んだ方はC++ に関する Windows XP サポートは不要ということです。
インストールするコンポーネントは以上です。
尚、Windows SDK 10は無駄にサイズが大きいため(つまりさらに余計なものが増えているということでしょうが)、今回のミッションでは選択肢から外しますのでご了承ください。
必要なものは基本的にはC標準ライブラリのヘッダ(stdio.hなど)が格納されているディレクトリのパス、
Windows SDKのヘッダ(windows.hなど)が格納されているディレクトリのパスです。
ただし、VS2015以降(VC14以降)では Windows Universal CRT SDKにより、C標準ライブラリのヘッダが格納されているディレクトリがもう一つ存在しますので
そちらも指定することになります(実はこちらにstdio.hが存在します)。
必要なものは基本的にはC標準ライブラリのライブラリ(libcmt.libなど)が格納されているディレクトリのパス、
Windows SDKのインポートライブラリ(kernel32.libやuser32.libなど)が格納されているディレクトリのパスです。
ただし、VS2015以降(VC14以降)では Windows Universal CRT SDKにより、libucrt.libと呼ばれるライブラリが格納されているディレクトリも指定しなければなりません。
libcmt.lib、libucrt.lib、kernel32.libはlink.exeコマンドにおける引数に登場しませんが、これらは裏で必ずリンクされるものになります。
またレジストリの情報を参照しているということはポータブルではないということです。
Windows SDKやVCコンパイラ本体の位置を変更したり、他のマシンへ移動したりした場合にこれらのバッチファイルでは(少なくとも環境変数を微調整するレベルでは)対応できないということになります。
従って今回はこれらを使いません。
同一ドライブ内を移動する場合であれば /d オプションがなくても大丈夫ですが、常に /d をつけておけば間違いはありません。
特にバッチファイルで移動する処理を書く場合は常に cd /d として記述すべきです。
ディレクトリ名が長い場合などはキーボードから正確に打つのが大変ですが、最近のコマンドプロンプトではこのようなディレクトリのパスを入力する時に
tabキーを使えば、自動的な補完ができます。
たとえば m を打ってtabキーを押すだけで、配下に名前が m から始まるディレクトリ(mathematicsなどのディレクトリ)が存在するなら
それを自動的に補完します。
そのようなディレクトリが存在しないならばtabキーを押しても何もおきません。
また名前が m から始まるディレクトリがmathematics以外にも複数存在するようなケースでは、
tabキーを続けて連打すると補完の候補を次々と変えていくこともできます。
大変便利なので是非活用してください。
今回は一つずつ順に移動しましょう。
すなわちまず cd mathematics を実行し、次に cd ero_gazo を実行します。
その様子を以下に示します。
バッチファイルとは拡張子が bat となっているファイルであり、エクスプローラからダブルクリックして実行することができます。
このときコマンドプロンプトウィンドウが自動的に開き(このプログラムの実体はC:\Windows\system32\cmd.exeであり、これが起動しています)、
中に記述されているスクリプトが実行され、その結果がそのウィンドウ内に出力されます。
何はともあれ、まずもっとも簡単な Hello World バッチファイルから始めましょう。
まずtest1.batという空のファイルを作り、あなたのテキストエディタでそれを編集し、次のような内容にして保存しましょう。
すべてのバッチファイルの最初の行に書くおまじないと考えてもらってもいいです。
これの値は on がデフォルトですが、これが on の状態ですと以降の行で実行されるすべてのコマンドにおいて、
それを呼び出した(引数等を含めた)コマンドの記述自体もそのままコマンドプロンプトウィンドウ内に出力されてしまいます。
batファイル実行においては多くの場合、これでは出力結果が非常に醜くなり困りますので、通常は off にしておくわけです。
batファイルはコマンドプロンプト上からもこれを実行させることができます。
たとえば現在Zenkakuディレクトリにいるとして、その直下にあるtest1.batという名前のバッチファイルをコマンドプロンプト上から実行させるには以下のように
単に test1.bat と入力してEnterを押すだけで結構です(Press and key to continue ...の部分は日本語で表示されることもあります)。
C:\Zenkaku>
C:\Zenkaku>test1.bat
Hello World.
Press any key to continue ...
C:\Zenkaku>
@echo off
echo Now setting INCLUDE and LIB...
set PATH=%PATH%;C:\MyVC\bin
set INCLUDE=C:\MyWindowsSDK\include;C:\MyVC\include
set LIB=C:\MyWindowsSDK\lib;C:\MyVC\include
Now setting INCLUDE and LIB...
PATH =[C:Windows\system32;C:\Windows;C:\MyVC\bin]
INCLUDE=[C:\MyWindowsSDK\include;C:\MyVC\include]
LIB =[C:\MyWindowsSDK\lib;C:\MyVC\include]
Press any key to continue ...
@echo off
REM ----
REM This is a sample of if command and goto command.
REM ----
if not "%INCLUDE%" == "" echo Environment variable INCLUDE is already defined.
if not "%LIB%" == "" echo Environment variable LIB is already defined.
REM Setting VC environment variables if hello_config.bat exists.
if exist "hello_config.bat" call hello_config.bat
if "%INCLUDE%" == "" goto Error_Include
if "%LIB%" == "" goto Error_Lib
goto End
REM Error Handlings.
:Error_Include
echo Error: INCLUDE is not set.
goto End
:Error_Include
echo Error: LIB is not set.
goto End
:End
pause
if "%MACHINE%" == "x86" echo This is x86( Target OS is 32bit/64bit Windows).& goto Report_End
if "%MACHINE%" == "x64" echo This is x64( Target OS is 64bit Windows only).& goto Report_End
…
:Report_End
if exist "%proguard%" goto proguardOk
REM set proguard location for the Android tree case
set "PROGUARD_HOME=%~dp0\..\..\..\..\external\proguard"
set "proguard=%PROGUARD_HOME%\bin\%proguardExec%"
:proguardOk
@echo off
REM
REM DetectVC Ver1.0 (introduced in 2021.12)
REM
REM @brief
REM This batch file will automatically set up the PATH, INCLUDE, and LIB required to run VC.
REM It has been confirmed to work with VC6.0, VS2003, VS2005, VS2008, VS2010, VS2012, VS2013, VS2015, and VS2017.
REM
REM DetectVC will work to some extent with the default specification, but usually you will need to set the basic path
REM in the three environment variables ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, and ZNK_VC_UCRT_DIR before running this.
REM DetectVC will use them to set up the necessary environment variables for VC.
REM
REM @auther
REM Zenkaku
REM
REM @licence
REM Copyright (c) Zen-nippon Network Kenkyujo(ZNK)
REM Licensed under the NYSL( see http://www.kmonos.net/nysl/index.en.html for detail ).
REM
REM @disclaimer
REM This software is provided 'as-is', without any express or implied warranty.
REM In no event will the authors be held liable for any damages arising
REM from the use of this software.
REM
REM Check if the execution environment is 2000 or later.
REM NOTE: The "&" "&&" operator is not available in command.com before Windows 98.
if exist "%windir%\System32\findstr.exe" goto Windows2000OrLaterCheck_End
echo [NG]: This script requires Windows 2000 or later to work.
pause
goto End
:Windows2000OrLaterCheck_End
set DET_VC_PATH=
set DET_VC_INCLUDE=
set DET_VC_LIB=
set DET_VC_SUBSYS_VER=
if "%__DET_VC_ORIG_PATH_SAVE__%" == "" set __DET_VC_ORIG_PATH_SAVE__=%PATH%
setlocal
REM Default
if not "%ProgramFiles(x86)%" == "" set PROGRAM_FILE_X86_DIR=%ProgramFiles(x86)%& goto ProgramFilesAutoSet_End
if not "%ProgramFiles%" == "" set PROGRAM_FILE_X86_DIR=%ProgramFiles%& goto ProgramFilesAutoSet_End
set PROGRAM_FILE_X86_DIR=C:\Program Files& goto ProgramFilesAutoSet_End
:ProgramFilesAutoSet_End
if "%ZNK_VC_WINSDK_DIR%" == "" set ZNK_VC_WINSDK_DIR=%PROGRAM_FILE_X86_DIR%
if "%ZNK_VC_UCRT_DIR%" == "" set ZNK_VC_UCRT_DIR=%PROGRAM_FILE_X86_DIR%
if not "%ZNK_VC_DIR%" == "" goto ZnkVCDirAutoSet_End
REM VS2017
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio\2017\BuildTools\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2015(VC14)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 14.0\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2013(VC12)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 12.0\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2012(VC11)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 11.0\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2010(VC10)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 10.0\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2008(VC9)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 9.0\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2005(VC8)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 8\VC
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS2003(VC7.1)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio .NET 2003\Vc7
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
REM VS6.0
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio\VC98
if exist "%TRY_DIR%" set ZNK_VC_DIR=%TRY_DIR%& goto ZnkVCDirAutoSet_End
echo DetectVC: Warning: ZNK_VC_DIR is not set. Also, the default could not be detected.
:ZnkVCDirAutoSet_End
set VC_DIR=%ZNK_VC_DIR%
set WINSDK_DIR=%ZNK_VC_WINSDK_DIR%
set UCRT_DIR=%ZNK_VC_UCRT_DIR%
REM CmdArg1:
REM Since we are inside setlocal-endlocal, this overwrite is acceptable.
if "%1" == "x64" set MACHINE=x64& goto CmdArg1_End
if "%1" == "x86" set MACHINE=x86& goto CmdArg1_End
if "%1" == "_" goto MachineAutoSet
if "%1" == "" goto MachineAutoSet
echo DetectVC: Warning: Invalid argument(1nd) "%1" : We regard it as "_".
REM default: MachineAutoSet
:MachineAutoSet
if not "%MACHINE%" == "x64" set MACHINE=x86
REM if "%PROCESSOR_ARCHITECTURE%" == "AMD64" set MACHINE=x64
:CmdArg1_End
REM CmdArg2:
REM This is a way to add to the environment variables of the VC system.
REM For environment variables of the DET_VC_* system, the specification here is not relevant.
set HOW_TO_SET=overwrite
if "%2" == "overwrite" set HOW_TO_SET=overwrite& goto CmdArg2_End
if "%2" == "add_back" set HOW_TO_SET=add_back& goto CmdArg2_End
if "%2" == "add_front" set HOW_TO_SET=add_front& goto CmdArg2_End
if "%2" == "_" goto CmdArg2_End
if "%2" == "" goto CmdArg2_End
echo DetectVC: Warning: Invalid argument(2nd) "%2" : We regard it as "%HOW_TO_SET%".
:CmdArg2_End
REM CmdArg3:
REM Specifies the type of environment variables that are actually exported.
REM There are two main types of environment variables: environment variables starting with DET_VC_*
REM or VC environment variables( PATH, INCLUDE, LIB ).
REM In the case of "recommanded" mode, DET_VC_SUBSYS_VER, PATH, LIB, and INCLUDE are exported.
set EXPORT_MODE=recommanded
if "%3" == "all" set EXPORT_MODE=all& goto CmdArg3_End
if "%3" == "det_vars_only" set EXPORT_MODE=det_vars_only& goto CmdArg3_End
if "%3" == "vc_vars_only" set EXPORT_MODE=vc_vars_only& goto CmdArg3_End
if "%3" == "recommanded" goto CmdArg3_End
if "%3" == "_" goto CmdArg3_End
if "%3" == "" goto CmdArg3_End
echo DetectVC: Warning: Invalid argument(3nd) "%3" : We regard it as "%EXPORT_MODE%".
:CmdArg3_End
REM CmdArg4:
REM Specify verbosity of reporting.
set VERBOSE_DETAIL=no
set VERBOSE_REPORT=yes
if "%4" == "detail" set VERBOSE_REPORT=yes& set VERBOSE_DETAIL=yes& goto CmdArg4_End
if "%4" == "report" set VERBOSE_REPORT=yes& goto CmdArg4_End
if "%4" == "silent" set VERBOSE_REPORT=no& set VERBOSE_DETAIL=no& goto CmdArg4_End
if "%4" == "_" goto CmdArg4_End
if "%4" == "" goto CmdArg4_End
echo DetectVC: Warning: Invalid argument(4nd) "%4" : We regard it as "_".
:CmdArg4_End
set FINDSTR=findstr
if exist "%windir%\System32\findstr.exe" set FINDSTR=%windir%\System32\findstr.exe
set SAFE_CD=cd /d
REM echo VCTop:
set TRY_DIR=%VC_DIR%
call :Func_FindVCTop
if not "%ANS_DIR%" == "" set VC_DIR=%ANS_DIR%
REM echo VCWinSdkDir:
set TRY_DIR=%WINSDK_DIR%
call :Func_FindVCWinSdkDir
if not "%ANS_DIR%" == "" set WINSDK_DIR=%ANS_DIR%
REM echo VCUcrtDir:
set TRY_DIR=%UCRT_DIR%
call :Func_FindVCUcrtDir
if not "%ANS_DIR%" == "" set UCRT_DIR=%ANS_DIR%
REM echo VCBin:
set TRY_DIR=%VC_DIR%
set SUB_DIR=Hostx86
set LANDMARK_EXE=cl.exe
set TRY_MACHINE=%MACHINE%
call :Func_FindVCBin
if not "%ANS_DIR%" == "" set VC_BIN=%ANS_DIR%
if "%VC_BIN%" == "" echo DetectVC: Warning: VC_BIN is not detected.
REM echo VCBin2: ( for the path where the dll that cl.exe depends on is located )
set TRY_DIR=%VC_DIR%
set SUB_DIR=Hostx86
set LANDMARK_EXE=cl.exe
set TRY_MACHINE=x86
call :Func_FindVCBin
if not "%ANS_DIR%" == "" if not "%ANS_DIR%" == "%VC_BIN%" set VC_BIN2=%ANS_DIR%
REM echo VCBin3: ( for old VC )
if exist "%VC_DIR%\..\Common7\IDE" set VC_BIN3=%VC_DIR%\..\Common7\IDE
REM The following scan is intended to find for VC6.0 dll path.
set ANS_PATH=%VC_BIN3%
if exist "%VC_DIR%\..\Common\MSDev98\Bin\mspdb*.dll" call :Func_PathAddBack "%VC_DIR%\..\Common\MSDev98\Bin"
set VC_BIN3=%ANS_PATH%
REM The following scan is intended to find, for example, VC_DIR\..\Visual Studio .NET Professional 2003 - Japanese\msvcp71.dll.
set TRY_DIR=%VC_DIR%\..
set ANS_PATH=
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\*.dll" call :Func_PathAddBack "%TRY_DIR%\%%a"
if not "%ANS_PATH%" == "" set VC_BIN3=%VC_BIN3%;%ANS_PATH%
REM The following scan is intended to find, for example, VC_DIR\redist\x86\Microsoft.VC*.CRT (for VS2013)
set TRY_DIR=%VC_DIR%\redist\x86
set ANS_PATH=
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i "Microsoft\.VC.*\.CRT"' ) do if exist "%TRY_DIR%\%%a\*.dll" call :Func_PathAddBack "%TRY_DIR%\%%a"
if not "%ANS_PATH%" == "" set VC_BIN3=%VC_BIN3%;%ANS_PATH%
REM echo VCInclude:
set TRY_DIR=%VC_DIR%
set SUB_DIR=um
set LANDMARK_HDR=vector
call :Func_FindVCSdkInclude
if not "%ANS_DIR%" == "" set VC_INCLUDE=%ANS_DIR%
REM echo VCLib:
set TRY_DIR=%VC_DIR%
set SUB_DIR=um
set LANDMARK_LIB=libcmt.lib
call :Func_FindVCSdkLib
if not "%ANS_DIR%" == "" set VC_LIB=%ANS_DIR%
REM echo VCWinSdkBin: ( for the path of rc.exe )
set TRY_DIR=%WINSDK_DIR%
set SUB_DIR=Hostx86
set LANDMARK_EXE=rc.exe
set TRY_MACHINE=x86
call :Func_FindVCSdkBin
if not "%ANS_DIR%" == "" set WINSDK_BIN=%ANS_DIR%
REM echo VCWinSdkInclude:
set TRY_DIR=%WINSDK_DIR%
set SUB_DIR=um
set LANDMARK_HDR=windows.h
call :Func_FindVCSdkInclude
if not "%ANS_DIR%" == "" set WINSDK_INCLUDE=%ANS_DIR%
set TRY_DIR=%WINSDK_DIR%
set SUB_DIR=shared
set LANDMARK_HDR=winapifamily.h
call :Func_FindVCSdkInclude
if not "%ANS_DIR%" == "" set WINSDK_INCLUDE=%WINSDK_INCLUDE%;%ANS_DIR%
REM echo VCWinSdkLib:
set TRY_DIR=%WINSDK_DIR%
set SUB_DIR=um
set LANDMARK_LIB=user32.lib
call :Func_FindVCSdkLib
if not "%ANS_DIR%" == "" set WINSDK_LIB=%ANS_DIR%
REM echo VCUcrtInclude:
set TRY_DIR=%UCRT_DIR%
set SUB_DIR=ucrt
set LANDMARK_HDR=stdio.h
call :Func_FindVCSdkInclude
if not "%ANS_DIR%" == "" set UCRT_INCLUDE=%ANS_DIR%
REM echo VCUcrtLib:
set TRY_DIR=%UCRT_DIR%
set SUB_DIR=ucrt
set LANDMARK_LIB=libucrt.lib
call :Func_FindVCSdkLib
if not "%ANS_DIR%" == "" set UCRT_LIB=%ANS_DIR%
REM echo VCInclude(ATLMFC):
set TRY_DIR=%VC_DIR%\atlmfc
set SUB_DIR=um
set LANDMARK_HDR=afxres.h
call :Func_FindVCSdkInclude
if not "%ANS_DIR%" == "" set VC_ATLMFC_INCLUDE=%ANS_DIR%
REM echo VCLib(ATLMFC):
set TRY_DIR=%VC_DIR%\atlmfc
set SUB_DIR=um
set LANDMARK_LIB=atl.lib
call :Func_FindVCSdkLib
if not "%ANS_DIR%" == "" set VC_ATLMFC_LIB=%ANS_DIR%
if not "%VERBOSE_DETAIL%" == "yes" goto ReportForDetail_End
echo:
echo DetectForDetail:
call :Func_PrintPathStr "VC_DIR" "%VC_DIR%"
call :Func_PrintPathStr "VC_BIN" "%VC_BIN%"
call :Func_PrintPathStr "VC_BIN2" "%VC_BIN2%"
call :Func_PrintPathStr "VC_BIN3" "%VC_BIN3%"
call :Func_PrintPathStr "VC_INCLUDE" "%VC_INCLUDE%"
call :Func_PrintPathStr "VC_LIB" "%VC_LIB%"
call :Func_PrintPathStr "WINSDK_DIR" "%WINSDK_DIR%"
call :Func_PrintPathStr "WINSDK_INCLUDE" "%WINSDK_INCLUDE%"
call :Func_PrintPathStr "WINSDK_LIB" "%WINSDK_LIB%"
call :Func_PrintPathStr "WINSDK_BIN" "%WINSDK_BIN%"
call :Func_PrintPathStr "UCRT_DIR" "%UCRT_DIR%"
call :Func_PrintPathStr "UCRT_INCLUDE" "%UCRT_INCLUDE%"
call :Func_PrintPathStr "UCRT_LIB" "%UCRT_LIB%"
call :Func_PrintPathStr "VC_ATLMFC_INCLUDE" "%VC_ATLMFC_INCLUDE%"
call :Func_PrintPathStr "VC_ATLMFC_LIB" "%VC_ATLMFC_LIB%"
echo:
:ReportForDetail_End
REM echo IntegrationOfDetection:
set ANS_PATH=%ZNK_VC_PATH%
call :Func_PathAddBack "%VC_BIN%"
call :Func_PathAddBack "%VC_BIN2%"
call :Func_PathAddBack "%VC_BIN3%"
call :Func_PathAddBack "%WINSDK_BIN%"
set DET_VC_PATH=%ANS_PATH%
REM NOTE:
REM WINSDK_INCLUDE should be given higher priority than VC_INCLUDE.
REM Otherwise, when you compile WinSDK8.1 with VS2010 or earlier VC, you will get a compilation error.
REM ( https://devblogs.microsoft.com/cppblog/using-the-windows-8-sdk-with-visual-studio-2010-configuring-multiple-projects )
set ANS_PATH=%ZNK_VC_INCLUDE%
call :Func_PathAddBack "%VC_ATLMFC_INCLUDE%"
call :Func_PathAddBack "%WINSDK_INCLUDE%"
call :Func_PathAddBack "%VC_INCLUDE%"
call :Func_PathAddBack "%UCRT_INCLUDE%"
set DET_VC_INCLUDE=%ANS_PATH%
set ANS_PATH=%ZNK_VC_LIB%
call :Func_PathAddBack "%VC_ATLMFC_LIB%"
call :Func_PathAddBack "%WINSDK_LIB%"
call :Func_PathAddBack "%VC_LIB%"
call :Func_PathAddBack "%UCRT_LIB%"
set DET_VC_LIB=%ANS_PATH%
REM echo DetectLinkSubsysVer:
REM See WINVER macro for details.
setlocal
REM for dll path
set PATH_SAVE=%PATH%
set PATH=%__DET_VC_ORIG_PATH_SAVE__%;%DET_VC_PATH%
set TRY_LINK_EXE=%VC_BIN%\link.exe
REM set CURRENT_DIR_SAVE=%CD%
REM %SAFE_CD% "%VC_BIN%"
REM if "%VERBOSE_DETAIL%" == "yes" echo [FYI]: DetectVC: Report: Check link.exe in [%CD%]
REM if not exist "link.exe" echo DetectVC: Warning: link.exe not found in [%VC_BIN%].
REM if not exist "link.exe" goto DetectLinkVer_End
if not exist "%TRY_LINK_EXE%" goto DetectLinkVer_End
REM Target OS : Windows 95/98
call :Func_CheckVCLinkSubsysVer "4.00"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
REM Target OS : Windows 2000/ME
call :Func_CheckVCLinkSubsysVer "5.00"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
REM Target OS : Windows XP etc.
if "%MACHINE%" == "x64" goto DetectLinkVer_x64
REM Target OS : Windows XP (x86)
call :Func_CheckVCLinkSubsysVer "5.01"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
goto DetectLinkVer_x64_End
:DetectLinkVer_x64
REM Target OS : Windows XP (x64)/ Windows Server 2003
call :Func_CheckVCLinkSubsysVer "5.02"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
goto DetectLinkVer_x64_End
:DetectLinkVer_x64_End
REM Target OS : Vista
call :Func_CheckVCLinkSubsysVer "6.00"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
REM Target OS : Windows 7
call :Func_CheckVCLinkSubsysVer "6.01"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
REM Target OS : Windows 8
call :Func_CheckVCLinkSubsysVer "6.02"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
REM Target OS : Windows 10
call :Func_CheckVCLinkSubsysVer "10.00"
if not "%DET_VC_SUBSYS_VER%" == "" goto DetectLinkVer_End
goto DetectLinkVer_End
:DetectLinkVer_End
REM %SAFE_CD% %CURRENT_DIR_SAVE%
set PATH=%PATH_SAVE%
REM export variables:
REM DET_VC_SUBSYS_VER
endlocal& set DET_VC_SUBSYS_VER=%DET_VC_SUBSYS_VER%
REM echo HowtoSet VCVars:
REM If a ZNK_VC_* series environment variable is defined,
REM it will be inserted before the DET_VC_* series one in priority.
if not "%HOW_TO_SET%" == "overwrite" goto HowtoSet_Overwrite_End
set ANS_PATH=%__DET_VC_ORIG_PATH_SAVE__%
call :Func_PathAddBack "%DET_VC_PATH%"
set PATH=%ANS_PATH%
set ANS_PATH=
call :Func_PathAddBack "%DET_VC_INCLUDE%"
set INCLUDE=%ANS_PATH%
set ANS_PATH=
call :Func_PathAddBack "%DET_VC_LIB%"
set LIB=%ANS_PATH%
:HowtoSet_Overwrite_End
if not "%HOW_TO_SET%" == "add_back" goto HowtoSet_AddBack_End
set ANS_PATH=%PATH%
call :Func_PathAddBack "%DET_VC_PATH%"
set PATH=%ANS_PATH%
set ANS_PATH=%INCLUDE%
call :Func_PathAddBack "%DET_VC_INCLUDE%"
set INCLUDE=%ANS_PATH%
set ANS_PATH=%LIB%
call :Func_PathAddBack "%DET_VC_LIB%"
set LIB=%ANS_PATH%
:HowtoSet_AddBack_End
if not "%HOW_TO_SET%" == "add_front" goto HowtoSet_AddFront_End
set ANS_PATH=%PATH%
call :Func_PathAddFront "%DET_VC_PATH%"
set PATH=%ANS_PATH%
set ANS_PATH=%INCLUDE%
call :Func_PathAddFront "%DET_VC_INCLUDE%"
set INCLUDE=%ANS_PATH%
set ANS_PATH=%LIB%
call :Func_PathAddFront "%DET_VC_LIB%"
set LIB=%ANS_PATH%
:HowtoSet_AddFront_End
REM export variables:
REM DET_VC_PATH
REM DET_VC_INCLUDE
REM DET_VC_LIB
REM DET_VC_SUBSYS_VER
REM PATH
REM INCLUDE
REM LIB
if "%EXPORT_MODE%" == "recommanded" goto Export_recommanded
if "%EXPORT_MODE%" == "all" goto Export_all
if "%EXPORT_MODE%" == "det_vars_only" goto Export_det_vars_only
if "%EXPORT_MODE%" == "vc_vars_only" goto Export_vc_vars_only
REM default : Export_recommanded
:Export_recommanded
if not "%VERBOSE_REPORT%" == "yes" goto ExportReport_recommanded_End
echo ExportMode: %EXPORT_MODE%
echo:
echo VCVars:
call :Func_PrintPathStr "PATH" "%PATH%"
call :Func_PrintPathStr "INCLUDE" "%INCLUDE%"
call :Func_PrintPathStr "LIB" "%LIB%"
echo:
echo DetectSubsystemVersion:
echo DET_VC_SUBSYS_VER=[%DET_VC_SUBSYS_VER%]
echo:
:ExportReport_recommanded_End
endlocal ^
& call :Func_Set "DET_VC_SUBSYS_VER" "%DET_VC_SUBSYS_VER%" ^
& call :Func_Set "PATH" "%PATH%" ^
& call :Func_Set "INCLUDE" "%INCLUDE%" ^
& call :Func_Set "LIB" "%LIB%"
goto Export_End
:Export_all
if not "%VERBOSE_REPORT%" == "yes" goto ExportReport_all_End
echo ExportMode: %EXPORT_MODE%
echo:
echo DetectVars Detail:
call :Func_PrintPathStr "DET_VC_PATH" "%DET_VC_PATH%"
call :Func_PrintPathStr "DET_VC_INCLUDE" "%DET_VC_INCLUDE%"
call :Func_PrintPathStr "DET_VC_LIB" "%DET_VC_LIB%"
echo:
echo VCVars:
call :Func_PrintPathStr "PATH" "%PATH%"
call :Func_PrintPathStr "INCLUDE" "%INCLUDE%"
call :Func_PrintPathStr "LIB" "%LIB%"
echo:
echo DetectSubsystemVersion:
echo DET_VC_SUBSYS_VER=[%DET_VC_SUBSYS_VER%]
echo:
:ExportReport_all_End
endlocal ^
& call :Func_Set "DET_VC_PATH" "%DET_VC_PATH%" ^
& call :Func_Set "DET_VC_INCLUDE" "%DET_VC_INCLUDE%" ^
& call :Func_Set "DET_VC_LIB" "%DET_VC_LIB%" ^
& call :Func_Set "DET_VC_SUBSYS_VER" "%DET_VC_SUBSYS_VER%" ^
& call :Func_Set "PATH" "%PATH%" ^
& call :Func_Set "INCLUDE" "%INCLUDE%" ^
& call :Func_Set "LIB" "%LIB%"
goto Export_End
:Export_det_vars_only
if not "%VERBOSE_REPORT%" == "yes" goto ExportReport_det_vars_End
echo ExportMode: %EXPORT_MODE%
echo:
echo DetectVars Detail:
call :Func_PrintPathStr "DET_VC_PATH" "%DET_VC_PATH%"
call :Func_PrintPathStr "DET_VC_INCLUDE" "%DET_VC_INCLUDE%"
call :Func_PrintPathStr "DET_VC_LIB" "%DET_VC_LIB%"
echo:
echo DetectSubsystemVersion:
echo DET_VC_SUBSYS_VER=[%DET_VC_SUBSYS_VER%]
echo:
:ExportReport_det_vars_End
endlocal ^
& call :Func_Set "DET_VC_PATH" "%DET_VC_PATH%" ^
& call :Func_Set "DET_VC_INCLUDE" "%DET_VC_INCLUDE%" ^
& call :Func_Set "DET_VC_LIB" "%DET_VC_LIB%" ^
& call :Func_Set "DET_VC_SUBSYS_VER" "%DET_VC_SUBSYS_VER%"
goto Export_End
:Export_vc_vars_only
if not "%VERBOSE_REPORT%" == "yes" goto ExportReport_vc_vars_End
echo ExportMode: %EXPORT_MODE%
echo:
echo VCVars:
call :Func_PrintPathStr "PATH" "%PATH%"
call :Func_PrintPathStr "INCLUDE" "%INCLUDE%"
call :Func_PrintPathStr "LIB" "%LIB%"
echo:
:ExportReport_vc_vars_End
endlocal ^
& call :Func_Set "PATH" "%PATH%" ^
& call :Func_Set "INCLUDE" "%INCLUDE%" ^
& call :Func_Set "LIB" "%LIB%"
goto Export_End
:Export_End
goto End
REM ----
REM Sub-routine Definitions
REM ----
REM
REM Note:
REM If you specify empty in the 'for' command delim (i.e. /f "delims="), only the newline code will be used as the delimiter.
REM
REM Sub-routine Func_PathAddBack
REM Add the directory given in the argument to the back of ANS_PATH.
REM
REM Arg : "%1"
REM Return : ANS_PATH
:Func_PathAddBack
call :Func_ConnectStr "%ANS_PATH%" %1 ";"
set ANS_PATH=%ANS_STR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_PathAddFront
REM Add the directory given in the argument to the front of ANS_PATH.
REM
REM Arg : "%1"
REM Return : ANS_PATH
:Func_PathAddFront
call :Func_ConnectStr %1 "%ANS_PATH%" ";"
set ANS_PATH=%ANS_STR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_ConnectStr
REM Concatenate strings in the order lhs-strings delimiter rhs-strings.
REM However, if either lhs-strings or rhs-strings is an empty string, delimiter is not added.
REM
REM Arg : const "%1" lhs-string
REM Arg : const "%2" rhs-string
REM Arg : const "%3" delimitor
REM Return : ANS_STR
:Func_ConnectStr
setlocal
set LHS=%1
set RHS=%2
set DLM=%3
REM Strip sides quotes.
set LHS=%LHS:~1,-1%
set RHS=%RHS:~1,-1%
set DLM=%DLM:~1,-1%
if "%LHS%" == "" goto Func_ConnectStr_EmptyLHS
if "%RHS%" == "" goto Func_ConnectStr_EmptyRHS
set ANS_STR=%LHS%%DLM%%RHS%
goto Func_ConnectStr_End
:Func_ConnectStr_EmptyLHS
set ANS_STR=%RHS%
goto Func_ConnectStr_End
:Func_ConnectStr_EmptyRHS
set ANS_STR=%LHS%
goto Func_ConnectStr_End
:Func_ConnectStr_End
endlocal& set ANS_STR=%ANS_STR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCTop
REM Arg : TRY_DIR
REM Return : ANS_DIR
:Func_FindVCTop
set ANS_DIR=
REM for VC8.0 or later
if exist "%TRY_DIR%\VC" set TRY_DIR=%TRY_DIR%\VC
REM for VC6.0
if exist "%TRY_DIR%\VC98" set TRY_DIR=%TRY_DIR%\VC98
REM for VC7.1
if exist "%TRY_DIR%\Vc7" set TRY_DIR=%TRY_DIR%\Vc7
REM for VC2017
if exist "%TRY_DIR%\Tools\MSVC" set TRY_DIR=%TRY_DIR%\Tools\MSVC
if exist "%TRY_DIR%\BIN" set ANS_DIR=%TRY_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCTop_End
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\BIN" set ANS_DIR=%TRY_DIR%\%%a
if not "%ANS_DIR%" == "" goto Func_FindVCTop_End
:Func_FindVCTop_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCWinSdkDir
REM Arg : TRY_DIR
REM Return : ANS_DIR
:Func_FindVCWinSdkDir
setlocal
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
REM Microsoft SDKs type : Windows SDK 7.1 or 6.0 etc.
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\Microsoft SDKs" set TRY_DIR=%TRY_DIR%\Microsoft SDKs
if exist "%TRY_DIR%\Windows" if not exist "%TRY_DIR%\Windows\system32" set TRY_DIR=%TRY_DIR%\Windows
if exist "%TRY_DIR%\include" set ANS_DIR=%TRY_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
call :Func_FindVCWinSdkVerDir
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
REM Windows Kits type : Windows SDK 8.0 or 10 etc.
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\Windows Kits" set TRY_DIR=%TRY_DIR%\Windows Kits
if exist "%TRY_DIR%\include" set ANS_DIR=%TRY_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
call :Func_FindVCWinSdkVerDir
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
REM for Future version ?
REM set TRY_DIR=%TRY_DIR_SAVE%
REM if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\LIB" set ANS_DIR=%TRY_DIR%\%%a
REM if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
REM Old VC : VC\PlatformSDK (VS2003,VS2005)
if exist "%ZNK_VC_DIR%\PlatformSDK" set ANS_DIR=%ZNK_VC_DIR%\PlatformSDK
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
REM Old VC : VC\Include\windows.h (VC6.0) : VC_DIR itself is a WINSDK_DIR.
if exist "%ZNK_VC_DIR%"\Include\windows.h set ANS_DIR=%ZNK_VC_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkDir_End
echo DetectVC: Warning: WINSDK_DIR is not detected in [%TRY_DIR_SAVE%].
:Func_FindVCWinSdkDir_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCUcrtDir
REM Arg : TRY_DIR
REM Return : ANS_DIR
:Func_FindVCUcrtDir
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
REM for Windows SDK 10
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\Windows Kits\10\LIB" set ANS_DIR=%TRY_DIR%\Windows Kits\10
if not "%ANS_DIR%" == "" goto Func_FindVCUcrtDir_End
REM for Windows SDK 10 (for modified by users)
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\Windows Kits" set TRY_DIR=%TRY_DIR%\Windows Kits
if exist "%TRY_DIR%\10" set TRY_DIR=%TRY_DIR%\10
if exist "%TRY_DIR%\LIB" set ANS_DIR=%TRY_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCUcrtDir_End
REM for Future version ?
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\LIB" set ANS_DIR=%TRY_DIR%\%%a
if not "%ANS_DIR%" == "" goto Func_FindVCUcrtDir_End
:Func_FindVCUcrtDir_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCSdkInclude
REM Arg : TRY_DIR
REM Arg : const SUB_DIR ( e.g. um, ucrt )
REM Arg : const LANDMARK_HDR ( e.g. windows.h, stdio.h )
REM Return : ANS_DIR
:Func_FindVCSdkInclude
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
REM for Windows SDK 8.1
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\include\%SUB_DIR%\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include\%SUB_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCSdkInclude_End
REM for Windows SDK 7.1 and 6.0
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\include\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include
if not "%ANS_DIR%" == "" goto Func_FindVCSdkInclude_End
REM for Windows SDK 10
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\include" set TRY_DIR=%TRY_DIR%\include
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%
if not "%ANS_DIR%" == "" goto Func_FindVCSdkInclude_End
:Func_FindVCSdkInclude_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCSdkLib
REM Arg : TRY_DIR
REM Arg : const SUB_DIR ( e.g. um, ucrt )
REM Arg : const LANDMARK_LIB ( e.g. user32.lib, libucrt.lib )
REM Return : ANS_DIR
:Func_FindVCSdkLib
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
if "%MACHINE%" == "x64" goto Func_FindVCSdkLib_x64
REM x86
REM for VC2017
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib\x86\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib\x86
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
REM for Windows SDK 7.1 and 6.0
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
REM for Windows SDK 8.1 or later
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib" set TRY_DIR=%TRY_DIR%\lib
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x86\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x86
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
goto Func_FindVCSdkLib_x64_End
:Func_FindVCSdkLib_x64
REM x64
REM for VC2017, Windows SDK 7.1 and 6.0
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib\x64\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib\x64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
REM for PlatformSDK 5.1
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib\amd64\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib\amd64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
REM for Windows SDK 8.1 or later
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib" set TRY_DIR=%TRY_DIR%\lib
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x64\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkLib_End
:Func_FindVCSdkLib_x64_End
:Func_FindVCSdkLib_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCSdkBin
REM Arg : TRY_DIR
REM Arg : const SUB_DIR ( e.g. Hostx86 )
REM Arg : const LANDMARK_EXE ( e.g. rc.exe )
REM Arg : const TRY_MACHINE ( x86 or x64 )
REM Return : ANS_DIR
:Func_FindVCSdkBin
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
if "%TRY_MACHINE%" == "x64" goto Func_FindVCSdkBin_x64
REM x86
REM for PlatformSDK 5.2 WinSDK 6.0
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for WinSDK 8.0 WinSDK 10
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\x86\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\x86
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for Future version ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin" set TRY_DIR=%TRY_DIR%\bin
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x86\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x86
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
goto Func_FindVCSdkBin_x64_End
:Func_FindVCSdkBin_x64
REM x64
REM for PlatformSDK 5.2 WinSDK 6.0
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for VC(PlatformSDK is marged) ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\x86_amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\x86_amd64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for WinSDK 8.0 WinSDK 10
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\x64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\x64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for Future version(WinSDK is marged) ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin" set TRY_DIR=%TRY_DIR%\bin
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
REM for VC(PlatformSDK is marged) ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\amd64
if not "%ANS_DIR%" == "" goto Func_FindVCSdkBin_End
:Func_FindVCSdkBin_x64_End
:Func_FindVCSdkBin_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCBin
REM Arg : TRY_DIR
REM Arg : const SUB_DIR ( e.g. Hostx86 )
REM Arg : const LANDMARK_EXE ( e.g. cl.exe )
REM Arg : const TRY_MACHINE ( x86 or x64 )
REM Return : ANS_DIR
:Func_FindVCBin
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
if "%TRY_MACHINE%" == "x64" goto Func_FindVCBin_x64
REM x86
REM for VC2017
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\Hostx86\x86\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\Hostx86\x86
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
REM for VC10, VC11
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
REM for Future version ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin" set TRY_DIR=%TRY_DIR%\bin
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x86\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x86
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
goto Func_FindVCBin_x64_End
:Func_FindVCBin_x64
REM x64
REM for VC2017
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\Hostx86\x64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\Hostx86\x64
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
REM for VC10, VC11
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\x86_amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\x86_amd64
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
REM for Future version ?
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin" set TRY_DIR=%TRY_DIR%\bin
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| %FINDSTR% /i ".*"' ) do if exist "%TRY_DIR%\%%a\%SUB_DIR%\x64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\%%a\%SUB_DIR%\x64
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
REM Alternatively, we use Native compiler (not Cross-compiler) (in old VC)
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\amd64
if not "%ANS_DIR%" == "" goto Func_FindVCBin_End
:Func_FindVCBin_x64_End
:Func_FindVCBin_End
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindVCWinSdkVerDir
REM Arg : TRY_DIR
REM Return : ANS_DIR
:Func_FindVCWinSdkVerDir
setlocal
set ANS_DIR=
set TRY_DIR_SAVE=%TRY_DIR%
set VER=
set VER=v6.0
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=v6.0a
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=v6.1
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=v7.0a
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=v7.1
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=v7.1A
if exist "%TRY_DIR%\%VER%\include\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=8.0
if exist "%TRY_DIR%\%VER%\include\um\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=8.0A
if exist "%TRY_DIR%\%VER%\include\um\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=8.1
if exist "%TRY_DIR%\%VER%\include\um\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=8.1A
if exist "%TRY_DIR%\%VER%\include\um\windows.h" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
set VER=10
if exist "%TRY_DIR%\%VER%\include" set ANS_DIR=%TRY_DIR%\%VER%
if not "%ANS_DIR%" == "" goto Func_FindVCWinSdkVerDir_End
:Func_FindVCWinSdkVerDir_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_CheckVCLinkSubsysVer
REM Arg : const "%1" Try Version
REM Arg : const TRY_LINK_EXE
REM Return : DET_VC_SUBSYS_VER
:Func_CheckVCLinkSubsysVer
REM Strip sides quotes.
set TRY_VER=%1
set TRY_VER=%TRY_VER:~1,-1%
REM
REM NOTE:
REM The check of SubsystemVersion also requires the option /MACHINE to be specified.
REM Otherwise, Warnig LNK4010: will not be displayed correctly.
REM (Supported SubsystemVersion may differ depending on whether X86 or AMD64 is specified.)
REM
if "%MACHINE%" == "x64" ( set VC_MACHINE=AMD64 ) else ( set VC_MACHINE=X86 )
REM
REM NOTE:
REM The original command is "LINK /MACHINE:%VC_MACHINE% /SUBSYSTEM,WINDOWS,%TRY_VER%",
REM but in a for-in statement, "," is a special character, so it must be escaped by writing "^" before ",".
REM
REM NOTE:
REM If you want to dynamically execute an arbitrary command in the IN ( '...' ) of a FOR statement,
REM you need to enclose the path in double quotes.
REM In this case, you should avoid using double quotes (") at the beginning and end of the IN ( '...' ),
REM because then those double quotes will be forced to be stripped.
REM
REM To do so, insert a dummy command, 'if x==x', at the very beginning of the IN ( '...' ).
REM Note that "set IN_BEGIN=if x^^=^^=x" by itself works with the "^" as an escape character,
REM so to store "if x^=^=x", you must use "if x^^=^^=x".
REM
set IN_BEGIN=if x^^=^^=x
set IN_REDIRECT_2TO1=2^^^>^^^&1
REM set CMD=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\link.exe
REM for /f "delims=" %%a in ( '%IN_BEGIN% "%CMD%" ^| findstr /i "Version"' ) do echo [%%a]
set FOUND_LNK4010=
for /f "delims=" %%a in ( '%IN_BEGIN% "%TRY_LINK_EXE%" /MACHINE:%VC_MACHINE% /SUBSYSTEM:WINDOWS^,%TRY_VER% ^| %FINDSTR% /i "LNK4010:"' ) do set FOUND_LNK4010=%%a
if "%FOUND_LNK4010%" == "" set DET_VC_SUBSYS_VER=%TRY_VER%
exit /b
REM endof Sub-routine
REM Sub-routine Func_PrintPathStr
REM Arg : const "%1" KEY
REM Arg : const "%2" VAL
:Func_PrintPathStr
setlocal
set KEY=%1
set VAL=%2
REM Strip sides quotes.
set KEY=%KEY:~1,-1%
set VAL=%VAL:~1,-1%
REM echo %KEY%=[%VAL%]
if "%VAL%" == "" echo %KEY% : {}
if "%VAL%" == "" goto Func_PrintPathStr_End
echo %KEY% : {
call :Func_PrintDelimitedStr "%VAL%" ";" " [" "]"
echo }
:Func_PrintPathStr_End
endlocal
exit /b
REM endof Sub-routine
REM Sub-routine Func_PrintDelimitedStr
REM Arg : const "%1" VAL
REM Arg : const "%2" DLM
REM Arg : const "%3" PFX
REM Arg : const "%4" SFX
:Func_PrintDelimitedStr
setlocal
set VAL=%1
set DLM=%2
set PFX=%3
set SFX=%4
REM Strip sides quotes.
set VAL=%VAL:~1,-1%
set DLM=%DLM:~1,-1%
set PFX=%PFX:~1,-1%
set SFX=%SFX:~1,-1%
REM
REM NOTE:
REM The variable expansions in IN(...) and DO(...) are performed separately,
REM so the value of LEFT is expanded to the latest one each time after the execution of DO(...), as expected.
REM
set LEFT=%VAL%
:Func_PrintDelimitedStr_Next
for /f "tokens=1,* delims=%DLM%" %%a in ( "%LEFT%" ) do (
echo %PFX%%%a%SFX%
set LEFT=%%b
)
if not "%LEFT%" == "" goto Func_PrintDelimitedStr_Next
endlocal
exit /b
REM endof Sub-routine
REM Sub-routine Func_Set
REM Arg : const "%1" KEY
REM Arg : const "%2" VAL
:Func_Set
setlocal
set KEY=%1
set VAL=%2
REM Strip sides quotes.
set KEY=%KEY:~1,-1%
set VAL=%VAL:~1,-1%
:Func_Set_End
endlocal&& set %KEY%=%VAL%
exit /b
REM endof Sub-routine
:End
@echo off
REM VC Directory
REM set ZNK_VC_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
REM set ZNK_VC_DIR=D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
REM set ZNK_VC_DIR=C:\MyVC\VC
REM set ZNK_VC_DIR=E:\share_e\trunk_id1\mt_redundant_dev\mt_compiler_ms\minvs\vs2017\BuildTools\VC
REM Windows SDK
REM set ZNK_VC_WINSDK_DIR=C:\Program Files (x86)
REM set ZNK_VC_WINSDK_DIR=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A
REM set ZNK_VC_WINSDK_DIR=D:\Program Files (x86)
REM set ZNK_VC_WINSDK_DIR=D:\Program Files (x86)\Windows Kits\8.1
REM set ZNK_VC_WINSDK_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WinSDK_v7
REM Windows Universal CRT SDK
REM set ZNK_VC_UCRT_DIR=C:\Program Files (x86)
REM set ZNK_VC_UCRT_DIR=D:\Program Files (x86)
REM set ZNK_VC_UCRT_DIR=D:\Program Files (x86)\Windows Kits\10
REM set ZNK_VC_UCRT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WindowsUniversalCRTSDK
ただ「Windows XPでも動作するような実行バイナリ」という条件ならば、普通は32bit版バイナリさえ作れればいいわけですから
(仮にそれをWindows XP Professional x64 Edition上に持っていっても動作しますから)、「とにかく5.01を指定する」と考えても
そう差し支えないとは思います。
これを指定しなかった場合(つまりデフォルトでは)6.00が指定されたものとみなされてしまいます。
これは Windows Vista 以降で動作するバイナリになります。
6.00 以上の SubsystemVersion の値は x86、x64ともに共通の値になっています。
例えば Windows Vista 以降で動作するバイナリを作りたい場合、x86版、x64版いずれのバイナリを作る場合でも6.00を指定すればよいです。
まあぶっちゃげそうなんですが、ただしVS2005の場合、Expressエディション(無料で手に入るエディション)では、x64向けのバイナリを作るためのコンパイラが含まれていません。
Windows SDKに含まれている場合があるので、それと組み合わせるなどといった工夫が必要になります
(ただし x64 向けのバイナリに限って言えば、いずれにせよSubsystemVersionの最小値は5.02(Windows XP Professional x64 Edition相当)にせざるを得ませんので、
VS2005である必要はないのですけども)。
5.01(Windows XP相当)が指定可能な最小値であり、またそれがデフォルトです。
このバージョンからはExpressエディションでもx64向けバイナリを生成できるlink.exeが付属します。
そちらについては5.02(Windows XP Professional x64 Edition相当)が指定可能な最小値であり、またそれがデフォルトです。
まあぶっちゃげそうなんですが、たとえそうだとしても実は油断できません。
それでも万全を期すなら、やはりlink.exeのオプション指定に 5.01 (Windows XP相当)あるいは5.02(Windows XP Professional x64 Edition相当)という値をハードコーディングすべきではありません。
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call detect_vc.bat
REM Making output directory automatically.
set OUT_DIR=.\out_dir\vc%MACHINE%
if not exist %OUT_DIR% mkdir %OUT_DIR%
REM Compile.
@echo on
cl -Fo%OUT_DIR%\test_hello.obj -c test_hello.c
@echo off
REM Link.
set VC_MACHINE=X86
if "%MACHINE%" == "x86" set VC_MACHINE=X86
if "%MACHINE%" == "x64" set VC_MACHINE=AMD64
set LINKER_OPT=/MACHINE:%VC_MACHINE% /SUBSYSTEM:CONSOLE,%DET_VC_SUBSYS_VER%
@echo on
link %LINKER_OPT% /OUT:%OUT_DIR%\test_hello.exe %OUT_DIR%\test_hello.obj
@echo off
pause
REM VC Directory
REM set ZNK_VC_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
REM set ZNK_VC_DIR=D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
REM set ZNK_VC_DIR=C:\MyVC\VC
set ZNK_VC_DIR=E:\share_e\trunk_id1\mt_redundant_dev\mt_compiler_ms\minvs\vs2017\BuildTools\VC
REM Windows SDK
REM set ZNK_VC_WINSDK_DIR=C:\Program Files (x86)
REM set ZNK_VC_WINSDK_DIR=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A
REM set ZNK_VC_WINSDK_DIR=D:\Program Files (x86)
REM set ZNK_VC_WINSDK_DIR=D:\Program Files (x86)\Windows Kits\8.1
set ZNK_VC_WINSDK_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WinSDK_v7
REM Windows Universal CRT SDK
REM set ZNK_VC_UCRT_DIR=C:\Program Files (x86)
REM set ZNK_VC_UCRT_DIR=D:\Program Files (x86)
REM set ZNK_VC_UCRT_DIR=D:\Program Files (x86)\Windows Kits\10
set ZNK_VC_UCRT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WindowsUniversalCRTSDK
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
call ..\detect_vc_config.bat
if exist "..\my_config.bat" call ..\my_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call ..\detect_vc.bat
if "%DET_VC_SUBSYS_VER%" == "" goto Error_DetectVC
REM Making output directory automatically.
set OUT_DIR=.\out_dir\vc%MACHINE%
if not exist %OUT_DIR% mkdir %OUT_DIR%
REM Compile.
@echo on
cl -Fo%OUT_DIR%\main.obj /c main.c
cl -Fo%OUT_DIR%\app1.obj /c app1.c
@echo off
REM Link.
set VC_MACHINE=X86
if "%MACHINE%" == "x86" set VC_MACHINE=X86
if "%MACHINE%" == "x64" set VC_MACHINE=AMD64
set LINKER_OPT=/MACHINE:%VC_MACHINE% /SUBSYSTEM:CONSOLE,%DET_VC_SUBSYS_VER%
@echo on
link %LINKER_OPT% /OUT:%OUT_DIR%\app1.exe %OUT_DIR%\main.obj %OUT_DIR%\app1.obj
@echo off
goto End
:Error_DetectVC
echo [NG]: Failed to execute DetectVC.
goto End
:End
pause
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
call ..\detect_vc_config.bat
if exist "..\my_config.bat" call ..\my_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call ..\detect_vc.bat
if "%DET_VC_SUBSYS_VER%" == "" goto Error_DetectVC
REM Making output directory automatically.
set OUT_DIR=.\out_dir\vc%MACHINE%
if not exist %OUT_DIR% mkdir %OUT_DIR%
REM Compile.
@echo on
cl -Fo%OUT_DIR%\util1.obj /c util1.c
cl -Fo%OUT_DIR%\util2.obj /c util2.c
@echo off
REM Make static-library.
@echo on
lib /OUT:%OUT_DIR%\util.lib %OUT_DIR%\util1.obj %OUT_DIR%\util2.obj
@echo off
goto End
:Error_DetectVC
echo [NG]: Failed to execute DetectVC.
goto End
:End
pause
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
call ..\detect_vc_config.bat
if exist "..\my_config.bat" call ..\my_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call ..\detect_vc.bat
if "%DET_VC_SUBSYS_VER%" == "" goto Error_DetectVC
REM Making output directory automatically.
set OUT_DIR=.\out_dir\vc%MACHINE%
if not exist %OUT_DIR% mkdir %OUT_DIR%
REM Compile.
@echo on
cl -Fo%OUT_DIR%\main.obj /c main.c
cl -Fo%OUT_DIR%\app2.obj /c app2.c
@echo off
REM Link.
set VC_MACHINE=X86
if "%MACHINE%" == "x86" set VC_MACHINE=X86
if "%MACHINE%" == "x64" set VC_MACHINE=AMD64
set LINKER_OPT=/MACHINE:%VC_MACHINE% /SUBSYSTEM:CONSOLE,%DET_VC_SUBSYS_VER%
@echo on
link %LINKER_OPT% /OUT:%OUT_DIR%\app2.exe %OUT_DIR%\main.obj %OUT_DIR%\app2.obj ..\util\%OUT_DIR%\util.lib
@echo off
goto End
:Error_DetectVC
echo [NG]: Failed to execute DetectVC.
goto End
:End
pause
# Source directory
S = .
!IF "$(MACHINE)" == "x64"
VC_MACHINE=AMD64
PLATFORM=win64
!ELSE
MACHINE=x86
VC_MACHINE=X86
PLATFORM=win32
!ENDIF
# Output directory
ABINAME=vc$(MACHINE)$(DEBUG)
O = .\out_dir\$(ABINAME)
#
# In VS2012(VC11) or later, if you want to generate XP-compatible EXE/DLL, you need to specify the subsystem-version (5.01/5.02)
# explicitly in LINK /SUBSYSTEM: option. For example, LINK /SUBSYSTEM:WINDOWS,5.01 etc.
# This is because the subsystem-version is set to 6.00 (target OS is Vista or later) by default in VC11 or later.
#
# Note that the version specified in the /SUBSYSTEM option of LINK has a different minimum value for each compiler.
# For VC2005 and earlier, the minimum value is 4.00 (target OS is Windows95 or later).
# For VS2008 (VC9) and VS2010 (VC10), the minimum value is 5.00 (target OS is Windows2000 or later).
# For VC2012 or later, the minimum value is 5.01/5.02 (target OS is WindowsXP x86 / Windows XP x64, Windows Server 2003 or later).
#
# If you specify a value that is less than the minimum, LINK will output an error LNK4010,
# so you can automatically get the minimum version value that should be specified by detecting that string.
# The detect_vc.bat (by Zenkaku@znk_project) will automatically retrieve it and set the result to the environment variable DET_VC_SUBSYS_VER.
#
LINKER_OPT_SUBSYSTEM=/SUBSYSTEM:CONSOLE,$(DET_VC_SUBSYS_VER)
!IF "$(DEBUG)" == "d"
COMPILER=cl -nologo -EHsc /GR /W4 /MTd /Z7 /D_DEBUG /RTC1
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM) /DEBUG /INCREMENTAL:NO
!ELSE
COMPILER=cl -nologo -EHsc /GR /W4 /MT /O2 /DNDEBUG
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM)
!ENDIF
INCLUDE_FLAG = \
EXE_FILE0=$O\app1.exe
OBJS0=\
$O\app1.obj \
$O\main.obj \
LIBS0=\
# Entry rule.
all: all_at_first $O $(EXE_FILE0)
# Init.
all_at_first:
# Mkdir rule.
$O:
if not exist $O mkdir $O
# Product files rule.
$(EXE_FILE0): $(OBJS0)
$(LINKER) /OUT:$(EXE_FILE0) $(OBJS0) $(LIBS0)
# Suffix rule.
{$S}.c{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
{$S}.cpp{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
# Clean rule.
clean:
rmdir /S /Q $O\
# Source directory
S = .
!IF "$(MACHINE)" == "x64"
VC_MACHINE=AMD64
PLATFORM=win64
!ELSE
MACHINE=x86
VC_MACHINE=X86
PLATFORM=win32
!ENDIF
# Output directory
ABINAME=vc$(MACHINE)$(DEBUG)
O = .\out_dir\$(ABINAME)
#
# In VS2012(VC11) or later, if you want to generate XP-compatible EXE/DLL, you need to specify the subsystem-version (5.01/5.02)
# explicitly in LINK /SUBSYSTEM: option. For example, LINK /SUBSYSTEM:WINDOWS,5.01 etc.
# This is because the subsystem-version is set to 6.00 (target OS is Vista or later) by default in VC11 or later.
#
# Note that the version specified in the /SUBSYSTEM option of LINK has a different minimum value for each compiler.
# For VC2005 and earlier, the minimum value is 4.00 (target OS is Windows95 or later).
# For VS2008 (VC9) and VS2010 (VC10), the minimum value is 5.00 (target OS is Windows2000 or later).
# For VC2012 or later, the minimum value is 5.01/5.02 (target OS is WindowsXP x86 / Windows XP x64, Windows Server 2003 or later).
#
# If you specify a value that is less than the minimum, LINK will output an error LNK4010,
# so you can automatically get the minimum version value that should be specified by detecting that string.
# The detect_vc.bat (by Zenkaku@znk_project) will automatically retrieve it and set the result to the environment variable DET_VC_SUBSYS_VER.
#
LINKER_OPT_SUBSYSTEM=/SUBSYSTEM:CONSOLE,$(DET_VC_SUBSYS_VER)
!IF "$(DEBUG)" == "d"
COMPILER=cl -nologo -EHsc /GR /W4 /MTd /Z7 /D_DEBUG /RTC1
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM) /DEBUG /INCREMENTAL:NO
!ELSE
COMPILER=cl -nologo -EHsc /GR /W4 /MT /O2 /DNDEBUG
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM)
!ENDIF
INCLUDE_FLAG = \
SLIB_FILE0=$O\util.lib
OBJS0=\
$O\util1.obj \
$O\util2.obj \
LIBS0=\
# Entry rule.
all: all_at_first $O $(SLIB_FILE0)
# Init.
all_at_first:
# Mkdir rule.
$O:
if not exist $O mkdir $O
# Product files rule.
$(SLIB_FILE0): $(OBJS0)
LIB /NOLOGO /OUT:$(SLIB_FILE0) $(OBJS0) $(SUB_LIBS)
# Suffix rule.
{$S}.c{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
{$S}.cpp{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
# Clean rule.
clean:
rmdir /S /Q $O\
# Source directory
S = .
!IF "$(MACHINE)" == "x64"
VC_MACHINE=AMD64
PLATFORM=win64
!ELSE
MACHINE=x86
VC_MACHINE=X86
PLATFORM=win32
!ENDIF
# Output directory
ABINAME=vc$(MACHINE)$(DEBUG)
O = .\out_dir\$(ABINAME)
#
# In VS2012(VC11) or later, if you want to generate XP-compatible EXE/DLL, you need to specify the subsystem-version (5.01/5.02)
# explicitly in LINK /SUBSYSTEM: option. For example, LINK /SUBSYSTEM:WINDOWS,5.01 etc.
# This is because the subsystem-version is set to 6.00 (target OS is Vista or later) by default in VC11 or later.
#
# Note that the version specified in the /SUBSYSTEM option of LINK has a different minimum value for each compiler.
# For VC2005 and earlier, the minimum value is 4.00 (target OS is Windows95 or later).
# For VS2008 (VC9) and VS2010 (VC10), the minimum value is 5.00 (target OS is Windows2000 or later).
# For VC2012 or later, the minimum value is 5.01/5.02 (target OS is WindowsXP x86 / Windows XP x64, Windows Server 2003 or later).
#
# If you specify a value that is less than the minimum, LINK will output an error LNK4010,
# so you can automatically get the minimum version value that should be specified by detecting that string.
# The detect_vc.bat (by Zenkaku@znk_project) will automatically retrieve it and set the result to the environment variable DET_VC_SUBSYS_VER.
#
LINKER_OPT_SUBSYSTEM=/SUBSYSTEM:CONSOLE,$(DET_VC_SUBSYS_VER)
!IF "$(DEBUG)" == "d"
COMPILER=cl -nologo -EHsc /GR /W4 /MTd /Z7 /D_DEBUG /RTC1
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM) /DEBUG /INCREMENTAL:NO
!ELSE
COMPILER=cl -nologo -EHsc /GR /W4 /MT /O2 /DNDEBUG
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM)
!ENDIF
INCLUDE_FLAG = \
-I..\util \
EXE_FILE0=$O\app2.exe
OBJS0=\
$O\app2.obj \
$O\main.obj \
LIBS0=\
..\util\$O\util.lib \
# Entry rule.
all: all_at_first $O $(EXE_FILE0)
# Init.
all_at_first:
# Mkdir rule.
$O:
if not exist $O mkdir $O
# Product files rule.
$(EXE_FILE0): $(OBJS0)
$(LINKER) /OUT:$(EXE_FILE0) $(OBJS0) $(LIBS0)
# Suffix rule.
{$S}.c{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
{$S}.cpp{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
# Clean rule.
clean:
rmdir /S /Q $O\
今は昔(いや今もかもしれまんが)、X-Window System(ゴメンなさい、UNIXの話です)に含まれていたMakefileでは、
make world というコマンドですべてがコンパイル、リンクできました。
make_world.bat という名前はそこから拝借しております。
それでは make_world.bat の中身を見てみます。
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call detect_vc.bat
if "%DET_VC_SUBSYS_VER%" == "" goto Error_DetectVC
set MAK_TGT=
call make_one.bat app1 %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
call make_one.bat util %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
call make_one.bat app2 %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
echo [OK]: The make_world is done successfully.
goto End
:Error_DetectVC
echo [NG]: Failed to execute DetectVC.
goto End
:Error_Make
echo [NG]: Failed to execute nmake.
goto End
:End
pause
@echo off
set DST_DIR=%1
set MAK_TGT=%2
set SAFE_CD=cd /d
echo ======
echo === Entering [%DST_DIR%] ===
set BAK_DIR=%CD%
%SAFE_CD% %DST_DIR%
REM REM Only when the one before && succeeds, the one after && will be executed.
set IS_ERROR=yes
nmake -f Makefile_vc.mak %MAK_TGT%&& set IS_ERROR=
%SAFE_CD% %BAK_DIR%
echo === Leaving [%DST_DIR%] ===
echo ======
echo:
環境変数errorlevelを使う上で一点注意して頂きたいのは、ここで言う「直前」とは「本当に直前」ということです。
例えば、以下のような記述の場合、errorlevel は「nmake -f Makefile_vc.mak」ではなく「echo ==== End of Makefile_vc.make ====」
の戻り値が格納されます。
echo ==== Begin of %DST_DIR%\Makefile_vc.make ====
nmake -f Makefile_vc.mak
echo ==== End of %DST_DIR%\Makefile_vc.make ====
if "%errorlevel%" == "1" goto Error
@echo off
REM x86 or x64.
REM x86 : Build x86 binary (for 32bit/64bit Windows)
REM x64 : Build x64 binary (for 64bit Windows only)
set MACHINE=x86
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary %MACHINE%.
call detect_vc.bat
if "%DET_VC_SUBSYS_VER%" == "" goto Error_DetectVC
set MAK_TGT=clean
call make_one.bat app1 %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
call make_one.bat util %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
call make_one.bat app2 %MAK_TGT%& if "%IS_ERROR%" == "yes" goto Error_Make
echo [OK]: The make_world is done successfully.
goto End
:Error_DetectVC
echo [NG]: Failed to execute DetectVC.
goto End
:Error_Make
echo [NG]: Failed to execute nmake.
goto End
:End
pause
@echo off
REM Call pseudo-subroutine MyFunc
call :MyFunc
REM This goto statement is necessary to go through the part that defines the subroutine.
goto End
:MyFunc
REM Contents of subroutine MyFunc.
echo This is MyFunc internal.
REM Return to caller.
exit /b
:End
pause
@echo off
set MY_INCLUDE=
set MY_LIB=
setlocal
set MY_INCLUDE=C:\Compiler\include
set MY_LIB=C:\Compiler\lib
REM export MY_INCLUDE, MY_LIB
endlocal& set MY_INCLUDE=%MY_INCLUDE%& set MY_LIB=%MY_LIB%
echo MY_INCLUDE=[%MY_INCLUDE%]
echo MY_LIB =[%MY_LIB%]
pause
endlocal ^
& set DET_VC_SUBSYS_VER=%DET_VC_SUBSYS_VER% ^
& set PATH=%PATH% ^
& set INCLUDE=%INCLUDE% ^
& set LIB=%LIB%
以下のような set コマンドのラッパーとなるサブルーチンを作り、set コマンドを見かけ上隠してしまえば、
一応上で挙げた問題にすべて対応することはできます。
REM Sub-routine Func_Set
REM Arg : const "%1" KEY
REM Arg : const "%2" VAL
:Func_Set
setlocal
set KEY=%1
set VAL=%2
REM Strip sides quotes.
set KEY=%KEY:~1,-1%
set VAL=%VAL:~1,-1%
:Func_Set_End
endlocal&& set %KEY%=%VAL%
exit /b
REM endof Sub-routine
このとき同時に do 後方のコマンドも実行されます。
つまり、列挙された文字列からこれらの文字列を一つ取り出しては、do 後方のコマンドを実行。
その繰り返しを列挙された文字列すべてに対して行います
(その他のプログラミング言語でforeach文というのをご存知の方は、まさにあの挙動です)。
ここで重要なことは do 後方のコマンドに特殊変数 %%a の値を埋め込めることです。
今回の例ではおそらく列挙された文字列は一つしかないので、特に繰り返し処理をする意味はないのですが、
この「do 後方のコマンドに%%aを埋め込める」という特性のためだけにfor文に協力してもらったというわけです。
では最後に完全なコードを示しましょう。
おそらくもう読めるはずです。
REM The following scan is intended to find, for example, VC_DIR\redist\x86\Microsoft.VC*.CRT (for VS2013/VS2015)
set TRY_DIR=%VC_DIR%\redist\x86
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| findstr /i "Microsoft\.VC.*\.CRT"' ) do if exist "%TRY_DIR%\%%a\*.dll" set MY_BIN=%MY_BIN%;%TRY_DIR%\%%a
かなり横に長いですがご了承ください。
この処理ではまず TRY_DIR に %VC_DIR%\redist\x86 を格納し、そのパスが存在するか否かを調べています。
存在する場合、次に %TRY_DIR%( =%VC_DIR%\redist\x86 ) 内を dir /b でリストアップし、"Microsoft\.VC.*\.CRT" にマッチするパターンのみを抽出します。
(これにマッチするのはおそらく一つですが)それをfor文の特殊変数 %%a へ格納します。
このとき同時に do の後方にある「if exist "%TRY_DIR%\%%a\*.dll" set MY_BIN=%MY_BIN%;%TRY_DIR%\%%a」も実行されます。
%TRY_DIR%\%%a 内に確かになんらかのdllが存在するならば、環境変数MY_BINに新たなパス %TRY_DIR%\%%a を追加します。
存在しないならば追加しません。
レベル1の例では in ( '...' ) 内で最初に実行したコマンドは「dir /b」と固定のものでしたが、もっと一般にそれ以外のコマンドを自由に指定できないでしょうか?
さらに環境変数でそのコマンドを動的に与えたいとします。
ですがそのためには色々と注意事項があり、起こり得る様々な問題を回避するため以下のようにする必要があります。
@echo off
set IN_BEGIN=if x^^=^^=x
set CMD=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\link.exe
for /f "delims=" %%a in ( '%IN_BEGIN% "%CMD%" ^| findstr /i "Version"' ) do echo [%%a]
この例では「C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\link.exe」を環境変数CMDにセットし、それを実行コマンドとして最初に与えています。
ですがそれより前の位置に%IN_BEGIN%が埋め込まれており、その具体的な値は「if x^^=^^=x」という謎の固定文字列です。
これを必ず in ( '...' ) 内の先頭に付加するようにしてください。
なぜこんなものを指定するのかその理由に興味がある方は、説明は大変長くなりますが以下の「in ( '...' ) の中身に関する分析」をご覧ください。
C:\Zenkaku>
C:\Zenkaku>bill_gates.bat
[Microsoft (R) Incremental Linker Version 8.00.50727.42]
[Copyright (C) Microsoft Corporation. All rights reserved.]
...
C:\Zenkaku>
@echo off
for /f "delims=" %%a in ( 'if x^=^=x "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\link.exe" ^| findstr /i "Version"' ) do echo [%%a]
C:\Zenkaku>
C:\Zenkaku>bill_gates.bat
[Microsoft (R) Incremental Linker Version 8.00.50727.42]
[ /VERSION:#[.#]]
少しだけ可読性についても検討しましょう。
毎回「if x^=^=x 」のように書くのも間違いの元ですので、例えば以下のように分かりやすい名前の変数に入れておきます。
また実行するコマンド本体も in ( '...' ) 内に直接書くと見づらいですので変数に格納した上で指定することにします。
@echo off
set IN_BEGIN=if x^^=^^=x
set CMD=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\link.exe
for /f "delims=" %%a in ( '%IN_BEGIN% "%CMD%" ^| findstr /i "Version"' ) do echo [%%a]
set IN_BEGIN=if x^^=^^=x
set CMD=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\nmake.exe
for /f "delims=" %%a in ( '%IN_BEGIN% "%CMD%" 2^>^&1 ^| findstr /i "Version"' ) do echo [%%a]
@echo off
set IN_BEGIN=if x^^=^^=x
set IN_REDIRECT_2TO1=2^^^>^^^&1
set CMD=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\nmake.exe
for /f "delims=" %%a in ( '%IN_BEGIN% "%CMD%" %IN_REDIRECT_2TO1% ^| findstr /i "Version"' ) do echo [%%a]
@echo off
REM Simple VC Include or Lib detection.
REM Target OS binary type (x86 or x64).
if %MACHINE% == "" set MACHINE=x86
if not "%ProgramFiles(x86)%" == "" set PROGRAM_FILE_X86_DIR=%ProgramFiles(x86)%& goto ProgramFilesAutoSet_End
if not "%ProgramFiles%" == "" set PROGRAM_FILE_X86_DIR=%ProgramFiles%& goto ProgramFilesAutoSet_End
set PROGRAM_FILE_X86_DIR=C:\Program Files& goto ProgramFilesAutoSet_End
:ProgramFilesAutoSet_End
REM Default (for VS2017)
set VC_SDK_ROOT_DIR=%PROGRAM_FILE_X86_DIR%
set VC_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.16.27023
set VC_UCRT_DIR=%PROGRAM_FILE_X86_DIR%\Windows Kits\10
set VC_UCRT_STRICT_VER=10.0.10240.0
REM Custom directory
REM set VC_SDK_ROOT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WinSDK_v7
REM set VC_DIR=E:\share_e\trunk_id1\mt_redundant_dev\mt_compiler_ms\minvs\vs2017\BuildTools\VC\Tools\MSVC\14.16.27023
REM set VC_UCRT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WindowsUniversalCRTSDK\Windows Kits\10
REM set VC_UCRT_STRICT_VER=10.0.10240.0
set INCLUDE=
set LIB=
if "%PATH%" == "" set PATH=%windir%\System32;%windir%
echo MACHINE=[%MACHINE%]
echo:
echo Scan Windows SDK 6.0 earlier:
setlocal
set WINSDK_DIR=%VC_SDK_ROOT_DIR%\Microsoft SDKs\Windows\v6.0
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "" "windows.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "" "%MACHINE%" "user32.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_FindLib "%WINSDK_DIR%" "" "%MACHINE%" "msdelta.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan Windows SDK 7.1:
setlocal
set WINSDK_DIR=%VC_SDK_ROOT_DIR%\Microsoft SDKs\Windows\v7.1
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "" "windows.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "" "%MACHINE%" "user32.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan Windows SDK 8.1:
setlocal
set WINSDK_DIR=%VC_SDK_ROOT_DIR%\Windows Kits\8.1
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "um" "windows.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
call :Func_FindInclude "%WINSDK_DIR%" "shared" "winapifamily.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "winv6.3\um" "%MACHINE%" "user32.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan Windows SDK 10:
setlocal
set WINSDK_DIR=%VC_SDK_ROOT_DIR%\Windows Kits\10
set STRICT_VER=%VC_UCRT_STRICT_VER%
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "%STRICT_VER%\um" "windows.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
call :Func_FindInclude "%WINSDK_DIR%" "%STRICT_VER%\shared" "winapifamily.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "%STRICT_VER%\um" "%MACHINE%" "user32.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan Windows Universal CRT SDK:
setlocal
set WINSDK_DIR=%VC_UCRT_DIR%
set STRICT_VER=%VC_UCRT_STRICT_VER%
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "%STRICT_VER%\ucrt" "stdio.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "%STRICT_VER%\ucrt" "%MACHINE%" "libucrt.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan C-Standard Library in VC-Compiler:
setlocal
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%VC_DIR%" "" "vector"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%VC_DIR%" "" "%MACHINE%" "libcmt.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
echo Scan VC-Compiler BinDir:
setlocal
set MY_BIN=
REM Scan bin for exe
call :Func_FindBin "%VC_DIR%" "%MACHINE%" "cl.exe"
if not "%ANS_DIR%" == "" set MY_BIN=%MY_BIN%;%ANS_DIR%
REM Scan bin for dll in "x86" that x86_amd64 depends on.
call :Func_FindBin "%VC_DIR%" "x86" "cl.exe"
if not "%ANS_DIR%" == "" set MY_BIN=%MY_BIN%;%ANS_DIR%
REM Scan Common7\IDE for dll that old vc depends on.
if exist "%VC_DIR%\..\Common7\IDE" set MY_BIN=%MY_BIN%;%VC_DIR%\..\Common7\IDE
REM The following scan is intended to find, for example, VC_DIR\redist\x86\Microsoft.VC*.CRT (for VS2013/VS2015)
set TRY_DIR=%VC_DIR%\redist\x86
if exist "%TRY_DIR%" for /f "delims=" %%a in ( 'dir /b "%TRY_DIR%" ^| findstr /i "Microsoft\.VC.*\.CRT"' ) do if exist "%TRY_DIR%\%%a\*.dll" set MY_BIN=%MY_BIN%;%TRY_DIR%\%%a
call :Func_Update_Path
REM export PATH
endlocal& set PATH=%PATH%
echo:
echo Final Total Result:
echo:
echo PATH=[%PATH%]
echo:
echo INCLUDE=[%INCLUDE%]
echo:
echo LIB=[%LIB%]
echo:
goto End
REM Sub-routine Func_FindInclude
REM Arg : "%1" TRY_DIR
REM Arg : "%2" TRY_SUB_DIR
REM Arg : "%3" LANDMARK_HDR
REM Return : ANS_DIR
REM
:Func_FindInclude
setlocal
set ANS_DIR=
REM Quoted parameters.
set TRY_DIR=%1
set TRY_SUB_DIR=%2
set LANDMARK_HDR=%3
REM Strip sides quotes.
set TRY_DIR=%TRY_DIR:~1,-1%
set TRY_SUB_DIR=%TRY_SUB_DIR:~1,-1%
set LANDMARK_HDR=%LANDMARK_HDR:~1,-1%
set TRY_DIR_SAVE=%TRY_DIR%
set TRY_DIR=%TRY_DIR_SAVE%
if not "%TRY_SUB_DIR%" == "" goto Func_FindInclude_WithSubDir
REM Check include
if exist "%TRY_DIR%\include\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include
goto Func_FindInclude_WithSubDir_End
:Func_FindInclude_WithSubDir
REM Check include\TRY_SUB_DIR
if exist "%TRY_DIR%\include\%TRY_SUB_DIR%\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include\%TRY_SUB_DIR%
:Func_FindInclude_WithSubDir_End
:Func_FindInclude_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindLib
REM Arg : "%1" TRY_DIR
REM Arg : "%2" TRY_SUB_DIR
REM Arg : "%3" TRY_MACHINE (x86 or x64)
REM Arg : "%4" LANDMARK_LIB
REM Return : ANS_DIR
REM
:Func_FindLib
setlocal
set ANS_DIR=
REM Quoted parameters.
set TRY_DIR=%1
set TRY_SUB_DIR=%2
set TRY_MACHINE=%3
set LANDMARK_LIB=%4
REM Strip sides quotes.
set TRY_DIR=%TRY_DIR:~1,-1%
set TRY_SUB_DIR=%TRY_SUB_DIR:~1,-1%
set TRY_MACHINE=%TRY_MACHINE:~1,-1%
set LANDMARK_LIB=%LANDMARK_LIB:~1,-1%
set TRY_DIR_SAVE=%TRY_DIR%
REM For Windows SDK 7.1 or 6.0 or 5.2.
REM In case x86
REM Check lib or lib\x86
REM In case x64
REM Check lib\x64
REM
set TRY_DIR=%TRY_DIR_SAVE%
if "%TRY_MACHINE%" == "x64" goto Func_FindLib_x64
REM In case x86
if exist "%TRY_DIR%\lib\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib
if exist "%TRY_DIR%\lib\x86\%LANDMARK_LIB%" set ANS_DIR=%ANS_DIR%;%TRY_DIR%\lib\x86
goto Func_FindLib_x64_End
:Func_FindLib_x64
REM In case x64
if exist "%TRY_DIR%\lib\x64\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib\x64
:Func_FindLib_x64_End
REM If the ANS has been obtained, return to the caller.
if not "%ANS_DIR%" == "" goto Func_FindLib_End
REM For Windows SDK 8.1 or lator
REM Check lib\TRY_SUB_DIR\TRY_MACHINE
REM
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\lib\%TRY_SUB_DIR%\%TRY_MACHINE%\%LANDMARK_LIB%" set ANS_DIR=%TRY_DIR%\lib\%TRY_SUB_DIR%\%TRY_MACHINE%
REM If the ANS has been obtained, return to the caller.
if not "%ANS_DIR%" == "" goto Func_FindLib_End
:Func_FindLib_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_FindBin
REM Arg : "%1" TRY_DIR
REM Arg : "%2" TRY_MACHINE (x86 or x64)
REM Arg : "%3" LANDMARK_EXE
REM Return : ANS_DIR
REM
:Func_FindBin
setlocal
set ANS_DIR=
REM Quoted parameters.
set TRY_DIR=%1
set TRY_MACHINE=%2
set LANDMARK_LIB=%3
REM Strip sides quotes.
set TRY_DIR=%TRY_DIR:~1,-1%
set TRY_MACHINE=%TRY_MACHINE:~1,-1%
set LANDMARK_LIB=%LANDMARK_LIB:~1,-1%
set TRY_DIR_SAVE=%TRY_DIR%
if "%TRY_MACHINE%" == "x64" goto Func_FindBin_x64
REM x86
REM for VC2017
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\Hostx86\x86\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\Hostx86\x86
if not "%ANS_DIR%" == "" goto Func_FindBin_End
REM for VC10, VC11
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin
if not "%ANS_DIR%" == "" goto Func_FindBin_End
goto Func_FindBin_x64_End
:Func_FindBin_x64
REM x64
REM for VC2017
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\Hostx86\x64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\Hostx86\x64
if not "%ANS_DIR%" == "" goto Func_FindBin_End
REM for VC10, VC11
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\x86_amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\x86_amd64
if not "%ANS_DIR%" == "" goto Func_FindBin_End
REM Alternatively, we use Native compiler (not Cross-compiler) (in old VC)
set TRY_DIR=%TRY_DIR_SAVE%
if exist "%TRY_DIR%\bin\amd64\%LANDMARK_EXE%" set ANS_DIR=%TRY_DIR%\bin\amd64
if not "%ANS_DIR%" == "" goto Func_FindBin_End
:Func_FindBin_x64_End
:Func_FindBin_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
REM Sub-routine Func_Update_Include_and_Lib
REM
:Func_Update_Include_and_Lib
echo Result:
echo MY_INCLUDE=[%MY_INCLUDE%]
echo MY_LIB =[%MY_LIB%]
echo:
REM update INCLUDE, LIB
if not "%MY_INCLUDE%" == "" set INCLUDE=%INCLUDE%;%MY_INCLUDE%
if not "%MY_LIB%" == "" set LIB=%LIB%;%MY_LIB%
exit /b
REM endof Sub-routine
REM Sub-routine Func_Update_Path
REM
:Func_Update_Path
echo Result:
echo MY_BIN =[%MY_BIN%]
echo:
REM update PATH
if not "%MY_BIN%" == "" set PATH=%PATH%;%MY_BIN%
exit /b
REM endof Sub-routine
:End
REM test.
REM cl.exe test.c
REM link.exe
pause
REM Custom directory
REM set VC_SDK_ROOT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WinSDK_v7
REM set VC_DIR=E:\share_e\trunk_id1\mt_redundant_dev\mt_compiler_ms\minvs\vs2017\BuildTools\VC\Tools\MSVC\14.16.27023
REM set VC_UCRT_DIR=E:\share_e\trunk_id1\mt_redundant_dev\ms_devs\WindowsUniversalCRTSDK\Windows Kits\10
REM set VC_UCRT_STRICT_VER=10.0.10240.0
setlocal
if not "%VC_DIR%" == "" goto VCDirAutoSet_End
REM VS2015(VC14)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 14.0\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2013(VC12)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 12.0\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2012(VC11)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 11.0\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2010(VC10)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 10.0\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2008(VC9)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 9.0\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2005(VC8)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio 8\VC
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS2003(VC7.1)
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio .NET 2003\Vc7
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
REM VS6.0
set TRY_DIR=%PROGRAM_FILE_X86_DIR%\Microsoft Visual Studio\VC98
if exist "%TRY_DIR%" set VC_DIR=%TRY_DIR%& goto VCDirAutoSet_End
:VCDirAutoSet_End
REM export VC_DIR
endlocal& set VC_DIR=%VC_DIR%
VC_UCRT_DIR
VS2015以降のVC(VC14)を使用される場合はこの指定が必要となります。
Windows Universal CRT SDKのトップディレクトリのパスを与えます。
これは、include、lib が直下に存在するディレクトリです。
さらにinclude\%VC_UCRT_STRICT_VER%\ucrtの配下stdio.hなどのC標準ライブラリのヘッダ、
lib\%VC_UCRT_STRICT_VER%\ucrtの配下にlibucrt.libが存在していなければなりません。
VC_UCRT_STRICT_VER
VS2015以降のVC(VC14)を使用される場合はこの指定が必要となります。
Windows Universal CRT SDKの厳密なバージョン番号です。
なぜこれを指定する必要があるかといえば、includeパス、libパスにこれを名前とするディレクトリが含まれるからです。
デフォルトではC:\Program Files (x86)\Windows Kits\10\includeなどを開くと現れるディレクトリの名前です。
echo Scan Windows SDK 7.1:
setlocal
set WINSDK_DIR=%VC_SDK_ROOT_DIR%\Microsoft SDKs\Windows\v7.1
set MY_INCLUDE=
set MY_LIB=
REM Scan include
call :Func_FindInclude "%WINSDK_DIR%" "" "windows.h"
if not "%ANS_DIR%" == "" set MY_INCLUDE=%MY_INCLUDE%;%ANS_DIR%
REM Scan lib
call :Func_FindLib "%WINSDK_DIR%" "" "%MACHINE%" "user32.lib"
if not "%ANS_DIR%" == "" set MY_LIB=%MY_LIB%;%ANS_DIR%
call :Func_Update_Include_and_Lib
REM export INCLUDE and LIB
endlocal& set INCLUDE=%INCLUDE%& set LIB=%LIB%
REM Sub-routine Func_FindInclude
REM Arg : "%1" TRY_DIR
REM Arg : "%2" TRY_SUB_DIR
REM Arg : "%3" LANDMARK_HDR
REM Return : ANS_DIR
REM
:Func_FindInclude
setlocal
set ANS_DIR=
REM Quoted parameters.
set TRY_DIR=%1
set TRY_SUB_DIR=%2
set LANDMARK_HDR=%3
REM Strip sides quotes.
set TRY_DIR=%TRY_DIR:~1,-1%
set TRY_SUB_DIR=%TRY_SUB_DIR:~1,-1%
set LANDMARK_HDR=%LANDMARK_HDR:~1,-1%
set TRY_DIR_SAVE=%TRY_DIR%
set TRY_DIR=%TRY_DIR_SAVE%
if not "%TRY_SUB_DIR%" == "" goto Func_FindInclude_WithSubDir
REM Check include
if exist "%TRY_DIR%\include\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include
goto Func_FindInclude_WithSubDir_End
:Func_FindInclude_WithSubDir
REM Check include\TRY_SUB_DIR
if exist "%TRY_DIR%\include\%TRY_SUB_DIR%\%LANDMARK_HDR%" set ANS_DIR=%TRY_DIR%\include\%TRY_SUB_DIR%
:Func_FindInclude_WithSubDir_End
:Func_FindInclude_End
endlocal& set ANS_DIR=%ANS_DIR%
exit /b
REM endof Sub-routine
# Source directory
S = .
!IF "$(MACHINE)" == "x64"
VC_MACHINE=AMD64
PLATFORM=win64
!ELSE
MACHINE=x86
VC_MACHINE=X86
PLATFORM=win32
!ENDIF
# Output directory
ABINAME=vc$(MACHINE)$(DEBUG)
O = .\out_dir\$(ABINAME)
#
# In VS2012(VC11) or later, if you want to generate XP-compatible EXE/DLL, you need to specify the subsystem-version (5.01/5.02)
# explicitly in LINK /SUBSYSTEM: option. For example, LINK /SUBSYSTEM:WINDOWS,5.01 etc.
# This is because the subsystem-version is set to 6.00 (target OS is Vista or later) by default in VC11 or later.
#
# Note that the version specified in the /SUBSYSTEM option of LINK has a different minimum value for each compiler.
# For VC2005 and earlier, the minimum value is 4.00 (target OS is Windows95 or later).
# For VS2008 (VC9) and VS2010 (VC10), the minimum value is 5.00 (target OS is Windows2000 or later).
# For VC2012 or later, the minimum value is 5.01/5.02 (target OS is WindowsXP x86 / Windows XP x64, Windows Server 2003 or later).
#
# If you specify a value that is less than the minimum, LINK will output an error LNK4010,
# so you can automatically get the minimum version value that should be specified by detecting that string.
# The detect_vc.bat (by Zenkaku@znk_project) will automatically retrieve it and set the result to the environment variable DET_VC_SUBSYS_VER.
#
LINKER_OPT_SUBSYSTEM=/SUBSYSTEM:CONSOLE,$(DET_VC_SUBSYS_VER)
!IF "$(DEBUG)" == "d"
COMPILER=cl -nologo -EHsc /GR /W4 /MTd /Z7 /D_DEBUG /RTC1
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM) /DEBUG /INCREMENTAL:NO
!ELSE
COMPILER=cl -nologo -EHsc /GR /W4 /MT /O2 /DNDEBUG
LINKER=link /MACHINE:$(VC_MACHINE) $(LINKER_OPT_SUBSYSTEM)
!ENDIF
INCLUDE_FLAG = \
INSTALL_DIR=out_dir\test_install
EXE_FILE0=$O\test_hello.exe
OBJS0=\
$O\test_hello.obj \
ILIBS0=\
EXE_FILE1=$O\test_ws.exe
OBJS1=\
$O\test_ws.obj \
ILIBS1=\
user32.lib \
ws2_32.lib \
EXE_FILE2=$O\test_stl.exe
OBJS2=\
$O\test_stl.obj \
ILIBS2=\
EXE_FILE3=$O\test_dbg.exe
OBJS3=\
$O\test_dbg.obj \
ILIBS3=\
# Entry rule.
all: all_at_first $O $(EXE_FILE0) $(EXE_FILE1) $(EXE_FILE2) $(EXE_FILE3)
# Init.
all_at_first:
test_hello: all_at_first $O $(EXE_FILE0)
test_ws: all_at_first $O $(EXE_FILE1)
test_stl: all_at_first $O $(EXE_FILE2)
test_dgb: all_at_first $O $(EXE_FILE3)
# Mkdir rule.
$O:
if not exist $O mkdir $O
# Product files rule.
$(EXE_FILE0): $(OBJS0)
$(LINKER) /OUT:$(EXE_FILE0) $(OBJS0) $(ILIBS0)
$(EXE_FILE1): $(OBJS1)
$(LINKER) /OUT:$(EXE_FILE1) $(OBJS1) $(ILIBS1)
$(EXE_FILE2): $(OBJS2)
$(LINKER) /OUT:$(EXE_FILE2) $(OBJS2) $(ILIBS2)
$(EXE_FILE3): $(OBJS3)
$(LINKER) /OUT:$(EXE_FILE3) $(OBJS3) $(ILIBS3)
# Suffix rule.
{$S}.c{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
{$S}.cpp{$O}.obj:
$(COMPILER) -I$S $(INCLUDE_FLAG) -Fo$@ -c $<
# Clean rule.
clean:
rmdir /S /Q $O\
@echo off
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
set MAK_TGT=test_hello
REM Build x86 binary (for 32bit/64bit Windows)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x86.
set MACHINE=x86
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
REM Build x64 binary (for 64bit Windows only)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x64.
set MACHINE=x64
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
#include <stdio.h>
#include <stdlib.h>
/***
* pragma warning(push) stores the current warning state for every warning.
*/
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4005)
#endif
#define WIN32_LEAN_AND_MEAN
/***
* NOTE: windows.h should be included after winsock2.h
*/
#include <winsock2.h>
#include <windows.h>
/***
* pragma warning(pop) pops the last warning state pushed onto the stack.
* Any changes that you made to the warning state between push and pop are undone.
*/
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
int main( void )
{
WSADATA wsaData;
printf( "Hello sizeof(void*)=[%u]\n", (unsigned int)sizeof(void*) );
if( WSAStartup(MAKEWORD(2,0), &wsaData) != 0 ){
printf( "[NG]: WSAStartup : failure.\n" );
return EXIT_FAILURE;
}
MessageBoxA( NULL, "Hello user32.lib and ws2_32.lib !", "MBCS", MB_OK );
WSACleanup();
return EXIT_SUCCESS;
}
@echo off
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
set MAK_TGT=test_ws
REM Build x86 binary (for 32bit/64bit Windows)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x86.
set MACHINE=x86
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
REM Build x64 binary (for 64bit Windows only)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x64.
set MACHINE=x64
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
@echo off
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
set MAK_TGT=test_stl
REM Build x86 binary (for 32bit/64bit Windows)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x86.
set MACHINE=x86
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
REM Build x64 binary (for 64bit Windows only)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x64.
set MACHINE=x64
call detect_vc.bat
REM For release (The binary is optimized)
set DEBUG=
nmake -f Makefile_vc.mak %MAK_TGT%
pause
Enables standard C++ stack unwinding. Catches only standard C++ exceptions when you use catch(...) syntax.
The compiler assumes that functions declared as extern "C" never throw a C++ exception.
Note that if you don't specify c, the compiler assumes that functions declared as extern "C" may throw a C++ exception.
(Excerpt from https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=msvc-170)
最初の2文で、C++の標準的な例外を有効にするには /EHs オプションを指定する必要があることが書かれてあります。
最後の文では、/EHsc の最後の c をもし指定しなかった場合は、C言語の関数の場合もC++例外を投げることがあると書かれてあります。
C++では例外が有効、C言語では例外は無効というのが自然であると私は思いますので、オプション /EHsc を指定しております。
次に /GR ですが、以下のようになります。
/GR
If your code uses dynamic_cast Operator or typeid, you usually need the /GR option.
By default, /GR is on.
(Excerpt from https://docs.microsoft.com/en-us/cpp/build/reference/gr-enable-run-time-type-information?view=msvc-170)
ダイナミックキャストやtypeidを使いたい場合に必要と書かれています。
C++ではこれらが有効である方が自然であると私は思いますので、オプション /GR を指定しております。
尚、By default, /GR is on. とありますが、昔のコンパイラではデフォルトでは off であったため、
そのようなコンパイラでも有効になるように明示的に指定しております。
@echo off
REM Define ZNK_VC_DIR, ZNK_VC_WINSDK_DIR, ZNK_VC_UCRT_DIR
if exist "detect_vc_config.bat" call detect_vc_config.bat
set MAK_TGT=test_dbg
REM Build x86 binary (for 32bit/64bit Windows)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x86.
set MACHINE=x86
call detect_vc.bat
REM For debug (The pdb file is also created)
set DEBUG=d
nmake -f Makefile_vc.mak
pause
REM Build x64 binary (for 64bit Windows only)
REM Define PATH, INCLUDE, LIB and DET_VC_SUBSYS_VER for VC, target binary x64.
set MACHINE=x64
call detect_vc.bat
REM For debug (The pdb file is also created)
set DEBUG=d
nmake -f Makefile_vc.mak
pause
@echo off
LINK /MACHINE:X86 /DEBUG /INCREMENTAL:NO /OUT:test_dbg.exe
Microsoft (R) Incremental Linker Version 11.00.50727.1
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1101: MSPDB110.DLL バージョンが正しくありません。この製品のインストールを再確認してください
NMAKE : fatal error U1077: 'E:\minvs\vs2012_vc11\VC\bin\LINK.EXE' : リターン コード '0x44d'
Stop.
libディレクトリよりもincludeディレクトリの方がサイズが大きくなっています。
includeディレクトリには拡張子が h 以外のファイルも含まれ、それがサイズを食っている感じですがこれは削除しない方がいいでしょう。
C言語の「#include」では拡張子が h とは異なるファイルも強引にincludeできてしまいます。
つまり何がどうincludeされているかファイル名だけでは全貌が判断できないため、不用意に削除すべきではありません。