Archive

Tag Cloud

3d account algorithms announcement archives arduino artificial intelligence assembly async audio bash batch blog bookmarklet booting c sharp c++ challenge chrome os code codepen coding conundrums coding conundrums evolved command line compiling css dailyprogrammer debugging demystification distributed computing downtime embedded systems encryption es6 features event experiment external first impressions future game github github gist graphics hardware meetup holiday html html5 html5 canvas interfaces internet io.js jabber javascript js bin labs learning library linux low level lua maintenance network networking node.js operating systems performance photos php pixelbot portable privacy programming problems project projects prolog protocol pseudo 3d python reddit reference release releases resource review rust secrets security series list server servers software sorting source code control svg technical terminal textures three thing game three.js tool tutorial twitter ubuntu university update upgrade version control visual web website windows windows 10 xmpp

Sorry for the (very) late post! I fell rather ill on the day before I was going to write the next post, and haven't been well enough to write it until now! Hopefully more cool posts will be on their way soon :-)

(Above: A nice picture of Durham Cathedral. Taken by @euruicimages.)

How many times have you just finished adding a new feature to your latest and greatest program, and hit the "Run" button in Visual Studio or Monodevelop? Have you ever wondered what happens under the hood? Have you ever encountered a strange build error, and just googled the error message in the hope of finding a solution?

In this post, I'm going take you on a journey to understand the build process for a typical C♯ program that happens every time you press Ctrl + Shift + B (or F8 in Monodevelop). I also hope to show you why I think it's important to understand what happens behind the scenes.

To start any journey, we need a map. I've created a simple diagram for our journey. We'll dive into the world of the project file further down. Lastly, we'll end our journey at the individual source code files that actually make up your project.

Before that though, we need to make a quick stop in your sln file. The sln file (or Solution File) is the place where everything starts. Normally, you only get one solution file for each project you create. It's the file that keeps track of the name of your project, its id, and where all the projects are that your solution references (they're usually in appropriately named subfolders). Note that it doesn't keep references to the other projects that you reference (that's done at the project file level).

Solution files sometimes automatically detected too (xbuild does this for sure). If you're in a command line or terminal, you can build an entire solution with just one command, without having to open Visual Studio or Monodevelop:

cd /path/to/awesome/project
# Windows
msbuild AwesomeSpaceProject.sln
# Linux / Mono
xbuild

With that out of the way, we can talk about project files. Project files define which source code files should be built, and how. You can even add custom triggers that run at any time before, during, or after the build process here (this is how I embedded commit hashes in a C♯ binary)!

Though the syntax is quite simple, much of it is, sadly, un or underdocumented. Thankfully most of it is quite intuitive, and a little experimentation goes a long way:

<Project>
....
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
....
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="GameObjects/Spaceship.cs" />
<Compile Include="GameObjects/Enemy.cs" />
....
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Spritesheet.png" />
<EmbeddedResource Include="Resources\CoolSpace.ttf" />
</ItemGroup>
....
</Project>

The above is a (simplified) example if a project file. It might be called something like CoolSpace.csproj. It references a few core assemblies, specifies a few C♯ files for compiling, and embeds a resource or two.

Of course, these files are generated for you automatically, but it's always helpful to know how to works so not only can you fix it more easily when it goes wrong, but you can also extend it to do extra things that you can't through the user interface, like use wildcards (careful! Too many wildcards can slow down your build) to specify a range of files that you wan to embed without having to go around them all one by one.

Next, let's talk about references. References allow you to pull in code from elsewhere, like a core system library, another project (that's how you link 2 projects in (or even out of!) a solution together), a library of sorts (like Nuget), or another random DLL or EXE (yes, you can reference other executable files) file lying around. With references, yo can spread your code around loads of files and pull in libraries from all over the galaxy and have the build process follow all of your references around and tie everything up into a nice neat package for you.

