Move project to app CRTs in preparation to run Universal (#3474)

* Change to use App CRT in preparation for universal.
* Try to make project build again by setting winconpty to static lib so it'll use the CRT inside TerminalConnection (or its other consumers) instead of linking its own.
* Remove test for conpty dll, it's a lib now. Add additional commentary on how CRT linking works for future reference. I'm sure this will come up again.
* use the _apiset variant until proven otherwise to match the existing one.
* Clarification in the comments for linking.
This commit is contained in:
Michael Niksa
2019-11-08 14:09:39 -08:00
committed by GitHub
parent 4dd476ecbd
commit ddcc06e911
6 changed files with 16 additions and 263 deletions

View File

@@ -83,9 +83,6 @@ Try {
}
}
If ($null -eq (Get-Item "$AppxPackageRootPath\conpty.dll" -EA:Ignore)) {
Throw "Failed to find conpty.dll -- check the wapproj and winconpty.vcxproj"
}
} Finally {
Remove-Item -Recurse -Force $AppxPackageRootPath
}

View File

@@ -26,7 +26,7 @@
Re-inject some necessary libs when MinimalCoreWin has been enabled.
-->
<AdditionalDependencies Condition="'$(MinimalCoreWin)'=='true'">gdi32.lib;advapi32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>onecore_apiset.lib;dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;uxtheme.lib;dwmapi.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>onecoreuap_apiset.lib;onecore_apiset.lib;dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;uxtheme.lib;dwmapi.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

View File

@@ -31,13 +31,18 @@
<!-- This is magic that tells msbuild to link against the Desktop platform
instead of the App platform. This you definitely want, because we're not
building a true universal "app", we're building a desktop application
with xaml. Without this, we'll link against the app CRT, and the
unpackaged story _will not_ work. Furthermore, APIs like
CreatePseudoConsole won't be linkable without this.
with xaml. APIs like CreatePseudoConsole won't always be linkable without Desktop platform,
but we now carry our own copy of them in the winconpty library which works everywhere.
For future reference, _VC_Target_Library_Platform can be configured to say which CRT to link against.
Now that this doesn't say anything, the implicit is 'Store' which links against the App CRT.
The alternative is 'Desktop' which links against the usual CRT redistributable.
Linking against the App CRT will require the VCRT forwarders to be dropped next to the final binary for
desktop situations, but it will let non-desktop situations work since there is no redist off desktop.
The forwarders can be found at https://github.com/microsoft/vcrt-forwarders and are already included
in our CascadiaPackage project.
-->
<PropertyGroup>
<_NoWinAPIFamilyApp>true</_NoWinAPIFamilyApp>
<_VC_Target_Library_Platform>Desktop</_VC_Target_Library_Platform>
<GenerateProjectSpecificOutputFolder>false</GenerateProjectSpecificOutputFolder>
</PropertyGroup>

View File

