Skip to content
MatthewForrester edited this page Oct 13, 2020 · 9 revisions

This page documents the Simutrans Makefile. It starts from first principles because I have only just learned most of this myself, so it may be helpful to correct errors in my understanding.

What is a Makefile and why is it needed?

The Simutrans source code is turned into a playable executable by special programs called a compiler and a linker. For the time being, we will just call them a compiler. You can think of it like cooking: you start with indigestible raw ingredients and turn them into something delicious.

If you use Microsoft Windows and do things the Microsoft way, then your source code editing, compilation, and linking is all done within Microsoft Visual Studio. In theory, it's as simple as clicking 'Compile'. Visual Studio already has your source code, it assumes that your executable will be used in Windows, and it knows exactly how Windows works. It's all very straightforward. (Of course, in practice, it's not straightforward at all, but this straw man is a useful contrast with what follows).

The Unix philosophy is 'one tool does one job' so the multiple roles performed by Visual Studio are split between multiple programs. In the Linux world, the standard compilers have traditionally been provided by the GNU project (hence the term 'GNU/Linux'). As Simutrans is a C++ program it requires GNU's C++ compiler (g++), its C compiler (gcc), and its linker; like most people we will refer to all three parts working together as GCC.

In contrast to Visual Studio, GCC does not know where your source code is. It also does not know where you want your executable to be used: you can use GCC to compile Simutrans for Linux, MacOS, Windows, and other more exotic platforms too. And it has limited information about those platforms and indeed about the platform that it is running on itself. So we can't just ask GCC to compile Simutrans. We must use a program called make to supply GCC with the information that it needs.

Let's review that using the cooking analogy. GCC is like the stove: it performs the magic of making the food edible. But you can't just put raw steak into a stove and wait. And a stove will happily let you roast pasta for ten minutes or boil prime steak for two hours, even though the results will be useless. The chef needs to put the right ingredients in the right part of the stove for the right amount of time at the right temperature. We can think of make as the chef.

This fits with the Unix philosophy: GCC's job is compilation and make's job is giving GCC the information is needs. But it just pushes the problem back a level, because make doesn't have that information either!

It is possible to provide that information by running make with a long series of parameters. In practice, this is only done for parameters that are specific to my particular computer, rather than the platform. For example, I often build Simutrans using this command:

"make -j2 2>20201011.log" at the command line

The parameter -j2 tells make to compile Simutrans using two CPU cores, because two are faster than one, but leaves other cores for playing K-pop tracks; you may want to use your cores differently. 2>20201011.log tells make to record any error messages in that file; you may want a different file name. And the fact that I'm running make in /mnt/garden/Git simutrans-extended is a clue that the source files are there (though this is not always true); I am probably the only person in the world who 'cooks' Simutrans in a 'garden'. 😂 We can see that all these parameters are personal to me.

But a lot of the information that make needs is going to be the same for everybody who (for example) compiles Simutrans for MacOS, so instead of typing in all the parameters every time, they can be stored in a 'makefile'. This gives make the essential information about the different platforms that Simutrans can be run on as well as some information about the platform that make is itself running on. Makefiles were designed using the metaphor of a cookbook with different recipes. They tell the chef (make) where to find the ingredients and how to cook (compile and link) them. The first place make looks for its cookbook is always a file called Makefile (with a capital M) and Simutrans follows this convention. It's also possible to use makefiles with different names (traditionally ending in .mk). Simutrans uses these too (I am not certain why, but I suspect that it's related to Autotools).

But the Makefile on its own is not enough, because make still doesn't know which of those platforms you want this particular executable to run on: the 'target' platform. You need to tell the chef what you want to eat for dinner (OK, no more culinary references in this section!). This

Todo

  • Understand how config.* files interact with the Makefile (relevant SE answer)
  • Understand how CFG= environment variable interacts with the Makefile
  • Work out whether the two above points apply to all makefile or are Simutrans idiosyncrasies
  • Annotate the Makefile line-by-line so that I understand what it's doing
  • Has Standard dropped BeOS support? If so, then Extended can too.
  • New page documenting Github Actions?