文章出處

這個真正的控制臺程序來自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 == '\n')
            {
                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 src\System.Console\src\System.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中的corefx\bin\Debug\System.Console\System.Console.dll文件復制到Mac的Coreclrhelloworld\runtime_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之路正一步一步向前邁進。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()