@@ -1,244 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
using WEX::Logging::Log;
using WEX::TestExecution::TestData;
using namespace WEX::Common;
class PtyTests
{
BEGIN_TEST_CLASS(PtyTests)
END_TEST_CLASS()
HRESULT SpawnClient(HPCON hPC, wil::unique_process_information& pi)
{
HRESULT hr = E_FAIL;
STARTUPINFOEXW startupInfo{};
if (S_OK == (hr = InitializeStartupInfoAttachedToPseudoConsole(&startupInfo, hPC)))
{
// Launch cmd to emit some text back via the pipe
auto szCommand = _wcsdup(L"cmd.exe");
hr = CreateProcessW(
NULL,
szCommand,
NULL,
NULL,
FALSE,
EXTENDED_STARTUPINFO_PRESENT,
NULL,
NULL,
&startupInfo.StartupInfo,
&pi) ?
S_OK :
GetLastError();
free(szCommand);
}
return hr;
}
struct Baton
{
HPCON hPC;
HANDLE ev;
DWORD closeMethod;
HANDLE inputWriter;
HANDLE outputReader;
};
HRESULT RunTest(bool inherit, bool read, bool write, DWORD endSessionBy)
{
Log::Comment(L"Creating communication pipes.");
HANDLE h1i, h1o, h2i, h2o;
auto f = !!CreatePipe(&h1o, &h1i, nullptr, 0);
if (!f)
{
Log::Comment(L"Beefed it at pipe 1");
return 1;
}
f = !!CreatePipe(&h2o, &h2i, nullptr, 0);
if (!f)
{
Log::Comment(L"Beefed it at pipe 2");
return 1;
}
DWORD dwFlags = 0;
if (inherit)
{
Log::Comment(L"Setting inherit flag...");
dwFlags = PSEUDOCONSOLE_INHERIT_CURSOR;
}
Log::Comment(L"Calling CreatePseudoConsole");
HPCON hPC;
auto hr = CreatePseudoConsole({ 80, 25 }, h1o, h2i, dwFlags, &hPC);
if (hr != S_OK)
{
Log::Comment(String().Format(L"Failed: %8.08x", hr));
return 1;
}
Log::Comment(L"Closing my half of the communication pipes.");
CloseHandle(h1o);
CloseHandle(h2i);
if (write)
{
// We do this out of order (writing the answer before we are asked) because we're doing it single threaded.
Log::Comment(L"Writing cursor response into buffer before we're asked.");
const char* buffer = "\x1b[0;0R";
DWORD dwWritten = 0;
WriteFile(h1i, buffer, 6, &dwWritten, nullptr);
const auto glewrite = GetLastError();
}
wil::unique_process_information pi;
Log::Comment(L"Spawning client application.");
hr = SpawnClient(hPC, pi);
if (read)
{
Log::Comment(L"Reading the cursor request from the buffer so it will be drained.");
byte bufferOut[256];
DWORD dwRead = 0;
ReadFile(h2o, &bufferOut, ARRAYSIZE(bufferOut), &dwRead, nullptr);
}
if (hr != S_OK)
{
Log::Comment(String().Format(L"Spawn took a trip to beeftown: %8.08x", hr));
return 1;
}
Log::Comment(L"Letting CMD actually spawn?");
Sleep(1000); // Let it settle?
Baton b{ hPC, nullptr };
b.ev = CreateEventW(nullptr, TRUE, FALSE, L"It is an event");
b.closeMethod = endSessionBy;
b.inputWriter = h1i;
b.outputReader = h2o;
CreateThread(
nullptr, 0, [](LPVOID c) -> DWORD {
Baton& b = *reinterpret_cast<Baton*>(c);
Log::Comment(L"Closing?");
switch (b.closeMethod)
{
case 0:
Log::Comment(L"Closing with the API (breaks signal handle)");
ClosePseudoConsole(b.hPC);
break;
case 1:
Log::Comment(L"Closing by breaking input handle.");
CloseHandle(b.inputWriter);
break;
case 2:
Log::Comment(L"Closing by breaking output handle.");
CloseHandle(b.outputReader);
break;
}
SetEvent(b.ev);
return 0;
},
(LPVOID)&b,
0,
nullptr);
Log::Comment(L"Waiting to let the environment teardown.");
auto r = WaitForSingleObject(b.ev, 5000);
switch (r)
{
case WAIT_OBJECT_0:
Log::Comment(L"Hey look it works.");
break;
case WAIT_TIMEOUT:
Log::Comment(L"\x1b[4;1;31mYOU DEADLOCKED IT\x1b[m\n");
return HRESULT_FROM_WIN32(WAIT_TIMEOUT);
case WAIT_FAILED:
{
auto gle = GetLastError();
Log::Comment(String().Format(L"You somehow broke it even worse (GLE=%d)", gle));
return HRESULT_FROM_WIN32(gle);
}
}
return S_OK;
}
// Initializes the specified startup info struct with the required properties and
// updates its thread attribute list with the specified ConPTY handle
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEXW* pStartupInfo, HPCON hPC)
{
HRESULT hr{ E_UNEXPECTED };
if (pStartupInfo)
{
SIZE_T attrListSize{};
pStartupInfo->StartupInfo.cb = sizeof(STARTUPINFOEXW);
// Get the size of the thread attribute list.
InitializeProcThreadAttributeList(NULL, 1, 0, &attrListSize);
// Allocate a thread attribute list of the correct size
pStartupInfo->lpAttributeList =
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attrListSize));
// Initialize thread attribute list
if (pStartupInfo->lpAttributeList && InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize))
{
// Set Pseudo Console attribute
hr = UpdateProcThreadAttribute(
pStartupInfo->lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
hPC,
sizeof(HPCON),
NULL,
NULL) ?
S_OK :
HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
TEST_METHOD(PtyInitAndShutdown)
{
BEGIN_TEST_METHOD_PROPERTIES()
TEST_METHOD_PROPERTY(L"Data:inheritCursor", L"{true, false}")
TEST_METHOD_PROPERTY(L"Data:readOutput", L"{true, false}")
TEST_METHOD_PROPERTY(L"Data:writeInput", L"{true, false}")
TEST_METHOD_PROPERTY(L"Data:endSessionBy", L"{0, 1, 2}")
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
END_TEST_METHOD_PROPERTIES()
bool inheritCursor;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"inheritCursor", inheritCursor));
bool readOutput;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"readOutput", readOutput));
bool writeInput;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"writeInput", writeInput));
DWORD endSessionBy;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"endSessionBy", endSessionBy));
VERIFY_SUCCEEDED(RunTest(inheritCursor, readOutput, writeInput, endSessionBy));
}
};

