• Mac OS X上用CoreCLR运行一个真正的.NET控制台程序


    这个真正的控制台程序来自corefxlab,名叫CoreClrHelloWorld,是一个跨平台的.NET控制台演示程序,可以显示微软、Linux、苹果的logo。

    CoreClrHelloWorld代码如下(代码中省略了拼接logo的字符串,完整代码见这里):

    using System;
    
    internal class Program
    {
        private static void Main(string[] args)
        {
            if (args.Length == 1 && args[0] == "linux")
            {
                DrawLinux();
            }
            else if (args.Length == 1 && args[0] == "mac")
            {
                DrawMac();
            }
            else
            {
                DrawWindows();
            }
    
            Console.WriteLine();
            Console.WriteLine("Press ENTER to exit ...");
            Console.ReadLine();
        }
    
        private static void DrawWindows()
        {
            Console.WriteLine("Hello, Windows...");
    
            const int squareSize = 20;
    
            var colors = new[] { ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Blue, ConsoleColor.Yellow };
            for (int row = 0; row < 2; row++)
            {
                for (int i = 0; i < squareSize / 2; i++)
                {
                    Console.WriteLine();
                    Console.Write("  ");
                    for (int col = 0; col < 2; col++)
                    {
                        Console.BackgroundColor = colors[row * 2 + col];
                        Console.ForegroundColor = colors[row * 2 + col];
                        for (int j = 0; j < squareSize; j++) Console.Write('@');
                        Console.ResetColor();
                    }
                }
            }
            Console.WriteLine();
        }
    
        private static void DrawLinux()
        {
            Console.WriteLine("Hello, Linux...");
    
            const string Penguin = @"...";
            foreach (char c in Penguin)
            {
                if (c == '
    ')
                {
                    Console.ResetColor();
                    Console.WriteLine();
                }
                else
                {
                    ConsoleColor cc =
                        c == '*' ? ConsoleColor.Blue :
                        c == '@' ? ConsoleColor.Black :
                        c == '-' ? ConsoleColor.Yellow :
                        ConsoleColor.White;
                    Console.BackgroundColor = cc;
                    Console.ForegroundColor = cc;
                    Console.Write(" ");
                }
            }
    
            Console.ResetColor();
            Console.WriteLine();
        }
    
        private static void DrawMac()
        {
            Console.WriteLine("Hello, Mac...");
    
            const string Apple = @"...";
    
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write(Apple);
            Console.ResetColor();
            Console.WriteLine();
        }
    }
    CoreClrHelloWorld

    在之前的博文在Mac OS X上用自己编译出的CoreCLR运行.NET程序中,当时的控制台演示程序只是用到了mscorlib.dll,并没有用到.NET Core Framework(CoreFx)中的程序集。而CoreClrHelloWorld用到了CoreFx中的System.Console.dll,所以如果将CoreClrHelloWorld在Mac上跑起来,就可以进一步体验跨平台的.NET Core。

    在Mac上折腾CoreClrHelloWorld的过程中,主要遇到了3个问题,问题出在System.Console中的ConsolePal.Unix.cs代码对Mac OS X的支持上:

    1)Interop.libc.open64需要改为Interop.libc.open,open64不是POSIX标准中定义的。(详见corefx#715

    2)在Mac OS X中读取terminfo的问题:在Linux中,文件路径是/lib/terminfo/x/xterm-256color;在Mac中是/usr/share/terminfo/78/xterm-256color。78是x的16进制ASCII码,而ConsolePal.Unix.cs中只根据x去读就读取不到。(详见corefx#723

    3)Interop.libc.lseek64需要改为Interop.libc.lseek,原因与问题1一样。(详见corefx#733

    当这3个问题被修复并合并到corefx的主分支之后,就可以在Mac上成功运行CoreClrHelloWorld了。(详见corefx/pull#716#725#736

    下面分享一下详细的操作步骤,操作有些繁琐。

    如果你嫌麻烦,可以从GitHub签出已经配置好的CoreClrHelloWorld,然后直接运行: 

    git clone https://github.com/cnblogs-dudu/CoreClrHelloWorld.git
    cd CoreClrHelloWorld
    runtime_mac/corerun app/HelloWorld.exe mac

    最好自己一步一步操作一下,这样会有不一样的体会。具体操作步骤如下:

    (一)

    【准备CoreClrHelloWorld文件】

    1)创建CoreClrHelloWorld文件夹:mkdir CoreClrHelloWorld;cd $_

    2)创建app文件夹:mkdir app;cd $_

    3)下载CoreClrHelloWorld.cs至app文件夹:

    curl -O https://raw.githubusercontent.com/dotnet/corefxlab/master/demos/CoreClrConsoleApplications/HelloWorld/HelloWorld.cs

    (二)

    【准备CoreCLR】

    运行CoreCLR需要三大组件:corerun, libcoreclr.dylib, mscorlib.dll。

    1)git签出最新版的coreclr代码库:git clone https://github.com/dotnet/coreclr.git

    2)编译coreclr:./build.sh

    3)编译成功之后,在CoreClrHelloWorld中创建runtime_mac文件夹:mkdir ../CoreClrHelloWorld/runtime_mac

    4) 将编译出来的corerun与libcoreclr.dylib复制到CoreClrHelloWorld/runtime_mac文件夹

    cp binaries/Product/amd64/debug/corerun binaries/Product/amd64/debug/libcoreclr.dylib ../CoreClrHelloWorld/runtime_mac

    5) 下载之前博文中用到的mscorlib.dll文件至CoreClrHelloWorld/runtime_mac(该文件由@kangaroo提供,在运行CoreClrHelloWorld时使用,详见这里) 

    cd ../CoreClrHelloWorld/runtime_mac
    curl http://files.cnblogs.com/files/dudu/mscorlib.dll.zip | tar -xf- -C .
    rm -r __MACOSX

    这2步之后CoreClrHelloWorld的文件夹结构如下:

    (三)

    【准备编译时需要引用的程序集】

    1)在CoreClrHelloWorld中创建compile_r_lib文件夹:mkdir compile_r_lib; cd $_

    2)下载nuget.exe:curl -L -O https://nuget.org/nuget.exe

    3)安装nuget中的System.Console包包:

    mono nuget.exe install System.Console -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease

    4)将子文件夹中的System.Console.dll与System.Runtime.dll文件复制到compile_r_lib文件夹:

    find . -wholename '*/aspnetcore50/System.Console.dll' -exec cp {} . ;
    find . -wholename '*/aspnetcore50/System.Runtime.dll' -exec cp {} . ;

    5)下载编译时要引用的mscorlib.dll至compile_r_lib文件夹(该文件也由@kangaroo提供,在编译HelloWorld.cs时使用,详见这里):

    curl http://files.cnblogs.com/files/dudu/mscorlib_contract.dll.zip | tar -xf- -C .
    rm -r __MACOSX

    (四)

    【编译HelloWorld.cs文件】 

    用mono的mcs命令进行编译。

    1)回到CoreClrHelloWorld文件夹:cd ..

    2)运行编译命令: 

    mcs -nostdlib  -r:compile_r_lib/mscorlib.dll -r:compile_r_lib/System.Runtime.dll -r:compile_r_lib/System.Console.dll app/HelloWorld.cs

    如果你不想用mono,也可以将项目复制到Windows中用csc命令进行编译: 

    csc /nostdlib  /r:compile_r_lib/mscorlib.dll /r:compile_r_lib/System.Runtime.dll /r:compile_r_lib/System.Console.dll app/HelloWorld.cs

    编译成功后,就会在app文件夹中看到HelloWorld.exe文件。

     

    (五)

    【准备运行HelloWorld.exe所需的程序集】

    1)由于System.Console还依赖一些其他程序集,都得要通过nuget下载下来,下载到compile_r_lib文件夹中。

    mono nuget.exe install System.Diagnostics.Contracts -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Diagnostics.Debug -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Diagnostics.Tools -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Globalization -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.IO.FileSystem.Primitives -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Reflection -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Resources.ResourceManager -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Runtime.Extensions -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Runtime.Handles -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Runtime.InteropServices -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Text.Encoding.Extensions -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease
    mono nuget.exe install System.Threading -Source https://www.myget.org/F/dotnet-corefx/ -Prerelease

    2)将compile_r_lib中所有通过nuget下载的包包的aspnetcore50文件夹中的程序集复制到runtime_mac文件夹中。

    find . -wholename '*/aspnetcore50/*' -exec cp -n {} ../runtime_mac ;

    3)删除compile_r_lib中所有的nuget包包文件夹

    find . -type d -exec rm -rf {} ;

    (注:感谢@问天何必提供了更简单的删除命令:rm -r -- */ )

    于是最新的CoreClrHelloWorld文件夹结构如下:

    大功告成?没有,但即将告成。现在如果运行程序,会出现下面的错误:

    Unable to continue due to missing library.

    当前的System.Console.dll是从nuget上取下来的,并不支持Mac OS X。我们需要从corefx中自己编译出System.Console.dll,这就是接下来的一项重要工作。

    (六)

    【编译System.Console】

    这一步操作要在Windows上进行。

    1)签出corefx的代码库:git clone https://github.com/dotnet/corefx.git

    2)打开Visual Stuiod的命令行(为了能运行msbuild命令)

    3)进入corefx所在的文件夹,运行msbuild命令:

    msbuild srcSystem.ConsolesrcSystem.Console.csproj /p:OS=Unix;DefineConstants=TRACE /t:clean,build

    (注:一定要加上DefineConstants=TRACE,这样在debug模式下编译时会去除代码中的Debug.Assert。因为Debug.Assert在运行时会引发CoreCLR出现"UNIXTODO: Implement string loading from resources"错误)

    4)编译成功之后,将Windows中的corefxinDebugSystem.ConsoleSystem.Console.dll文件复制到Mac的Coreclrhelloworld untime_mac文件夹中,替换已有的System.Console.dll。

    (七)

    【用CoreCLR运行HelloWorld.exe】

    回到Mac中,进入CoreClrHelloWorld文件夹,运行如下命令:

    runtime_mac/corerun app/HelloWorld.exe mac

    激动人心的时刻到来了!运果结果如下:

    CoreClrHelloWorld for mac

    接着运行命令 runtime_mac/corerun app/HelloWorld.exe linux :

    企鹅只出来了上半身,这地方有点问题,暂且不管了。(这个问题后来被解决了,详见corefx#761

    再接着运行命令 runtime_mac/corerun app/HelloWorld.exe windows :

    CoreClrHelloWorld for Windows

    搞定!Mac.NET之路正一步一步向前迈进。

  • 相关阅读:
    Android开发笔记——WebView
    字符串_最小表示法求循环串的最小序列(HDU_4162)
    STL_map简单应用(HDU_1075)
    DP_最大子序列和(HDU_1003)
    STL map 使用方法(转)
    数学_线性筛法建立素数表(HDU_1262)
    學習筆記 ADO數據庫訪問技術
    C#多线程学习
    Java容器
    选取单元格的基本语句
  • 原文地址:https://www.cnblogs.com/dudu/p/mac-coreclr-helloworld.html
Copyright © 2020-2023  润新知