mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-07 05:39:46 +00:00
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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user