The next piece of the puzzle is the builder. The software that actually builds your code. On Windows with Visual Studio, it's called msbuild, and is the original build tool, created by Microsoft, that sets the standard. On Linux, there's a different (but very similar) tool called xbuild. xbuild implements the standard that msbuild sets, allowing solutions written on Windows with Visual Studio to be compiled 9 times out of 10 on Linux (and probably Mac too, though I don't have one to check - let me know in the comments if you have one!) without any changes.

The final stone in the bridge, so to speak, is your code itself. The builder (whether it be xbuild or msbuild) preprocesses each included file into an object file, which are then all linked together into the final executable binary, which itself contains common intermediate language (or CIL) which is executed by your operating system (or mono on Linux / Mac). While CIL is a different topic for a separate time, it's still important, so I'm mentioning it here.

Tired of battling endless <script> tags in your html files? Fed up with messing with a dozen libraries cluttering up the place? Can't see the wood from the trees? Try browserify (+ rollupify + wzrd)! It's amazing! It's awesome! It tidies up your code for you, so you don't have to (perhaps not :P)!

Seriously though, I've just been playing around with browserify, and it's awesome. It's that missing thing I've been trying to find for a long time. But what does it actually do, you ask?

Well, perhaps it's best to use an example. Consider these (relatively) harmless javascript files:

// SillySay.js
"use strict";

function sillySay(sentence) {
// Split the sentence up into words
var words = splitWords(sentence);

// Loop over all the words in the above array and display them one by one
for(let i in words) {
}
}

// WordSplitter.js
"use strict";
function splitWords(sentence) {
// Split the sentence on whitespace and return the resulting array
return sentence.split(/\s+/g);
}

To use our (perfectly ridiculous) example code, we not only have to include SillySay.js, but WordSplitter.js (this could be a library you use for example) as well:

<!DOCTYPE html>
<html>
<meta charset='utf-8' />
<title>Silly Say Demo</title>
<body>
<p>Silly Say Demo</p>
<p>By <a href="https://starbeamrainbowlabs.com/">Starbeamrainbowlabs</a></p>

<!---------------->
<script src="WordSplitter.js"></script>
<script src="SillySay.js" charset="utf-8"></script>
<script>
sillySay("This is a test");
});
</script>

<style>
html, body { font-size: 100%; }
body
{
font-family: sans-serif;
}
</style>
</html>

That's looking a bit messy, but imagine what it'd be like if you added another few libraries? Or a new feature in a separate file? See the problem? Browserify solves just this issue. It analyses the dependencies of the entry point to your app, and bundles up all your code into a single file, nice and neat. You can add extra transforms (like plugins), too, to do extra things like automatically insert your app's version, or include other data files automatically, or transpile other languages to javascript automagically (full list here).

Sounds cool yet? Let me give you a quick tutorial on how I set up Browserify, with Rollupify and Wzrd.

Firstly, we need to set things up. If you don't have Node.js installed, do that now. You'll also get npm - Node's (perfectly awesome!) package manager. Next, let's create a quick project and paste in the code above. I've recorded an asciicast (as you may have seen a few times before here) of me going through the process:

