diff --git a/Readme.md b/Readme.md index 3ffe1a5..88d8ff7 100644 --- a/Readme.md +++ b/Readme.md @@ -83,7 +83,7 @@ If you need to use the heap debugging, please disable VC-LTL. | -------------- | -- | Visual Studio | NuGet or [VC-LTL helper for Visual Studio.props](#31-using-vc-ltl-in-visual-studio) | CMake | [VC-LTL helper for cmake.cmake](#32-using-vc-ltl-in-cmake) -| NMake, CL | [VC-LTL helper for nmake.cmd](#33-using-vc-ltl-in-nmakecl) +| NMake, CL | [VC-LTL helper for nmake.cmd/VC-LTL helper for nmake.ps1](#33-using-vc-ltl-in-nmakecl) | QMake | VC-LTL helper for qmake.pri | Rust | crate @@ -167,13 +167,26 @@ If you download and unzip [VC-LTL Binary](https://github.com/Chuyu-Team/VC-LTL5/ Copy `VC-LTL helper for nmake.cmd` to your project. Run `vcvars32.bat` or `vcvars64.bat` and execute this script. The script will automatically modify the `include` and `lib` environment variables. -**Example:** +**Example: cmd** ``` call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" call "D:\VC-LTL\VC-LTL helper for nmake.cmd" nmake /f Test.mak ``` + +**Example: powershell** +``` +$BuiltInVsWhereExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +$LatestVisualStudioRoot = & $BuiltInVsWhereExe -latest -prerelease -property installationPath + +# x86、amd64、arm、arm64 +& "$LatestVisualStudioRoot\Common7\Tools\Launch-VsDevShell.ps1" -arch x86 +& D:\VC-LTL\VC-LTL helper for nmake.ps1" + +& nmake /f Test.mak +``` + #### 3.3.2. Modify The Configuration > It's recommended to use `/MT` to compile the project when using VC-LTL. diff --git a/Readme.osc.md b/Readme.osc.md index 5816ec2..6e6251f 100644 --- a/Readme.osc.md +++ b/Readme.osc.md @@ -75,7 +75,7 @@ VC-LTL 5.0开始,ABI与微软原版`兼容`,您可以直接使用现有的 | -------------- | -- | Visual Studio | NuGet 或者 [VC-LTL helper for Visual Studio.props](#31-在visual-studio中使用vc-ltl) | CMake | [VC-LTL helper for cmake.cmake](#32-在cmake中使用vc-ltl) -| NMake、CL | [VC-LTL helper for nmake.cmd](#33-在nmake纯cl中使用vc-ltl) +| NMake、CL | [VC-LTL helper for nmake.cmd/VC-LTL helper for nmake.ps1](#33-在nmake纯cl中使用vc-ltl) | QMake | VC-LTL helper for qmake.pri | Rust | crate @@ -158,13 +158,25 @@ add_subdirectory(src) 将辅助脚本`VC-LTL helper for nmake.cmd`复制到你的工程目录。启动`vcvars32.bat/vcvars64.bat`执行此脚本即可,脚本将自动修改`include`以及`lib`环境变量。 -**示例:** +**CMD 示例:** ``` call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" call "D:\VC-LTL\VC-LTL helper for nmake.cmd" nmake /f Test.mak ``` + +**powershell 示例:** +``` +$BuiltInVsWhereExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +$LatestVisualStudioRoot = & $BuiltInVsWhereExe -latest -prerelease -property installationPath + +# x86、amd64、arm、arm64 +& "$LatestVisualStudioRoot\Common7\Tools\Launch-VsDevShell.ps1" -arch x86 +& D:\VC-LTL\VC-LTL helper for nmake.ps1" + +& nmake /f Test.mak +``` #### 3.3.2. 配置工程属性 > 建议使用`/MT`编译代码。如需支持XP,请修改`VC-LTL helper for nmake.cmd`启用 `set WindowsTargetPlatformMinVersion=5.1.2600.0`,除此之外建议您安装YY-Thunks。 diff --git a/UnitTest/UnitTest.cpp b/UnitTest/UnitTest.cpp index db5e372..be61feb 100644 --- a/UnitTest/UnitTest.cpp +++ b/UnitTest/UnitTest.cpp @@ -110,27 +110,190 @@ typedef struct }SecondSec; -class DllImportInfo + +template +static void BuildProcNames(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, IMAGE_THUNK_DATA_T* pThunkData, std::vector& ProcNames) { -public: - CStringA DllName; - //所有CRT导入都是名称导入,所以我们直接把序号导入丢弃! - std::vector ImportNames; + for (; pThunkData->u1.AddressOfData; ++pThunkData) + { + if (pThunkData->u1.AddressOfData >> ((sizeof(pThunkData->u1.AddressOfData) * 8) - 1)) + { + //不支持序号,直接忽略即可 + //Ordinal.insert(pThunkData->u1.Ordinal & 0xffff); + } + else if (auto pImportByName = (PIMAGE_IMPORT_BY_NAME)YY::RtlImageRvaToVa(pNtHeader, pBase, pThunkData->u1.AddressOfData, NULL)) + { + ProcNames.push_back(pImportByName->Name); + } + else + { + CStringW Error; + Error.Format(L"Error:无法加载偏移 %I64X /?\n", (long long)pThunkData->u1.AddressOfData); + + Assert::Fail(Error); + } + } +} - DllImportInfo() +#define IMAGE_FIRST_DIRECTORY(ntheader) (IMAGE_DATA_DIRECTORY*)((byte*)IMAGE_FIRST_SECTION(ntheader)-sizeof(IMAGE_DATA_DIRECTORY)*IMAGE_NUMBEROF_DIRECTORY_ENTRIES) + +template +static void BuildImport(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, std::vector& Infos) +{ + auto pDirectorys = IMAGE_FIRST_DIRECTORY(pNtHeader); + + auto& Imort = pDirectorys[IMAGE_DIRECTORY_ENTRY_IMPORT]; + + auto pImport = (IMAGE_IMPORT_DESCRIPTOR*)YY::RtlImageRvaToVa(pNtHeader, pBase, Imort.VirtualAddress, NULL); + + if (!pImport) { + Assert::AreNotEqual((void*)pImport, (void*)nullptr); + return; } - DllImportInfo(const DllImportInfo& value) = default; + for (; pImport->Name; ++pImport) + { + auto DllName = (const char*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->Name, NULL); + + Assert::AreNotEqual(DllName, nullptr); + + if (!DllName) + { + continue; + } + + DllImportInfo Info; + Info.DllName = DllName; - DllImportInfo(DllImportInfo&& value) - : DllName(value.DllName) - , ImportNames(std::move(value.ImportNames)) + auto pThunkData = (IMAGE_THUNK_DATA_T*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->OriginalFirstThunk, NULL); + + Assert::AreNotEqual((void*)pThunkData, (void*)nullptr); + + if (!pThunkData) + { + //wprintf(L"Error:程序无法读取 dllname = %S OriginalFirstThunk Rva= 0x%.8X。\n", DllName, pImport->OriginalFirstThunk); + + continue; + } + + + BuildProcNames(pBase, pNtHeader, pThunkData, Info.ImportNames); + + Infos.push_back(std::move(Info)); + + } +} + +template +static void BuildDelayImport(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, std::vector& Infos) +{ + auto pDirectorys = IMAGE_FIRST_DIRECTORY(pNtHeader); + + auto& Imort = pDirectorys[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; + + if (Imort.VirtualAddress == 0) + return; + + auto pImport = (IMAGE_DELAYLOAD_DESCRIPTOR*)YY::RtlImageRvaToVa(pNtHeader, pBase, Imort.VirtualAddress, NULL); + + Assert::AreNotEqual((void*)pImport, (void*)nullptr); + + if (!pImport) { - value.DllName.Empty(); + //wprintf(L"Warning:无法加载导入表。\n"); + return; } -}; + for (; pImport->DllNameRVA; ++pImport) + { + auto DllName = (const char*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->DllNameRVA, NULL); + + Assert::AreNotEqual(DllName, nullptr); + + if (!DllName) + { + //wprintf(L"Error:程序无法读取 Rva= 0x%.8X。\n", pImport->DllNameRVA); + + continue; + } + + DllImportInfo Info; + Info.DllName = DllName; + + + auto pThunkData = (IMAGE_THUNK_DATA_T*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->ImportNameTableRVA, NULL); + + Assert::AreNotEqual((void*)pThunkData, (void*)nullptr); + + if (!pThunkData) + { + //wprintf(L"Error:程序无法读取 dllname = %S OriginalFirstThunk Rva= 0x%.8X。\n", DllName, pImport->ImportNameTableRVA); + + continue; + } + + BuildProcNames(pBase, pNtHeader, pThunkData, Info.ImportNames); + + Infos.push_back(std::move(Info)); + + } +} + +std::vector GetDllImportInfo(LPCWSTR szWin32PEFilePath) +{ + std::vector Infos; + + PVOID pBase = nullptr; + + do + { + auto hFile = CreateFileW(szWin32PEFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); + + if (hFile == INVALID_HANDLE_VALUE) + { + break; + } + + auto hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap != NULL) + { + pBase = (PVOID)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + + CloseHandle(hMap); + } + + CloseHandle(hFile); + + } while (false); + + if (pBase == nullptr) + return Infos; + + + auto pNtHeader = YY::RtlImageNtHeader((PVOID)pBase); + + switch (pNtHeader->FileHeader.Machine) + { + case IMAGE_FILE_MACHINE_I386: + case IMAGE_FILE_MACHINE_ARMNT: + BuildImport(pBase, pNtHeader, Infos); + BuildDelayImport(pBase, pNtHeader, Infos); + break; + case IMAGE_FILE_MACHINE_AMD64: + case IMAGE_FILE_MACHINE_ARM64: + BuildImport(pBase, pNtHeader, Infos); + BuildDelayImport(pBase, pNtHeader, Infos); + break; + default: + Assert::Fail(); + break; + } + if(pBase) + UnmapViewOfFile(pBase); + + return Infos; +} namespace UnitTest @@ -550,15 +713,7 @@ namespace UnitTest //关键的来自DLL的函数是否被导入 - const DllImportInfo* pInfo = nullptr; - for (auto& Item : DllImportInfos) - { - if (stricmp(Info.DllName, Item.DllName) == 0) - { - pInfo = &Item; - break; - } - } + const DllImportInfo* pInfo = FindDllImport(DllImportInfos, Info.DllName); Assert::IsNotNull(pInfo, ErrorExt); @@ -852,186 +1007,6 @@ namespace UnitTest return ExclusionSymbols; } - template - static void BuildProcNames(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, IMAGE_THUNK_DATA_T* pThunkData, std::vector& ProcNames) - { - for (; pThunkData->u1.AddressOfData; ++pThunkData) - { - if (pThunkData->u1.AddressOfData >> ((sizeof(pThunkData->u1.AddressOfData) * 8) - 1)) - { - //不支持序号,直接忽略即可 - //Ordinal.insert(pThunkData->u1.Ordinal & 0xffff); - } - else if (auto pImportByName = (PIMAGE_IMPORT_BY_NAME)YY::RtlImageRvaToVa(pNtHeader, pBase, pThunkData->u1.AddressOfData, NULL)) - { - ProcNames.push_back(pImportByName->Name); - } - else - { - CStringW Error; - Error.Format(L"Error:无法加载偏移 %I64X /?\n", (long long)pThunkData->u1.AddressOfData); - - Assert::Fail(Error); - } - } - } - -#define IMAGE_FIRST_DIRECTORY(ntheader) (IMAGE_DATA_DIRECTORY*)((byte*)IMAGE_FIRST_SECTION(ntheader)-sizeof(IMAGE_DATA_DIRECTORY)*IMAGE_NUMBEROF_DIRECTORY_ENTRIES) - - template - static void BuildImport(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, std::vector& Infos) - { - auto pDirectorys = IMAGE_FIRST_DIRECTORY(pNtHeader); - - auto& Imort = pDirectorys[IMAGE_DIRECTORY_ENTRY_IMPORT]; - - auto pImport = (IMAGE_IMPORT_DESCRIPTOR*)YY::RtlImageRvaToVa(pNtHeader, pBase, Imort.VirtualAddress, NULL); - - if (!pImport) - { - Assert::AreNotEqual((void*)pImport, (void*)nullptr); - return; - } - - for (; pImport->Name; ++pImport) - { - auto DllName = (const char*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->Name, NULL); - - Assert::AreNotEqual(DllName, nullptr); - - if (!DllName) - { - continue; - } - - DllImportInfo Info; - Info.DllName = DllName; - - auto pThunkData = (IMAGE_THUNK_DATA_T*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->OriginalFirstThunk, NULL); - - Assert::AreNotEqual((void*)pThunkData, (void*)nullptr); - - if (!pThunkData) - { - //wprintf(L"Error:程序无法读取 dllname = %S OriginalFirstThunk Rva= 0x%.8X。\n", DllName, pImport->OriginalFirstThunk); - - continue; - } - - - BuildProcNames(pBase, pNtHeader, pThunkData, Info.ImportNames); - - Infos.push_back(std::move(Info)); - - } - } - - template - static void BuildDelayImport(PVOID pBase, PIMAGE_NT_HEADERS pNtHeader, std::vector& Infos) - { - auto pDirectorys = IMAGE_FIRST_DIRECTORY(pNtHeader); - - auto& Imort = pDirectorys[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; - - if (Imort.VirtualAddress == 0) - return; - - auto pImport = (IMAGE_DELAYLOAD_DESCRIPTOR*)YY::RtlImageRvaToVa(pNtHeader, pBase, Imort.VirtualAddress, NULL); - - Assert::AreNotEqual((void*)pImport, (void*)nullptr); - - if (!pImport) - { - //wprintf(L"Warning:无法加载导入表。\n"); - return; - } - - for (; pImport->DllNameRVA; ++pImport) - { - auto DllName = (const char*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->DllNameRVA, NULL); - - Assert::AreNotEqual(DllName, nullptr); - - if (!DllName) - { - //wprintf(L"Error:程序无法读取 Rva= 0x%.8X。\n", pImport->DllNameRVA); - - continue; - } - - DllImportInfo Info; - Info.DllName = DllName; - - - auto pThunkData = (IMAGE_THUNK_DATA_T*)YY::RtlImageRvaToVa(pNtHeader, pBase, pImport->ImportNameTableRVA, NULL); - - Assert::AreNotEqual((void*)pThunkData, (void*)nullptr); - - if (!pThunkData) - { - //wprintf(L"Error:程序无法读取 dllname = %S OriginalFirstThunk Rva= 0x%.8X。\n", DllName, pImport->ImportNameTableRVA); - - continue; - } - - BuildProcNames(pBase, pNtHeader, pThunkData, Info.ImportNames); - - Infos.push_back(std::move(Info)); - - } - } - - static std::vector GetDllImportInfo(LPCWSTR szWin32PEFilePath) - { - std::vector Infos; - - PVOID pBase = nullptr; - - do - { - auto hFile = CreateFileW(szWin32PEFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); - - if (hFile == INVALID_HANDLE_VALUE) - { - break; - } - - auto hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hMap != NULL) - { - pBase = (PVOID)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); - - CloseHandle(hMap); - } - - CloseHandle(hFile); - - } while (false); - - if (pBase == nullptr) - return Infos; - - auto pNtHeader = YY::RtlImageNtHeader((PVOID)pBase); - - switch (pNtHeader->FileHeader.Machine) - { - case IMAGE_FILE_MACHINE_I386: - case IMAGE_FILE_MACHINE_ARMNT: - BuildImport(pBase, pNtHeader, Infos); - BuildDelayImport(pBase, pNtHeader, Infos); - break; - case IMAGE_FILE_MACHINE_AMD64: - case IMAGE_FILE_MACHINE_ARM64: - BuildImport(pBase, pNtHeader, Infos); - BuildDelayImport(pBase, pNtHeader, Infos); - break; - default: - Assert::Fail(); - break; - } - - return Infos; - } }; } diff --git a/UnitTest/UnitTest.vcxproj b/UnitTest/UnitTest.vcxproj index cef979e..573846b 100644 --- a/UnitTest/UnitTest.vcxproj +++ b/UnitTest/UnitTest.vcxproj @@ -79,15 +79,19 @@ true + $(ProjectDir);$(IncludePath) true + $(ProjectDir);$(IncludePath) false + $(ProjectDir);$(IncludePath) false + $(ProjectDir);$(IncludePath) @@ -168,10 +172,15 @@ + + + + + diff --git a/UnitTest/UnitTest.vcxproj.filters b/UnitTest/UnitTest.vcxproj.filters index 17263c7..1a2ad13 100644 --- a/UnitTest/UnitTest.vcxproj.filters +++ b/UnitTest/UnitTest.vcxproj.filters @@ -13,6 +13,12 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {230941b5-bba7-46d5-af25-4a94dbe32338} + + + {b703a832-2244-49d9-bbf4-0c184418df34} + @@ -30,10 +36,21 @@ 源文件 + + 源文件\VC-LTL_HelperUnitTest\PowerShell + 头文件 + + + 源文件\VC-LTL_HelperUnitTest\PowerShell + + + 源文件\VC-LTL_HelperUnitTest\PowerShell + + \ No newline at end of file diff --git a/UnitTest/VC-LTL_HelperUnitTest/Example/Example.cpp b/UnitTest/VC-LTL_HelperUnitTest/Example/Example.cpp new file mode 100644 index 0000000..9fe34b6 --- /dev/null +++ b/UnitTest/VC-LTL_HelperUnitTest/Example/Example.cpp @@ -0,0 +1,12 @@ +#include +#include + +#ifndef _LTL_Core_Version +#error VC_LTL not load. +#endif + +int __cdecl main() +{ + printf("VC-LTL Example."); + return 0; +} \ No newline at end of file diff --git a/UnitTest/VC-LTL_HelperUnitTest/Example/NMake/Example.mak b/UnitTest/VC-LTL_HelperUnitTest/Example/NMake/Example.mak new file mode 100644 index 0000000..bb60d5c --- /dev/null +++ b/UnitTest/VC-LTL_HelperUnitTest/Example/NMake/Example.mak @@ -0,0 +1,3 @@ + +build: + cl /MT /Fo"%OutDir%\Example.obj" /Fe"%OutDir%\NMakeExample.exe" ..\Example.cpp \ No newline at end of file diff --git a/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellBuildUnitTest.ps1 b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellBuildUnitTest.ps1 new file mode 100644 index 0000000..87ea9a8 --- /dev/null +++ b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellBuildUnitTest.ps1 @@ -0,0 +1,27 @@ +param($OutDir, $arch, $WindowsTargetPlatformMinVersion="", $CleanImport="") + +&"${PSScriptRoot}\PowerShellInitUnitTest.ps1" -arch $arch -WindowsTargetPlatformMinVersion $WindowsTargetPlatformMinVersion -CleanImport $CleanImport +if($lastexitcode -ne 0) +{ + Write-Error "nmake失败" + exit $lastexitcode +} + +&pushd "${PSScriptRoot}\..\Example\NMake" +$env:OutDir = $OutDir + + +if (-not (Test-Path $env:OutDir)) +{ + mkdir -p "$env:OutDir" +} +& nmake -f Example.mak +&popd + +if($lastexitcode -ne 0) +{ + Write-Error "nmake失败" + exit $lastexitcode +} + +exit 0 \ No newline at end of file diff --git a/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellInitUnitTest.ps1 b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellInitUnitTest.ps1 new file mode 100644 index 0000000..79253c2 --- /dev/null +++ b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellInitUnitTest.ps1 @@ -0,0 +1,44 @@ +param($arch, $WindowsTargetPlatformMinVersion="", $CleanImport="") + +$ProgramFiles = ${env:ProgramFiles(x86)} + +if (-not $ProgramFiles) +{ + $ProgramFiles = $env:ProgramFiles +} + +$BuiltInVsWhereExe = "$ProgramFiles\Microsoft Visual Studio\Installer\vswhere.exe" + +if (-not (Test-Path $BuiltInVsWhereExe)) +{ + Write-Error "找不到vswhere.exe!" + exit 1 +} + +Write-Output $BuiltInVsWhereExe + +$LatestVisualStudioRoot = & $BuiltInVsWhereExe -latest -prerelease -property installationPath + +if (-not (Test-Path $LatestVisualStudioRoot)) +{ + Write-Error "找不到 VisualStudioRoot!" + exit 1 +} + +& "$LatestVisualStudioRoot\Common7\Tools\Launch-VsDevShell.ps1" -arch $arch + +$env:VC_LTL_Root = "${PSScriptRoot}\..\..\.." + +if ($WindowsTargetPlatformMinVersion -ne "") +{ + $env:WindowsTargetPlatformMinVersion = "$WindowsTargetPlatformMinVersion" +} + +if ($CleanImport -ne "") +{ + $env:CleanImport = "$CleanImport" +} + +& "$env:VC_LTL_Root\VC-LTL helper for nmake.ps1" + +exit 0 \ No newline at end of file diff --git a/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellUnitTest.cpp b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellUnitTest.cpp new file mode 100644 index 0000000..03d9631 --- /dev/null +++ b/UnitTest/VC-LTL_HelperUnitTest/PowerShell/PowerShellUnitTest.cpp @@ -0,0 +1,158 @@ +#include "pch.h" +#include "CppUnitTest.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace UnitTest +{ + TEST_CLASS(HelperForPowerShellUnitTest) + { + public: + CString szPSRootPath; + CString szTestDllPath; + + HelperForPowerShellUnitTest() + { + szPSRootPath = _CRT_WIDE(__FILE__); + szPSRootPath.ReleaseBufferSetLength(szPSRootPath.ReverseFind(L'\\') + 1); + + szTestDllPath.ReleaseBufferSetLength(GetModuleFileNameW((HMODULE)&__ImageBase, szTestDllPath.GetBuffer(512), 512)); + szTestDllPath.ReleaseBufferSetLength(szTestDllPath.ReverseFind(L'\\') + 1); + + } + + TEST_METHOD(WindowsTargetPlatformMinVersion适配性检查) + { + struct CheckConfig + { + LPCWSTR szInput; + LPCWSTR szOutput; + }; + + static const CheckConfig _oConfigList[] = + { + // 如果设置 5.0.0.0,预期应该变成5.1.2600.0,因为最低仅支持5.1.2600.0 + { L"5.0.0.0", L"5.1.2600.0"}, + // 版本完全支持,那么就应该维持现状 + { L"5.1.2600.0", L"5.1.2600.0" }, + { L"6.0.6000.0", L"6.0.6000.0"}, + { L"10.0.19041.0", L"10.0.19041.0"}, + // 输入略大于 5.1.2600.0的版本,应该就近匹配,所以是 5.1.2600.0 + { L"5.1.2700.0", L"5.1.2600.0" }, + // 输入超大版本号,自动匹配到最高支持版本 + {L"99.0.19041.0", L"10.0.19041.0"}, + }; + for (auto& _oConfig : _oConfigList) + { + CString _szCmd; + _szCmd.Format(LR"(powershell.exe -File "%wsPowerShellInitUnitTest.ps1" -arch x86 -WindowsTargetPlatformMinVersion "%ws")", szPSRootPath.GetString(), _oConfig.szInput); + CString _szOut; + auto _lStatus = RunCmd(nullptr, _szCmd, &_szOut); + Assert::AreEqual(_lStatus, (LSTATUS)ERROR_SUCCESS); + + auto _nIndex = _szOut.Find(CString(L"WindowsTargetPlatformMinVersion : ") + _oConfig.szOutput); + Assert::AreNotEqual(_nIndex, -1, CString(L"未找到:") + _oConfig.szOutput); + } + } + + TEST_METHOD(可链接性检查) + { + struct CheckConfig + { + LPCWSTR szPlatform; + LPCWSTR szTargetPlatform; + std::vector IncludeDllNames; + std::vector ExcludeDllNames; + }; + + static const CheckConfig _oConfigList[] = + { + {L"x86", L"Win32", {"msvcrt.dll"}, {"vcruntime140.dll"}}, + {L"amd64", L"x64", {"msvcrt.dll"}, {"vcruntime140.dll"}}, + }; + + for (auto& _oConfig : _oConfigList) + { + CString _szOutDir = szTestDllPath; + _szOutDir += LR"(out\HelperForPowerShellUnitTest\)"; + _szOutDir += _oConfig.szPlatform; + + CString _szCmd; + _szCmd.Format(LR"(powershell.exe -File "%wsPowerShellBuildUnitTest.ps1" -arch %ws -OutDir "%ws")", szPSRootPath.GetString(), _oConfig.szPlatform, _szOutDir.GetString()); + CString _szOut; + auto _lStatus = RunCmd(nullptr, _szCmd, &_szOut); + Assert::AreEqual(_lStatus, (LSTATUS)ERROR_SUCCESS); + + auto _nIndex = _szOut.Find(CString(L"Platform : ") + _oConfig.szTargetPlatform); + Assert::AreNotEqual(_nIndex, -1, CString(L"未找到:") + _oConfig.szTargetPlatform); + + auto _oImportInfo = GetDllImportInfo(_szOutDir + LR"(\NMakeExample.exe)"); + + + for (auto _szIncludeDllName : _oConfig.IncludeDllNames) + { + auto _pInfo = FindDllImport(_oImportInfo, _szIncludeDllName); + Assert::IsNotNull(_pInfo, CStringW(_oConfig.szPlatform) + L" Include:" + _szIncludeDllName); + } + + for (auto _szExcludeDllName : _oConfig.ExcludeDllNames) + { + auto _pInfo = FindDllImport(_oImportInfo, _szExcludeDllName); + Assert::IsNull(_pInfo, CStringW(_oConfig.szPlatform) + L" Exclude:" + _szExcludeDllName); + } + } + } + + TEST_METHOD(CleanImport生效检查) + { + struct CheckConfig + { + LPCWSTR szPlatform; + LPCWSTR szAppend; + std::vector IncludeDllNames; + std::vector ExcludeDllNames; + }; + + static const CheckConfig _oConfigList[] = + { + // 默认情况不开启 CleanImport,会依赖 api-ms-win-crt-stdio + {L"x86", L" -WindowsTargetPlatformMinVersion 10.0.10240.0", {"ucrtbase.dll", "api-ms-win-crt-stdio-l1-1-0.dll"}, {"vcruntime140.dll"}}, + // 显式指定关闭 CleanImport,会依赖 api-ms-win-crt-stdio + {L"x86", L" -WindowsTargetPlatformMinVersion 10.0.10240.0 -CleanImport false", {"ucrtbase.dll", "api-ms-win-crt-stdio-l1-1-0.dll"}, {"vcruntime140.dll"}}, + // 开启时不依赖 api-ms-win-crt-stdio + {L"x86", L" -WindowsTargetPlatformMinVersion 10.0.10240.0 -CleanImport true", {"ucrtbase.dll"}, {"vcruntime140.dll", "api-ms-win-crt-stdio-l1-1-0.dll"}}, + }; + + for (auto& _oConfig : _oConfigList) + { + CString _szOutDir = szTestDllPath; + _szOutDir += LR"(out\HelperForPowerShellCleanImportUnitTest\)"; + _szOutDir += _oConfig.szPlatform; + + CString _szCmd; + _szCmd.Format(LR"(powershell.exe -File "%wsPowerShellBuildUnitTest.ps1" -arch %ws -OutDir "%ws")", szPSRootPath.GetString(), _oConfig.szPlatform, _szOutDir.GetString()); + + _szCmd += _oConfig.szAppend; + + CString _szOut; + auto _lStatus = RunCmd(nullptr, _szCmd, &_szOut); + Assert::AreEqual(_lStatus, (LSTATUS)ERROR_SUCCESS); + + auto _oImportInfo = GetDllImportInfo(_szOutDir + LR"(\NMakeExample.exe)"); + + + for (auto _szIncludeDllName : _oConfig.IncludeDllNames) + { + auto _pInfo = FindDllImport(_oImportInfo, _szIncludeDllName); + Assert::IsNotNull(_pInfo, CStringW(_oConfig.szPlatform) + L" Include:" + _szIncludeDllName); + } + + for (auto _szExcludeDllName : _oConfig.ExcludeDllNames) + { + auto _pInfo = FindDllImport(_oImportInfo, _szExcludeDllName); + Assert::IsNull(_pInfo, CStringW(_oConfig.szPlatform) + L" Exclude:" + _szExcludeDllName); + } + } + } + }; +} diff --git a/UnitTest/pch.cpp b/UnitTest/pch.cpp index ad50992..0f09cf7 100644 --- a/UnitTest/pch.cpp +++ b/UnitTest/pch.cpp @@ -4,7 +4,7 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; // 当使用预编译的头时,需要使用此源文件,编译才能成功。 -LSTATUS RunCmd(LPCWSTR FilePath, CString CmdString, CString* pOutString) +LSTATUS RunCmd(LPCWSTR FilePath, CString CmdString, CString* pOutString, CString _szCurrentDirectory) { SECURITY_ATTRIBUTES sa; HANDLE hRead, hWrite; @@ -28,11 +28,12 @@ LSTATUS RunCmd(LPCWSTR FilePath, CString CmdString, CString* pOutString) //关键步骤,CreateProcess函数参数意义请查阅MSDN //auto TT= EXECDOSCMD.GetBuffer(); - wchar_t SystempPath[MAX_PATH + 1]; - - GetSystemDirectoryW(SystempPath, _countof(SystempPath)); + if (_szCurrentDirectory.IsEmpty()) + { + _szCurrentDirectory.ReleaseBufferSetLength(GetSystemDirectoryW(_szCurrentDirectory.GetBuffer(MAX_PATH), MAX_PATH)); + } - if (!CreateProcessW(FilePath, CmdString.GetBuffer(), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, SystempPath, &si, &pi)) + if (!CreateProcessW(FilePath, CmdString.GetBuffer(), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, _szCurrentDirectory.GetString(), &si, &pi)) { return GetLastError(); } diff --git a/UnitTest/pch.h b/UnitTest/pch.h index 3459ab7..0591650 100644 --- a/UnitTest/pch.h +++ b/UnitTest/pch.h @@ -18,7 +18,7 @@ #include #include "CppUnitTest.h" -LSTATUS RunCmd(LPCWSTR FilePath, CString CmdString, CString* pOutString); +LSTATUS RunCmd(LPCWSTR FilePath, CString CmdString, CString* pOutString, CString _szCurrentDirectory = CString()); LSTATUS CreateFileByData(LPCWSTR FilePath, const void* Data, DWORD ccbData); @@ -44,4 +44,39 @@ CString RunMSBuildTest( LPCWSTR BuildProperty = nullptr, CStringW* pTempRoot = nullptr ); + +class DllImportInfo +{ +public: + CStringA DllName; + //所有CRT导入都是名称导入,所以我们直接把序号导入丢弃! + std::vector ImportNames; + + DllImportInfo() + { + } + + DllImportInfo(const DllImportInfo& value) = default; + + DllImportInfo(DllImportInfo&& value) + : DllName(value.DllName) + , ImportNames(std::move(value.ImportNames)) + { + value.DllName.Empty(); + } +}; + +std::vector GetDllImportInfo(LPCWSTR szWin32PEFilePath); + +inline const DllImportInfo* FindDllImport(const std::vector& _oDllImportInfos, LPCSTR _szDllName) +{ + for (auto& Item : _oDllImportInfos) + { + if (stricmp(_szDllName, Item.DllName) == 0) + { + return &Item; + } + } + return nullptr; +} #endif //PCH_H diff --git a/VC-LTL helper for nmake.ps1 b/VC-LTL helper for nmake.ps1 new file mode 100644 index 0000000..31e678e --- /dev/null +++ b/VC-LTL helper for nmake.ps1 @@ -0,0 +1,101 @@ +# +# VC-LTL自动化加载配置,建议你将此文件单独复制到你的工程再使用,该文件能自动识别当前环境是否存在VC-LTL,并且自动应用。 +# +# 使用方法: +# 方法: 1.启动Powershell,并执行如下命令: +# $BuiltInVsWhereExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +# $LatestVisualStudioRoot = & $BuiltInVsWhereExe -latest -prerelease -property installationPath +# # arch支持 x86、amd64、arm、arm64 +# & "$LatestVisualStudioRoot\Common7\Tools\Launch-VsDevShell.ps1" -arch x86 +# +# 2. 然后执行此脚本(VC-LTL helper for nmake.ps1),运行完成后将自动修改include以及lib环境变量,方便nmake以及纯cl用户引用VC-LTL。 +# +# VC-LTL默认搜索顺序 +# 1. “VC-LTL helper for nmake.ps1”所在根目录,即 $PSScriptRoot +# 2. “VC-LTL helper for nmake.ps1”所在根目录下的VC-LTL目录,即 ${PSScriptRoot}\VC-LTL +# 3. “VC-LTL helper for nmake.ps1”所在父目录,即 ${PSScriptRoot}\.. +# 3. “VC-LTL helper for nmake.ps1”所在父目录下的VC-LTL目录,即 ${PSScriptRoot}\..\VC-LTL +# 4. 当前目录,即 (Get-Location).Path +# 5. 当前目录下的VC-LTL目录,即 ${(Get-Location).Path}\VC-LTL +# 6. 当前目录的父目录下的VC-LTL目录,即 ${(Get-Location).Path}\..\VC-LTL +# 7. 注册表HKEY_CURRENT_USER\Code\VC-LTL@Root +# +# 把VC-LTL放在其中一个位置即可,VC-LTL就能被自动引用。 +# +# 如果你对默认搜索顺序不满,你可以修改此文件。你也可以直接指定 $env:VC_LTL_Root 变量更加任性的去加载VC-LTL。 +# +###########################################################VC-LTL设置########################################################### + +# 控制TargetPlatform版本,目前可用版本为 5.1.2600.0 6.0.6000.0(默认) 6.2.9200.0 10.0.10240.0 10.0.19041.0 +# $env:WindowsTargetPlatformMinVersion="10.0.10240.0" + +# 启用干净的导入表,消除 ucrt apiset(如:api-ms-win-crt-time-l1-1-0.dll),满足强迫症患者。 +# $env:CleanImport="true" + +################################################################################################################################ + +do +{ + if ($env:VC_LTL_Root.Length -ne 0) + { + break + } + + #脚本文件根目录存在VC-LTL? + if(Test-Path "${PSScriptRoot}\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root=$PSScriptRoot + break + } + + #脚本文件根目录下存在VC-LTL? + if(Test-Path "${PSScriptRoot}\VC-LTL\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root="${PSScriptRoot}\VC-LTL" + break + } + + #脚本文件父目录存在VC-LTL? + if(Test-Path "${PSScriptRoot}\..\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root="${PSScriptRoot}\.." + break + } + + #脚本文件父目录存在VC-LTL? + if(Test-Path "${PSScriptRoot}\..\VC-LTL\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root="${PSScriptRoot}\..\VC-LTL" + break + } + #当前根目录就是VC-LTL? + if(Test-Path ".\_msvcrt.h" -PathType Leaf){ + $env:VC_LTL_Root=(Get-Location).Path + break + } + #当前根目录存在VC-LTL? + if(Test-Path "${(Get-Location).Path}\VC-LTL\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root="${(Get-Location).Path}\VC-LTL" + break + } + #当前父目录存在VC-LTL? + if(Test-Path "{(Get-Location).Path}\..\VC-LTL\_msvcrt.h" -PathType Leaf) + { + $env:VC_LTL_Root="${(Get-Location).Path}\..\VC-LTL" + break + } + + #读取注册表 HKCU\Code\VC-LTL@Root + try + { + $env:VC_LTL_Root=(Get-ItemProperty -Name "Root" -Path "HKCU:\Code\VC-LTL").Root + break + }catch + { + return + } + +}while($false) + +&"${env:VC_LTL_Root}\config\config.ps1" diff --git a/config/1033/config.strings.ps1 b/config/1033/config.strings.ps1 new file mode 100644 index 0000000..20dd3a6 --- /dev/null +++ b/config/1033/config.strings.ps1 @@ -0,0 +1,12 @@ +Function InitMuiStrings() +{ + $private:lang=@{} + $lang.Add("ERROR_VC_LTL_DONOT_USE_THIS_FILE","Please don't call this script file directly, you should use 'VC-LTL helper for nmake'") + $lang.Add("ERROR_VC_LTL_CANNOT_FOUND_INCLUDE_ENV","The environment variable INCLUDE cannot be found, please make sure Developer PowerShell is executed.") + $lang.Add("ERROR_VC_LTL_CANNOT_FOUND_LIB_ENV","The environment variable LIB cannot be found, please make sure Developer PowerShell is executed.") + $lang.Add("ERROR_VC_LTL_NOT_SUPPORT_PLATFORM_TOOLSET","VC-LTL only supports Visual Studio 2015, 2017, 2019 and 2022.") + $lang.Add("ERROR_VC_LTL_NOT_SUPPORT_PLATFORM","VC-LTL does not support $env:VSCMD_ARG_TGT_ARCH platform.") + $lang.Add("ERROR_VC_LTL_FILE_MISSING","VC-LTL can't find lib files, please download the binary files from https://github.com/Chuyu-Team/VC-LTL5/releases/latest then continue.") + + return $lang; +} \ No newline at end of file diff --git a/config/2052/config.strings.ps1 b/config/2052/config.strings.ps1 new file mode 100644 index 0000000..3dad10d --- /dev/null +++ b/config/2052/config.strings.ps1 @@ -0,0 +1,12 @@ +Function InitMuiStrings() +{ + $private:lang=@{} + $lang.Add("ERROR_VC_LTL_DONOT_USE_THIS_FILE","请不要直接使用此脚本,应该使用VC-LTL helper for nmake.ps1。") + $lang.Add("ERROR_VC_LTL_CANNOT_FOUND_INCLUDE_ENV","找不到环境变量INCLUDE,请在Developer PowerShell执行后调用此脚本。") + $lang.Add("ERROR_VC_LTL_CANNOT_FOUND_LIB_ENV","找不到环境变量LIB,请在Developer PowerShell执行后调用此脚本。") + $lang.Add("ERROR_VC_LTL_NOT_SUPPORT_PLATFORM_TOOLSET","VC-LTL仅支持VS 2015、2017、2019以及2022。") + $lang.Add("ERROR_VC_LTL_NOT_SUPPORT_PLATFORM","VC-LTL POWERSHELL脚本不支持体系 : $env:VSCMD_ARG_TGT_ARCH") + $lang.Add("ERROR_VC_LTL_FILE_MISSING","VC-LTL不找不到lib文件,请从 https://github.com/Chuyu-Team/VC-LTL5/releases/latest 下载完整二进制文件然后继续。") + + return $lang; +} \ No newline at end of file diff --git a/config/config.ps1 b/config/config.ps1 new file mode 100644 index 0000000..b2b340b --- /dev/null +++ b/config/config.ps1 @@ -0,0 +1,221 @@ +# +# 请不要直接使用此脚本,应该使用VC-LTL helper for nmake.ps1 +# + +Function FoundBestTargetPlatformDefault +{ + if($LTLPlatform -ieq "arm64") + { + return "10.0.10240.0" + } + elseif($LTLPlatform -ieq "arm") + { + return "6.2.9200.0" + } + else + { + return "6.0.6000.0" + } +} + +Function FoundBestTargetPlatform +{ + if($env:WindowsTargetPlatformMinVersion.Length -eq 0) + { + return FoundBestTargetPlatformDefault + } + + $CurrentWindowsTargetPlatformMinVersion = [Version]::new($env:WindowsTargetPlatformMinVersion) + + if($CurrentWindowsTargetPlatformMinVersion -gt [Version]::new("10.0.10240.0")) + { + return "10.0.19041.0" + } + elseif($LTLPlatform -ieq "arm64") + { + return "10.0.10240.0" + } + elseif($CurrentWindowsTargetPlatformMinVersion -gt [Version]::new("6.2.9200.0")) + { + return "10.0.10240.0" + } + elseif($LTLPlatform -ieq "arm") + { + return "6.2.9200.0" + } + elseif($CurrentWindowsTargetPlatformMinVersion -gt [Version]::new("6.0.6000.0")) + { + return "6.2.9200.0" + } + elseif($CurrentWindowsTargetPlatformMinVersion -gt [Version]::new("5.2.3790.0")) + { + return "6.0.6000.0" + } + elseif($LTLPlatform -ieq "x64") + { + return "5.2.3790.0" + } + else + { + return "5.1.2600.0" + } +} + +if($env:VC_LTL_Helper_Load -ieq "true") +{ + return +} + +$private:LCID=[globalization.cultureinfo]::CurrentUICulture.LCID +if(-not (Test-Path "${PSScriptRoot}\$LCID\config.strings.ps1")) +{ + # 找不到匹配就使用英语 + $LCID=1033 +} + +."${PSScriptRoot}\$LCID\config.strings.ps1" +$private:lang = InitMuiStrings + +# 检查环境是否可以加载VC-LTL +if($env:INCLUDE.Length -eq 0) +{ + Write-Error $lang.ERROR_VC_LTL_CANNOT_FOUND_INCLUDE_ENV + return +} + +if($env:LIB.Length -eq 0) +{ + Write-Error $lang.ERROR_VC_LTL_CANNOT_FOUND_LIB_ENV + return +} + +# 当前VisualStudio版本符合条件? +if($env:VisualStudioVersion -notin "14.0","15.0","16.0","17.0") +{ + Write-Error $lang.ERROR_VC_LTL_NOT_SUPPORT_PLATFORM_TOOLSET + return +} + +$private:LTLPlatform="" +switch($env:VSCMD_ARG_TGT_ARCH) +{ + "x86" {$LTLPlatform="Win32"} + "x64" {$LTLPlatform="x64"} + "arm" {$LTLPlatform="arm"} + "arm64" {$LTLPlatform="arm64"} + default {$LTLPlatform=""} +} + +if($LTLPlatform -eq "") +{ + Write-Error $lang.ERROR_VC_LTL_NOT_SUPPORT_PLATFORM_TOOLSET + return +} + +# VC-LTL核心版本号,由于4.X并不兼容3.X。此值可以用于兼容性判断。 +$env:LTL_CoreVersion=5 + +$env:VC_LTL_Helper_Load="true" + +# 搜索最佳TargetPlatform +$private:LTLWindowsTargetPlatformMinVersion = FoundBestTargetPlatform + +if(-not (Test-Path "$env:VC_LTL_Root\TargetPlatform\$LTLWindowsTargetPlatformMinVersion\lib\$LTLPlatform")) +{ + Write-Error $lang.ERROR_VC_LTL_FILE_MISSING + return +} + +#line 1 +Write-Host "#######################################################################" -BackgroundColor White -ForegroundColor Black +#line 2 +Write-Host "# #" -BackgroundColor White -ForegroundColor Black +#line 3 +Write-Host -NoNewline "# “ -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline "8b d8" -ForegroundColor Red -BackgroundColor White +Write-Host -NoNewline " ,ad8888ba, " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "888888888888" -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline " 88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 4 +Write-Host -NoNewline "# " -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline "`8b d8" -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "' d8`"' `"8b " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 5 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `8b d8'" -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline " d8' " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 6 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `8b d8' " -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "88 " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 7 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `8b d8' " -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "88 " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "aaaaaaaa " -ForegroundColor DarkMagenta -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 8 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `8b d8' " -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "Y8, " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "`"`"`"`"`"`"`"`" " -ForegroundColor DarkMagenta -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 9 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `888' " -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "Y8a. .a8P " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 10 +Write-Host -NoNewline "#" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline " `8' " -BackgroundColor White -ForegroundColor Red +Write-Host -NoNewline "`"Y8888Y`"' " -ForegroundColor Blue -BackgroundColor White +Write-Host -NoNewline "88888888888 " -ForegroundColor Green -BackgroundColor White +Write-Host -NoNewline "88 " -ForegroundColor DarkYellow -BackgroundColor White +Write-Host -NoNewline "88888888888 " -ForegroundColor Cyan -BackgroundColor White +Write-Host "#" -BackgroundColor White -ForegroundColor Black +#line 11 +Write-Host "# #" -BackgroundColor White -ForegroundColor Black +#line 12 +Write-Host "#######################################################################" -BackgroundColor White -ForegroundColor Black +Write-Host -NoNewline "VC-LTL Path : " -ForegroundColor Red +Write-Host "$env:VC_LTL_Root"-ForegroundColor Green +Write-Host -NoNewline "VC Tools Version : " -ForegroundColor Red +Write-Host "$env:VCToolsVersion" -ForegroundColor Green +Write-Host -NoNewline "WindowsTargetPlatformMinVersion : " -ForegroundColor Red +Write-Host "$LTLWindowsTargetPlatformMinVersion" -ForegroundColor Green +Write-Host -NoNewline "Platform : " -ForegroundColor Red +Write-Host "$LTLPlatform" -ForegroundColor Green + +$env:INCLUDE="$env:VC_LTL_Root\TargetPlatform\header;$env:VC_LTL_Root\TargetPlatform\$LTLWindowsTargetPlatformMinVersion\header;$env:INCLUDE" +$env:LIB="$env:VC_LTL_Root\TargetPlatform\$LTLWindowsTargetPlatformMinVersion\lib\$LTLPlatform;$env:LIB" + +if($CleanImport -ieq "true") +{ + if(Test-Path "$env:VC_LTL_Root\TargetPlatform\$LTLWindowsTargetPlatformMinVersion\lib\$LTLPlatform\CleanImport") + { + $env:LIB="$env:VC_LTL_Root\TargetPlatform\$LTLWindowsTargetPlatformMinVersion\lib\$LTLPlatform\CleanImport;$env:LIB" + } +}