For an introduction to my reasons for migrating from Windows to Linux, see my previous blog post. Here I will try to stick to my experience as a Linux beginner, and hopefully inspire other developers to try it out.
The first stage of course in migrating to Linux is to either install it on your PC, or try a 'live' version off e.g. a usb stick (or even try it on a virtual machine?). I can't say too much here, because I got my new PC with Linux Mint pre-installed, and there should be plenty of guides on google. I went for Mint because I had briefly tried Ubuntu a few years ago, and I liked the look of Mint and fancied a change. I knew it was based on Debian like Ubuntu so there should be lots of software.
My first stage after unplugging my windows machine was just to take baby steps to familiarize myself with it, without running away in fright. After plugging in my network cable, I was away with Firefox browser. But after a few minutes I decided to install Chrome, as I am a fan and used that on windows (going with familiar!! safe space!!). This entailed installing software.
On windows, the process of installing software usually involves downloading an installer package from the internet and running it, and hoping it likes your machine windows version / hardware / dependencies. You can do this on Linux too (particularly for cutting edge versions of software), but there is also a far easier way to do it, via a 'package manager'. The package manager is actually the pre-cursor to all the various 'app stores' that have become popular on Android and iOS, but the idea is simple, you have a searchable database of lots of software you can install, usually simply with a click. It also has the magic advantage that it has a very good system for automatically working out the dependencies required by any software, and installing those for you too in the background, or for finding conflicts (if these do occur, when I have rarely had conflicts it has been because I've been trying to do something nonsensical!).
I don't know whether it is my new machine, or linux, but the process of installation (and removal) is orders of magnitude faster than windows. It honestly only takes a couple of seconds for most of these installations. Anyway suffice to say I was very quickly running chrome, installing my favourite plugins, running my favourite websites.
Accessing Windows Hard Disks
The next stage was to get some of my data across from my old windows PC. This is where things get slightly interesting. Predictably enough, linux uses a different filesystem to windows, 'ext4' on my machine, whereas my windows external hard disk was formatted as NTFS. As is Microsoft's way (to discourage competitors, no doubt), NTFS is not public domain. The clever Linux devs have presumably reverse engineered much of NTFS, because you can mount and read from the NTFS disk. However, I am erring on the side of caution and not writing to NTFS for now, because from previous experience of exFAT on Android, it is possible that an incorrect write can bork the file system, and hence lose a LOT of work. My solution for now was to copy my working source code etc from the NTFS hard disk to my ext4 linux SSD. Longterm I intend to convert all my NTFS external hard drives to ext4. It would also presumably be useful if Windows could read from ext4 drives, but I don't know how easy this is as yet.
Great! I had some data on my new machine. I tried some movies and they worked great in the in-built player, and VLC (which I installed). Image files loaded fine in the in-built viewer and in 'the gimp', which is sort of like the linux photoshop. I've used the gimp a little on windows, and am hoping it can do a lot of the photoshop duties.
For 3d models, I've been using blender on windows, and as luck would have it, this open source software is available and runs very nicely on linux. Was installed and loading my game models in no time.
For development, this just left an IDE and compiler for c++ (my language of choice). Linux has a very handy standard compiler which is easy to install (g++ / gcc). This is where I might mention 'the terminal'.
Although the name windows has become synonymous with the windows GUI, it is important to realise that an operating system doesn't have to be irrevocably intertwined with a GUI system. In linux, the operating system can use several different GUIs, depending which flavour you prefer. Or none at all, if for example you are running a server. The way to talk to the operating system below the level of the GUI is a command line interface called 'the terminal'. There used to be one used commonly in windows too, the DOS prompt, but it is rarely used now. In contrast on Linux, the terminal is still very useful for a number of operations, unfortunately it can be a little scary for beginners but this is a little unjustified.
To get the terminal up I just press Alt-T. You can list what is in your current directory by typing 'ls'. You can navigate up a directory with 'cd ..'. And you can navigate into a directory with 'cd MyFolder'. It will also auto-complete the folder / filename if you press tab.
From the terminal you can do a lot of stuff you would also do from the graphical file manager (the excellent 'nemo' is built in to linux mint), such as copying, deleting, moving files. You can also manually tell it to install packages just like it would install from the package manager, with the command 'apt-get'. To install software, you need admin privileges (this is handy as it prevents malware from doing anything naughty without you typing in the admin password). To get admin you type 'sudo' before the command:
sudo apt-get install build-essential
This tells it to run as admin (sudo) to run apt-get, and install (or remove) the package called 'build-essential'. This contains the compiler and other building tools.
Unless you fancy yourself as a hardcore compile from the terminal from the getgo type of guy, you will also probably want to use an IDE for development. As I use C++, there are several to choose from, such as Eclipse, Code::Blocks, KDevelop, Code Lite etc. I went for QT creator, as I have used it on windows (again, familiarity!! baby steps!!).
Once QT creator was installed, it was fairly easy to tell it to create a hello world app and test it, it worked great!
This is where things got slightly more interesting. My current project is an Android game. I had been maintaining both a PC build on windows, and the Android build, with the platform specific stuff isolated into things like creating a windows, setting up OpenGL, input, and low level sound.
Where things got slightly confusing is that because I am developing for Android, I was using OpenGL ES 2.0, rather than the desktop version of OpenGL. On windows I had been using the ARM Mali OpenGL ES Emulator, which emulates OpenGL ES by outputting a bunch of normal OpenGL calls for each ES call. I was anticipating having to use something similar on linux, so I attempted to install the Mali emulator in Linux, however I had little joy.
I was getting conflicts with existing OpenGL libraries used in SDL (which I intended to use for platform specific stuff). Finally after investigation I realised that my assumptions were wrong, and Linux actually directly supports OpenGL ES AS WELL as desktop OpenGL, through the open source Mesa drivers. I eventually got a 'hello world' OpenGL ES program working, and was convinced I now had the necessary libraries to start work.
64 Bit Conversion
The next stumbling block was a biggie. For historical reasons, all my libraries and game code were 32 bit. I had been developing with the idea that a lot of Android devices were 32 bit, and I was hoping the 64 bit devices would run the 32 bit code (hadn't really tested this out lol). So I had been previously compiling a 32 bit windows version, and a 32 bit android version. And it soon became clear that my linux setup was compiling by default to 64 bit.
No problem I thought, I should be able to cross compile. With some quick research I managed to get 32 versions of the libraries, however I had no joy with 32 bit version of OpenGL. It refused to install, and being a linux beginner I was stuck. I did some little research, but no simple path, and realised that maybe it was time to convert my code to 64 bit. Or rather, to have my code run in 32 bit and 64 bit.
I had been (rather unjustifiably) dreading this, as I have a lot of library code written over quite a few years. As it happened, aside from some changes to my template library, the biggest problem was in the use of 'fixup' 32 pointers in flat binary files formats. I have been using this technique for a long time now as it greatly speeds file loading, and also helps prevent memory fragmentation.
Essentially the idea with a 'fixup' pointer is you store into the file an 'offset' from a fixed point in the file to a resource, often the start, because there is no point in saving a real pointer to a file as it points to a (changeable) memory location. Then you can load the entire binary file as one big block, and on loading 'fixup' the offset pointer to a real pointer by adding e.g. the offset to the memory location of the start of the file in memory.
This works great when the offsets are 32 bit and your pointers are 32 bit. But when you move to 64 bit, your offsets are fine (as long as the file is smaller than 4gb), but there is not enough room to store a 64 bit pointer. So you have a choice, you can either do some pointer arithmetic on the fly, or change your file formats to use 64 bit offsets / pointers.
After a trial with the first method, I have eventually settled on going with 64 bit in the file, even if it uses a little more space. Of course the disadvantage is that it has meant I have needed to re-export all my assets. So at the same time as converting my libraries to 64 bit, the game code, I also needed to convert my exporters to 64 bit, and re-export all the assets (models, sprites, sound etc).
This has been a frustrating big job, particularly because you are coding 'blind'. Normally when you program you will change a little bit, recompile, run and test. But with such a conversion, I had to convert *everything* before I could test any of it.
It has been demoralizing doing the conversion, I won't lie. But I have been so impressed with the operating system I was determined to make it work. And finally bit by bit I got the exporters working, re-exported, then the game, debugged. Got some crazy graphical errors, errors in the shaders that the OpenGL ES implementation didn't like (that's a whole other story!) but finally got it displaying the graphics, then did an SDL version of the sound this afternoon which is working great.
One thing I will say is I should have been using SDL before, it is really simple and makes a whole lot of sense of taking out the eccentricity of setup code on different platforms (windows in particular is very messy).
So to summarize I now have (nearly) everything working, compiling and running on linux. I still have to install android studio and try debugging an android hardware device through usb but I'm very hopeful that will work. Even if it doesn't it's not a show stopper as I can always use a second PC. I am gradually becoming more familiar with linux every day and even feeling I might get tempted to learn QT so I can do some nice 'native' looking apps.