View File

@@ -6,7 +6,7 @@
<RootNamespace>HostFeatureTests</RootNamespace>
<ProjectName>Host.Tests.Feature</ProjectName>
<TargetName>ConHost.Feature.Tests</TargetName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
@@ -59,10 +59,9 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.build.tests.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>$(OutDir)\conpty.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
</Project>

View File

@@ -6,7 +6,7 @@
<RootNamespace>winconpty</RootNamespace>
<ProjectName>winconpty</ProjectName>
<TargetName>conpty</TargetName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
@@ -25,13 +25,11 @@
</ItemDefinitionGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<ItemDefinitionGroup>
<Link>
<ModuleDefinitionFile>winconpty.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<!-- Override GetPackagingOutputs to roll up our DLL.
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
-->
@@ -41,7 +39,7 @@
</PropertyGroup>
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
<CallTarget Targets="BuiltProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="_BuiltProjectOutputGroupOutput"/>
<Output TaskParameter="TargetOutputs" ItemName="_BuiltProjectOutputGroupOutput" />
</CallTarget>
<ItemGroup>
<_PackagingOutputsUnexpanded Include="%(_BuiltProjectOutputGroupOutput.FinalOutputPath)">
@@ -50,9 +48,8 @@
<ProjectName>$(ProjectName)</ProjectName>
</_PackagingOutputsUnexpanded>
</ItemGroup>
<CallTarget Targets="DebugSymbolsProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="_DebugSymbolsProjectOutputGroupOutput"/>
<Output TaskParameter="TargetOutputs" ItemName="_DebugSymbolsProjectOutputGroupOutput" />
</CallTarget>
<ItemGroup>
<_PackagingOutputsUnexpanded Include="%(_DebugSymbolsProjectOutputGroupOutput.FinalOutputPath)">
@@ -60,11 +57,10 @@
<ProjectName>$(ProjectName)</ProjectName>
</_PackagingOutputsUnexpanded>
</ItemGroup>
<ItemGroup>
<PackagingOutputs Include="@(_PackagingOutputsUnexpanded)">
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
</Project>
</Project>