Skip to content

Commit

Permalink
Port System.Private.DeveloperExperience.Console to CoreRT
Browse files Browse the repository at this point in the history
[tfs-changeset: 1553090]
  • Loading branch information
AlexGhiondea authored and jkotas committed Dec 1, 2015
1 parent 1c04057 commit 9287f36
Show file tree
Hide file tree
Showing 16 changed files with 334 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@

internal static partial class Interop
{
private static class Libraries
{
internal const string SystemPrivateCoreLibNative = "System.Private.CoreLib.Native";
}

internal unsafe partial class Sys
{
[DllImport(Libraries.SystemPrivateCoreLibNative)]
[DllImport(Interop.Libraries.SystemPrivateCoreLibNative)]
internal static unsafe extern int GetEnvironmentVariable(byte* name, out IntPtr result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

internal static partial class Interop
{
internal static class Libraries
{
internal const string SystemPrivateCoreLibNative = "System.Private.CoreLib.Native";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Sys
{
/// <summary>
/// Writes the specified buffer to the provided open file descriptor
/// </summary>
/// <param name="fd">The file descriptor to try and write to</param>
/// <param name="buffer">The data to attempt to write</param>
/// <param name="bufferSize">The amount of data to write, in bytes</param>
/// <returns>
/// Returns the number of bytes written on success; otherwise, returns -1 and sets errno
/// </returns>
[DllImport(Interop.Libraries.SystemPrivateCoreLibNative, SetLastError = true)]
internal static unsafe extern int Write2(int fd, byte* buffer, int bufferSize);
}
}
15 changes: 15 additions & 0 deletions src/Common/src/Interop/Unix/libc/Interop.FileDescriptors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

internal static partial class Interop
{
internal static partial class Sys
{
internal static class FileDescriptors
{
internal const int STDIN_FILENO = 0;
internal const int STDOUT_FILENO = 1;
internal const int STDERR_FILENO = 2;
}
}
}
24 changes: 24 additions & 0 deletions src/Common/src/Interop/Windows/mincore/Interop.Console.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

internal static partial class Interop
{
private static class Libraries
{
internal const string Process = "api-ms-win-core-processenvironment-l1-1-0.dll";
internal const string Console = "api-ms-win-core-console-l1-1-0.dll";
}

internal static unsafe partial class mincore
{
[DllImport("Libraries.Process")]
internal static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport("Libraries.Console", EntryPoint = "WriteConsoleW")]
internal static unsafe extern bool WriteConsole(IntPtr hConsoleOutput, byte* lpBuffer, int nNumberOfCharsToWrite, out int lpNumberOfCharsWritten, IntPtr lpReservedMustBeNull);
}
}
14 changes: 14 additions & 0 deletions src/Common/src/Interop/Windows/mincore/Interop.HandleTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

internal partial class Interop
{
internal partial class mincore
{
internal partial class HandleTypes
{
internal const int INVALID_HANDLE_VALUE = -1;
internal const int STD_ERROR_HANDLE = -12;
}
}
}
27 changes: 27 additions & 0 deletions src/Native/Common/pal_utilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#pragma once

#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <type_traits>

/**
* Cast a positive value typed as a signed integer to the
* appropriately sized unsigned integer type.
*
* We use this when we've already ensured that the value is positive,
* but we don't want to cast to a specific unsigned type as that could
* inadvertently defeat the compiler's narrowing conversion warnings
* (which we treat as error).
*/
template <typename T>
inline typename std::make_unsigned<T>::type UnsignedCast(T value)
{
assert(value >= 0);
return static_cast<typename std::make_unsigned<T>::type>(value);
}

1 change: 1 addition & 0 deletions src/Native/System.Private.CoreLib.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ project(System.Private.CoreLib.Native)
set(NATIVE_SOURCES
pal_environment.cpp
pal_memory.cpp
pal_io.cpp
)

add_library(System.Private.CoreLib.Native
Expand Down
27 changes: 27 additions & 0 deletions src/Native/System.Private.CoreLib.Native/pal_io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include "pal_utilities.h"

extern "C" int32_t Write2(int32_t fd, const void* buffer, int32_t bufferSize)
{
assert(buffer != nullptr || bufferSize == 0);
assert(bufferSize >= 0);

if (bufferSize < 0)
{
errno = ERANGE;
return -1;
}

ssize_t count = write(fd, buffer, UnsignedCast(bufferSize));
assert(count >= -1 && count <= bufferSize);
return static_cast<int32_t>(count);
}

2 changes: 2 additions & 0 deletions src/Native/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ include(CheckStructHasMember)
include(CheckCXXSourceCompiles)
include(CheckCXXSourceRuns)

add_compile_options(-I${CMAKE_CURRENT_SOURCE_DIR}/Common)

if (NOT WIN32)
include_directories(SYSTEM /usr/local/include)
endif ()
Expand Down
5 changes: 3 additions & 2 deletions src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@
</ItemGroup>

<!-- Windows is default build -->
<ItemGroup Condition="'$(OSGroup)' == 'Windows_NT'">
<ItemGroup Condition="'$(TargetsWindows)'=='true'">
<Compile Include="System\Globalization\CultureInfo.Win32.cs" />
<Compile Include="System\Globalization\CompareInfo.Win32.cs" />
<Compile Include="System\Globalization\CultureData.Win32.cs" />
Expand All @@ -492,14 +492,15 @@
<Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.Environment.cs" />
</ItemGroup>

<ItemGroup Condition="'$(OSGroup)' != 'Windows_NT'">
<ItemGroup Condition="'$(TargetsUnix)'=='true'">
<Compile Include="System\Globalization\CultureInfo.Dummy.cs" />
<Compile Include="System\Globalization\CompareInfo.Dummy.cs" />
<Compile Include="System\Globalization\CultureData.Dummy.cs" />
<Compile Include="System\Globalization\TextInfo.Dummy.cs" />
<Compile Include="System\Globalization\CalendarData.Dummy.cs" />
<Compile Include="System\Environment.EnvironmentVariables.Unix.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Environment.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Libraries.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.StringHelper.cs" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace Internal.DeveloperExperience
{
internal static class ConsolePal
{
internal unsafe static void WriteError(string errorMessage)
{
byte[] errorMessageAsBytes = Interop.StringHelper.GetBytesFromUTF8string(errorMessage);
fixed (byte* pBuffer = errorMessageAsBytes)
{
Interop.Sys.Write2(Interop.Sys.FileDescriptors.STDERR_FILENO, pBuffer, errorMessageAsBytes.Length);
}

// Write new line
byte newLine = (byte) '\n';
Interop.Sys.Write2(Interop.Sys.FileDescriptors.STDERR_FILENO, &newLine, 1);

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace Internal.DeveloperExperience
{
internal static class ConsolePal
{
private static IntPtr s_consoleErrorHandle = Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_ERROR_HANDLE);

internal unsafe static void WriteError(string errorMessage)
{
if (s_consoleErrorHandle == new IntPtr(Interop.mincore.HandleTypes.INVALID_HANDLE_VALUE))
{
// ensure we have a valid handle before writing to it
return;
}

fixed (char *pBuffer = errorMessage)
{
int numberOfCharsWritten;
Interop.mincore.WriteConsole(s_consoleErrorHandle, (byte*)pBuffer, errorMessage.Length, out numberOfCharsWritten, IntPtr.Zero);
}

// Write new line
fixed (char* pBuffer = "\r\n")
{
int numberOfCharsWritten;
Interop.mincore.WriteConsole(s_consoleErrorHandle, (byte*)pBuffer, 2, out numberOfCharsWritten, IntPtr.Zero);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using global::System;
using global::System.Diagnostics;

namespace Internal.DeveloperExperience
{
public static class DeveloperExperienceConnectorConsole
{
// This method is targeted by the MainMethodInjector transform. This method exists in various DeveloperExperience.*.dll's.
// The MainMethodInjector chooses an appropriate one (or none) depending on the build configuration and app structure.
//
// The Console DeveloperExperience is chosen if the main exe has a reference to System.Console. This is for internal Microsoft use only.
// It should remain small enough that we don't bother shutting it off on retail builds.
public static void Initialize()
{
DeveloperExperience.Default = new DeveloperExperienceConsole();
return;
}
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using global::System;
using global::System.Diagnostics;
using global::Internal.StackTraceGenerator;

namespace Internal.DeveloperExperience
{
internal sealed class DeveloperExperienceConsole : DeveloperExperience
{
public sealed override void WriteLine(String s)
{
ConsolePal.WriteError(s);
}

public sealed override String CreateStackTraceString(IntPtr ip, bool includeFileInfo)
{
String s = Internal.StackTraceGenerator.StackTraceGenerator.CreateStackTraceString(ip, includeFileInfo);
if (s != null)
return s;
return base.CreateStackTraceString(ip, includeFileInfo);
}

public sealed override void TryGetSourceLineInfo(IntPtr ip, out string fileName, out int lineNumber, out int columnNumber)
{
Internal.StackTraceGenerator.StackTraceGenerator.TryGetSourceLineInfo(ip, out fileName, out lineNumber, out columnNumber);
// we take whatever data StackTraceGenerator can get (none/partial/all). No reason to fall-back because the base-type
// never finds anything.
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<AssemblyName>System.Private.DeveloperExperience.Console</AssemblyName>
<OutputType>Library</OutputType>
<ProjectGuid>{F9EF39E7-C8E4-4776-A952-FEF7A1FC2D3B}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetPlatformIdentifier>Portable</TargetPlatformIdentifier>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkMonikerDisplayName>.NET Portable Subset</TargetFrameworkMonikerDisplayName>
<ImplicitlyExpandTargetFramework>false</ImplicitlyExpandTargetFramework>
</PropertyGroup>

<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|amd64' ">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|amd64' ">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|arm' ">
<PlatformTarget>arm</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|arm' ">
<PlatformTarget>arm</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Compile Include="Internal\DeveloperExperience\DeveloperExperienceConnector.cs" />
<Compile Include="Internal\DeveloperExperience\DeveloperExperienceConsole.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetsWindows)'=='true'">
<Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.Console.cs" />
<Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.HandleTypes.cs" />
<Compile Include="Internal\DeveloperExperience\ConsolePal.Windows.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetsUnix)'=='true'">
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.StringHelper.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Libraries.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Write.cs" />
<Compile Include="..\..\Common\src\Interop\Unix\libc\Interop.FileDescriptors.cs" />
<Compile Include="Internal\DeveloperExperience\ConsolePal.Unix.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
<ProjectReference Include="..\..\AotPackageReference\AotPackageReference.depproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

<ReferencePath Include="$(AotPackageReferencePath)\System.Runtime.dll" />
<ReferencePath Include="$(AotPackageReferencePath)\System.Runtime.Extensions.dll" />
<ReferencePath Include="$(AotPackageReferencePath)\System.Diagnostics.Tracing.dll" />
<ReferencePath Include="$(AotPackageReferencePath)\System.Collections.dll" />
<ReferencePath Include="$(AotPackageReferencePath)\System.Resources.ResourceManager.dll" />

<ProjectReference Include="..\..\System.Private.StackTraceGenerator\src\System.Private.StackTraceGenerator.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

0 comments on commit 9287f36

Please sign in to comment.