Last semester at my uni I had a subject called Object Oriented Programming where our teacher told us we were going to be using C# (C Sharp) as our language for the class. It meant that we had to find a way to install Visual Studio and get things done but the main problem was with those who had a Mac or me, the only one who dared to have a fresh Elementary OS installation (dual booted with Windows 10) into class. For the Mac people, it meant that they didn’t know how what tool to use apart from X-Code which of course didn’t work (but it did for C++) and me, it meant that I had to find a way to compile my code written in mere text editors like Atom or Sublime.
Introduction to cross-compiling for Linux Or: Host, Target, Cross-Compilers, and All That Host vs Target. A compiler is a program that turns source code into executable code. Like all programs, a compiler runs on a specific type of computer, and the new programs it outputs also run on a specific type of computer.
Thankfully I found three ways I could catch up with my classmates during our lab classes: REPL.it (an online tool for writing in a plethora of languages and seeing the STDOUT result), the CSC (C-Sharp compiler) command line tool in Windows and Mono (compiled from the Terminal or with MonoDevelop which is a cross-platform IDE).
- @IsAnton said in Cross compile Qt from Linux to Macos: And in Linux no such tool as xcodebuild, does it means that I can't build Qt from Lunux for Macos? Yes, Apple is the odd one out. You need a Mac to compile for iOS and/or MacOS. As far as I know, no way around it.
- @IsAnton said in Cross compile Qt from Linux to Macos: And in Linux no such tool as xcodebuild, does it means that I can't build Qt from Lunux for Macos? Yes, Apple is the odd one out. You need a Mac to compile for iOS and/or MacOS. As far as I know, no way around it.
Sponsored by Microsoft, Mono is an open-source implementation of Microsoft’s .NET Framework based on the ECMA standards for C# and the Common Language Runtime. A growing family of solutions and an active and enthusiastic contributing community is helping position Mono to become the leading choice for development of cross platform applications. - Mono’s Website
Compiling C# on Windows
Since this is Windows we’re talking about, you probably have the .NET Framework already installed on your computer; the usual path to it is C:/Windows/Microsoft.NET/Framework
, inside you’ll see a bunch of folders with version names. Navigate to the version number that you want to work with (I always choose 4.x) and copy the absolute path of the folder by clicking on the address bar and copying its contents.
Now, you have to edit the PATH environment variable and add the directory address you just copied. This is easy on Windows 7+ because all you have to do is open the search box and typing “variable”, you’ll see something like “Edit System Environment Variables”, click on it and you’ll see something like this:
Click on PATH (sometimes it’s “Path”) and click on the Edit button, in the “Variable Value” text box, at the very end, if it doesn’t end with a semicolon, insert one and paste the address you copied.
Hit OK on both windows, exit the system configuration dialogs and then open the command line (Win + R
and type cmd
, then click on Run) and type in csc
, if it says that the command isn’t recognized, you’re doing things wrong. Install the .NET Framework if you haven’t, localize the direct path to the latest version where the csc.exe executable is and copy the path, then follow the PATH variable instructions here from HowToGeek. Otherwise, you’ll be welcomed with the Microsoft C# Compiler and it’s copyright details.
Now, create a C# test file, it can be this:
Run the following command in the same directory as the file:
Once you fix any compilation warnings and errors that the compiler may throw at you, you won’t see any output but it means that you can now run the code by typing the name of the executable (adding .exe
is optional), hit ENTER
and you’ll see your console output! CSC has some options that you can use, for example, the file wildcard for compiling more than one C# files into a single executable by substituting source_file.cs
with *.cs
, also, refer to the documentation.
Compiling and running C# on Linux and Mac
You can run a GUI application and a console app using Mono, but to actually run ASP .NET web applications you need more than just Mono, you need the K Runtime Environment, I’m sorry I can’t help you with that (I haven’t even bothered to learn ASP .NET ─yet─) but I can refer you to a good and quick tutorial to get install it and get a .NET application running and its dependencies installed; click here for the TechRepublic tutorial. I also saw .NET Core being suggested so you may want to check that out.
Step 1: Install Mono
For Mac users, I won’t say more than this: all you have to do is download the .pkg file, skip to the next step and get going. Now, for the Linux users, you can go here and follow the instructions which I’m going to mention next anyway. Note that the instructions I’ll paste are valid for Ubuntu and Debian based distros (I’m using Elementary OS so, I had to choose this) but if you’re running CentOS, Fedora (or any of its derivatives) or OpenSUSE and SLES you better click on the link I mentioned a couple of sentences ago.
Open up your terminal window and type in the following command, which is going to add a PPA key, you don’t need to worry about what this means if you are new to package management in Linux:
The following command will append a new line to our source list file so that apt-get can find the package instead of outputting a message saying it couldn’t find it:
Now, by rule of thumb, every time we modify the source list or intend to install a new package, we have to run a command to download the package lists from the repositories and update them to the latest versions (it will probably ask for your user password, type it in and hit ENTER
):
Finally, it’s time to install Mono itself and all its dependencies, when you run the command you’ll see that it will ask you to download a ton of packages, it’s ok. What we’re doing here is tell apt-get to retrieve and install all of the packages mentioned; this process is detailed here.
Step 2: Compiling and running C# code
To make sure mono is working correctly, why don’t we set an example console STDOUT application? A simple “Hello World” will do the trick. Open the terminal and navigate to any directory you want, then create a file called hello.cs
by typing touch hello.cs
or editing directly into VIM or Nano and then save the file. Here are the contents of said file:
Now, save it and in the terminal window (making sure you’re still in the same directory as the C# file), execute the Mono compiler; now, there are three compilers that you should be aware of according to the Documentation:
- mcs: references the 4.0-profile libraries (the APIs as defined in .NET 4.0) and supports C# 4.0.
- gmcs: references the 2.0-profile libraries (the APIs as defined in .NET 2.0 and .NET 3.5) and exposes the full C# 3.0 language.
- smcs: references the 2.1-profile libraries (the APIs defined for Silverlight) and exposes the full C# 3.0 language. This is the compiler used for creating Silverlight/Moonlight applications.
dmcs has now been deprecated and the compiler tells us to use mcs instead, so this is the one I’m using!
This command will use the mcs compiler and create a Windows executable with the name of “hello”, taking from source hello.cs
. If the compiler has no warnings or errors to tell you about, you won’t see any output, why don’t you try to remove the semicolon from line 5 on the file? It will output something like this:
It’s telling us that there’s an error on line 6, column 3 (it says 6 and not 5 because of the missing semicolon, it thinks the line continues up to the curly brace) and the message is ; expected
which is pretty self-explanatory. If you want to see all the options available in the compiler, why don’t you head up to the official documentation? One last tip, if you want to compile all the files in a folder you can use the wildcard mcs -out:my-program.exe *.cs
asterisk.
But what if I want to compile a Windows desktop app with GUI that I built with Windows Forms? Then you’d have reference the appropriate DLLs and then run the following command:
Note that you can also start building with GTK, refer to the documentation for how to build GUIs with GTK using Mono.
Time to run the code
The mono
command will allow you to execute the code we just created in the terminal or even a desktop GUI app (for web apps, that’s a whole different shabang). Open the terminal if you closed it by accident and navigate to the directory where the C# file was. Now, execute the following command:
You’ll see that the output is indeed “Hello from KozmicLuis!”:
Enter OmniSharp and MonoDevelop
OmniSharp is a server that will enable your code editor to have the properties of a C# IDE (still not comparable to a real IDE though) and you can also install Yeoman to use some pretty neat project generators (scaffolding). For SublimeText you can go ahead and use the package installer and fetch OmniSharp
. If you’re running Atom (the experience is more pleasant here) you can install the package with the same name omnisharp-atom
(via the app or using apm). For more information go to the official website or watch this video. For Omnisharp to work you need Mono 3 dot something and bigger, I am running the 4th version and still couldn’t get it to work on Elementary OS, I’m not sure if I’m stupid or if I am missing something but I really hope you can get it to work because it’s a blessing because it provides IntelliSense, errors and warnings, code autocompletion and more.
All due image credits go to Quique Fernández at EsMSDN’s blog.
What about the IDEs?
As I mentioned somewhere in this tutorial, you can install two IDEs that are cross-platform and compatible with Mono. MonoDevelop works with C# and F# (functional programming language by Microsoft) and can be installed on the 3 major platforms.
And Xamarin is a mobile .NET platform, you can create Android, iOS and Windows Apps with it using C#.
Also, if you’re on Windows and can’t afford Visual Studio Professional, you can always rely on Visual Studio Community. Another good editor you can use is called VS Code, which can make your transition a bit more comfortable.
Conclusion
Whatever method or platform you use, make sure it’s what you need, I’m still very new to C# and I haven’t even looked into what ASP .NET has to offer because I’m too tangled into the cool kids’ stacks like MERN (MongoDB, Express, ReactJS, and NodeJS) or LEPP (Linux, Nginx, PostgreSQL, and PHP).
Did you know that there’s a C# interactive console? I didn’t, I just found out today while writing this thing. Type csharp
in the terminal if you have Mono installed and enjoy!
Optional: Build with Sublime Text
I almost forgot! You can take advantage of Sublime Text’s builds, they are just shell commands you can execute from within ST by running the CTRL/CMD + B
key combination (or going to Tools > Build).
To get started, go to the Tools
menu and hit the Build System
submenu, then click on New Build System...
. You will be received with a new file that looks like a JSON literal, change the content of that file with this:
For Linux and MacOS
For Windows Machines
Now, save the file with the name of csharp.sublime-build
in the suggested directory and now go to a c# file with Sublime Text, navigate to the Tools > Build
submenu and click the “csharp” checkmark, now when you execute the Build
command (CTRL/CMD + B
) you’ll see a mini window down below like this:
There’s also a plugin called Script! for the Atom editor but it’s harder to configure as it uses csc
as its default command for executing C# code.
Comments:
In my previous posts, I came to the realization that the Raspberry Pi is not very fast! This results lots of chair spinning time while waiting for my projects to compile. A
After I did some brief research, I came across crosstool-ng. It enagbles anyone to create a toolchain to compile Raspberry Pi code directly on a (much faster) Macbook.
If you are unfamiliar with the process of compiling a toolchain on your own computer, let me be frank: it’s not fun.
Luckily, with this post you can get yours working in no time.
Update 8/29/16: I have updated this tutorial in several places for newer systems. I’m currently running a Macbook Pro with 10.11.6.
Note 8/29: This tutorial now is focused on the Raspberry Pi 3 B. Steps can be tweaked to account for older Pis
So without further ado lets do this thing.
Cross Compile On Mac For Linux Virtualbox
Before we get started
Before we start anything I recently compiled the toolchain for RPi3. It will save you a whole bunch of time to download it here rather than go through this procedure.
These files include:
Linux Kernel: 4.3
hardfp: yes
arch: armv8-a
proc: cortex-a53
glibc 2_22
gcc 5.2.0
binutils 2.25.1
gdb 7.10
gmp 6.0.0
mpfr 3.1.3
mpc 1.0.3
For those who want to continue for giggles, by all means…
Install Homebrew
You will need Hombrew to install some dependencies. If you haven’t already installed it you can run the command below:
Install crosstool-ng
Note: a few other dependencies get installed when crosstool-ng is compiled. Be prepared to wait a little while everything assembles.
Install gettext
Note: this is more of a precaution then a requirement. I believe by the end of this process that this was not necessary for getting crosstool-ng to work.
Create two case-sensitive disk images
Open up Disk utility. Click on the New Image button.
1. You need a disk at least 15GB in size. This will house all the source code and object files when all said and done.
2. The next disk can be exactly the same but only 250MB in size. (When fully compiled and compressed everything turned out to be around 107MB)
Note 8/29: for some reason there is a bug on OSX which prevents you from formating a case sensitive drive in Disk Utility. So create a non-case sensitive image and format it to a case sensitive one. The file system needs to be case sensitive.
Note* 8/29: Also, should you make a disk that is not the correct size, you can invoke the resize command to fix it!
Install GNU grep
Crosstools relies on the use of GNU grep. The grep built with OSX is not 100% exactly the same. So, let’s build it!
Note 8/29: this now can be done while installing crosstool-ng using the --with-grep
option.
Edit paths.sh file
My paths.sh file was located here:
I changed the grep line from:
To:
Note 8/29: likely can be avoided with the note above. You can also edit your .bash_profile to temporarily set which grep to use
Load the Linux/GNU option
This will load a general Linux/GNU config. We’ll end up replacing the config but it gives us a good starting point.
Note 8/29: this is a better starting point than my original suggestion. The config file below will change the remaining settings to accomodate for the different processor.
Install config file
Download the config file here.
You will have to copy it to your case sensitive disk image and rename it to .config.
Modify the config file
Run the following in your working directory.
Change the following as needed. Note: This only needs to be changed if you change the names of the .dmg images.
Paths and misc options
Note: all of these are under the ** Paths ** section.
Local tarballs directory
I used /Volumes/xtools-build-env/src. Make sure you set yours to your setup.
Working directory
I used /Volumes/xtools-build-env/.build. Make sure you set yours to your setup.
Prefix directory
I used /Volumes/xtools/${CT_TARGET}. Make sure you set yours to your setup.
Note: the next few settings are under the ** Extracting ** section.
Stop after extracting tarballs
This option should be checked.
Parallel jobs
Note 8/29: new version already has this value set. You can leave it be.
Download and extract the packages
Run the following command:
The build command will stop after extracting all the sources.
Change source file
In ./.build/src/binutils-2.25.1/gold/gold-threads.cc you will need to change the file at line 284. Here is the before and after code blocks:
Change it to:
Update the ulimit
Ulimit controls the amount of resources allowed by a shell instance. In this case we need to increase this limit in order to prevent compilation errors.
Undo some the extract only config option
Undo one of the config settings we changed earlier. Open up:
Paths and misc options.
Compile Linux Program On Windows
Note: the next few settings are under the ** Extracting ** section.
Stop after extracting tarballs
This option should be unchecked.
Begin the build!
Run:
Play the waiting game
Depending on how fast your setup is it may take a few hours to compile fully. If you’re impatient you can always get the binaries I just compiled here
In the end
By the time it’s done doing its thing you should have a fully capable cross platform toolchain for the Raspberry Pi! (Woot) An easy way to test it is to do the following:
Cross Compile On Mac For Linux Operating System
(Hit ctrl-d to escape)
Copy test over to your Raspberry Pi.
Linux Compile C Program
Then ssh in and run the test executable
Cross Compile On Mac For Linux Virtualbox
Other Notes
New notes as of 8/29 are as follows:
STOP/RESTART Crosstools now has a nifty stop and restart feature. Should a build break on a particular sub-component, you can actually fix the issue and continue the build from where it broke. It saves a ton of time. In order to take advantage of the feature you need to enable CT_DEBUG_CT_SAVE_STEPS in your .config
Cross Compile On Mac For Linux Download
Then you can invoke the STOP or RESTART command:
ct-ng list-stepsct-ng build RESTART=cc_core_pass_1
Building Static Becuase OSX does not build based on static libraries we need to make sure those options are disabled. This is already done in my config file but for those who are interested here are the flags:
Thank you to Rolando for posting this in the comments!
Many thanks
I used several blog posts and articles over the web to get this to work. Many thanks to their previous efforts.
Last Modified: 2020.3.7