(Can't see the asciicast above? Try viewing it here.)

If you'd like to take a look at the final result, as written in the asciicast above, you can find it over here. Questions and comments are welcome below :-)

The lost post: Embedding commit hashes in C♯ binaries

I seem to remember that I've started to write this post no less than 3 times, and I've managed to lose the source each and every time. If you're reading this it means that I've managed to complete it this time :D

Imagine you've got a confused client on the phone, asking why the newest feature X in your program doesn't work. You ask them whether they have the latest version of your program installed... and they say that they don't know. Version numbers and changelogs to the rescue! Except.... that last release was rather rushed and you forgot to finish updating the changelog. This is just one scenario in which embedding the latest commit hash into your program is useful.

You could embed the short hash (the first 7 characters) into the version string, for example v3.6.1-375ae31. Then you could compare it against the revision history to see exactly what your codebase looked like when your client's version was built.

For a while now I've wanted to do just this, and now I've finally figured out how to do it cross-platform. This post documents how I went about doing it, and how you can do it too.

The basic principle of the idea is to run a command that will output the latest commit hash to a file before the build starts, and then embed that file into the resulting binary. To achieve this, we need to go about it in 2 parts. Firstly, we need to fiddle with the project file to add an optional pre-build event. Open the project file (MyProject.csproj) in your favourite text editor (but preferably not your favourite IDE such as Visual Studio or MonoDevelop) and add this to the bottom, just before the closing </Project>:

<Target Name="BeforeBuild" BeforeTargets="Build">
<Exec Command="git rev-parse HEAD &gt;git-hash.txt" WorkingDirectory="$(ProjectDir)" IgnoreExitCode="true" /> </Target> If you don't use Git, then change git rev-parse HEAD &gt;git-hash.txt in the above to the equivalent command for your version control system. For SVN, this stackoverflow question looks like it'll do the job for Windows - for Linux you should go here. Once done, the next step is to add the generated file as an embedded resource. We can't do this with the GUI easily here since the file in question hasn't been generated yet! Add the following to the bottom of the csproj file, again just before the </Project>: <ItemGroup> <EmbeddedResource Include="git-hash.txt" /> </ItemGroup> Remember to change the git-hash.txt to whatever you changed it to above. Next, save it and reopen the solution in your IDE. The final step is to actually utilise the commit hash (or revision number in SVN) in your program. Since it's just an embedded file, you can simply find it with a bit of reflection, and read it in with a StreamReader. I've written a good tutorial on how to do that over on my Embedding files in C♯ binaries post. Make sure that your program is prepared to handle junk instead of a commit hash - you can't predict the contents of the embedded file if Git (or SVN) isn't installed on the machine used to build your project. If you want to require that the commit hash (or revision number) is actually present, just remove the IgnoreExitCode="true" from the first snippet above. Sources Use C♯ 6.0 today in Visual Studio 2013 (Banner from hdw.eweb4.com) In case you haven't heard, C♯ 6.0 is here now and it's awesome (here's a cheat sheet from programmingwithmosh.com showing the most noteable new features). Unfortunately, you must be using either Visual Studio 2015 or above or MonoDevelop in order to take advantage of it.... until now: Microsoft have released their C♯ 6.0 compiler Roslyn as a NuGet package. If you don't know what a NuGet package is, Nuget is a modular system that allows you to pull in and use various different libraries and tools automatically. There's a central registry over at nuget.org, which people (like you!) can upload their packages to and other people can download them from. This looks like a good tutorial for Windows users. MonoDevelop users need to install this addin, but it should be installed already. All you have to do is install the Microsoft.Net.Compilers NuGet package in order to use C♯ 6.0 in Visual Studio 2013. That's it! Unfortunately, this breaks the build process on platforms other than Windows, as the MicroSoft.Net.Compilers package is Windows only. The solution is fairly simple however. Once you've installed the above NuGet package, open your ".csproj" file in your favourite plain text editor (such as Notepad or gedit), and find the line that looks like this (it should be near the bottom): <Import Project="..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props')" /> And add AND '$(OS)' == 'Windows_NT' to the end of the Condition attribute like this:

  <Import Project="..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props') AND '\$(OS)' == 'Windows_NT'" />

The above adds a condition that prevents the compiler in NuGet package you installed from being used on platforms other than Windows. This doesn't mean that you can't use C♯ 6.0 on other platforms - Mono (the Linux c♯ compiler) already supports C♯ 6.0 natively, so it doesn't need to be replaced. it's just the C♯ compiler bundled with Visual Studio 2013 and below that's no good.

Splitting your C♯ Code into Multiple Files 2: DLLs

I have found out about compiling and linking to DLLs. I think this is called Dynamic Linking but again, I could be wrong.

We will be using the example files from last time:

filea.cs:

using System;

class ClassA
{
public static void Main()
{
Console.WriteLine("This is a test from file A");
Someplace.ClassB.PrintHello();
}
}

fileb.cs:

using System;

namespace Someplace
{
public class ClassB
{
public static void PrintHello()
{
Console.WriteLine("Another hello from file B!");
}
}
}

This is a 2 step process. First we need to compile the DLL, then we need to compile the main exe and link to the DLL.

To compile the DLL, you type something like this:

csc /target:library fileb.cs

The important bit here is /target:library. This tells the C♯ compiler to compile your code to a DLL and not and exe.

To compile the main exe, you need to type something like this:

csc /reference:fileb.dll filea.cs

This tells the C♯ compiler to compile the code in filea.cs into an exe, and link it to fileb.dll.

Taken from this MSDN page.

Splitting your C♯ Code into Multiple Files

I have just started to work out how to split my C♯ code into multiple files, and thought that I would share it with you. This post will be about what I believe to be static linking, but I could be wrong. Anyway, it is actually quite simple:

Here is the contents of filea.cs:

using System;

class ClassA
{
public static void Main()
{
Console.WriteLine("This is a test from file A");
Someplace.ClassB.PrintHello();
}
}

and here is the contents of fileb.cs:

using System;

namespace Someplace
{
class ClassB
{
public static void PrintHello()
{
Console.WriteLine("Another hello from file B!");
}
}
}

Then when you compile, you should do something like this:

csc filea.cs fileb.cs

This will tell the C Sharp compiler to grab both filea.cs and fileb.cs, and to output a single filea.exe.

Next I will try to figure out how to create a .dll file and include that - then I can build my own libraries.

Art by Mythdael