How I support Windows, Mac and Linux

10th Jan 2019 12:03 GMT - I just wanted to write a positive article that might help others. So please don’t use this post as a stick to beat others. It’s a complex issue of dev experience, team size and frankly money. We’re all just trying to make great games - dazza.

So as usual there is some controversy about supporting Linux (and macOS for that matter) if you’re a game dev. I am a game dev and our current game Smith and Winston support Windows, Linux and macOS. So how do I as a lone coder in a team of two support three platforms and is it all easy and free?

How?

Custom Code

Firstly we use a custom engine and this makes it harder but also better. Here is a blog about how I assemble the engine. I’m sure it is a lot ‘easier’ to just use Unity, Unreal, Godot or any of the other engines out there. The easy path is not necessarily the most fun or rewarding path to travel though.

The upside of custom code is that I basically build upon the best for me, my game and my customers. libSDL2 is fantastic and takes 90% of the pain away from platform support. BGFX is an amazing library for rendering, written by someone who clearly knows about cross platform support and is dedicated to producing quality code.

Custom code gives me the maximum chance of being able to debug a platform specific issue. Not only is the source code available but because I integrated it I know how it works. I hate the idea that I would have to say to a customer that “I can’t fix that issue because there is a bug in Unity/Unreal that I can’t fix and will never really know when it’s going to be fixed”. This is a matter of professional due diligence. Of course there are hidden corners of all the libraries I use so I can’t guarantee anything but I at least have a fighting chance.

From day one I intended to support multiple platforms. I didn’t code for all of them from day one but I knew that where ever I touched the OS I was going to need to think about platform differences. Common areas are files, file paths, rendering, threading, sound, date and time and localisation. You just need to think about it. If you didn’t compile it then you may need to wrap it in a cross platform API.

Machines and VMs

I dedicate hardware to building and testing macOS, Windows and Linux.

I have a machine dedicated to building the engine and game datasets on all platforms in all configurations all the time. It has many VMs running. It just sits there waiting for new code to be added and the opportunity to make me look stupid. It emails me with build errors and warnings. I hate that machine. Here are the configurations it builds:

  • Windows
  • Windows + Oculus
  • Windows + Steam
  • Windows + Steam + Oculus
  • Linux
  • Linux + Steam
  • macOS
  • macOS + Steam
  • FreeBSD
  • (consoles I can’t talk about)

all of them in debug, release and profiling configurations. So that’s 27 targets I can talk about. While it’s only really four platforms each of the sub-platforms offer opportunities for me to break things. If you make finding these faults easy and fast then you’re much more likely to fix them early and quickly.

This means I am totally relaxed about macOS and Linux as platforms. There are no surprises for me when it comes to testing and deployment. I use a custom python build system that constantly loops through (checkout, cmake/premake/GENie, build, report). It’s only a few thousand lines of code but it’s saved me many hours by catching code that breaks a platform I am not working on.

I also rotate my primary development platform spending time in Windows, macOS and Linux. This means I know the platforms and tools well.

I’m old

I’ve been writing games and engines for 30+ years so none of this is new, I have a lot of experience. But you only get the experience by doing it and not making excuses.

Separation of game and engine logic

Our engine uses Lua for game logic and C++ for the runtime code. This separation means we can focus our testing depending on what has changed between releases. Mostly the engine stays the same so we can focus on testing the actual elements of the game and the few bug fixes the engine gets.

Why?

Moral Argument

There are a lot of good things to say about Microsoft. Monopolies are not good for anyone though. While you can’t break a monopoly on your own you can play your small part. Microsoft is an infinitely better company now than they were 10 years ago because they’ve had a few bloody noses. Let’s hope someone does the same to Google and Facebook pretty soon. So by supporting the minor platforms you are making the major platform better.

Quality Argument

By forcing the game through different compilers (Visual C++, Clang and GCC) you find different code bugs (leave the warnings on max). By forcing the runtime to use different memory allocators, threading libraries and rendering technologies you find different runtime bugs. This makes your code way more stable on every platform. Even if you never deploy your code to a non windows platform just running it on Linux or macOS will expose crashes instantly that rarely appear on Windows. So delivering a quality product on the dominant platform is easier if your support the minor platforms as well.

Porting argument

Starting with Windows, Linux and macOS makes porting to XBox One, PS4 and Switch a LOT easier. There will be a clear separation between common and platform specific. Maybe you’ll never port to those platforms but if you do you’ll be ready.

Is it free?

Hell no. But if it were free it probably wouldn’t be worth doing. Machines take time to maintain, they cost money to run and purchase. Certainly macOS is an expensive platform to buy in to with it’s low end machines being expensive and very low end.

Over time there is a cost as well. With the transition from DX11 to DX12 and OpenGL to Vulkan I need to manage that. Unity and Unreal will ‘hopefully’ make this completely transparent to their users (but I doubt it). macOS moves pretty slowly but it routinely drops features where as Windows has only recently dropped some DOS features! This needs to be factored in to the long term maintenance costs of an engine and game.

Do you make your money back? It’s hard to say definitely which could mean no. Linux and macOS sales are low so the direct rewards are also low. However this needs to be weighed up against the increase in quality of the engine. For Smith and Winston right now I don’t think it’s been worth it financially (but it will probably make it’s money back on Launch), but mentally (peace of mind), morally and quality wise it’s been more than worth it.

Fanboy!

I am not a Linux fan boy. In fact I use FreeBSD, recommend FreeBSD and am a total FreeBSD fan boy. I’ll probably never ship a game on FreeBSD because that’s just not what it is for. Linux is however a desktop OS and a pretty good one so I see no reason not to support it.

Conclusion

People will tell you it’s not worth supporting the minor desktop OSes. My argument is that by doing it you will create a better quality product on the major OSes saving you money in testing and bug fixing for the majority of your users. I have nothing other than 25 years of commercial experience making games to back up this statement so feel free to ignore it.

Happy new year and good luck in what ever you decide to do.