Setting up cMake with minGW on Windows
I develop mostly in safety of Visual Studio or Visual Studio Code. And in .NET. Only recently, I rediscovered passion for C++. The speed, the elegance, numerous hours thrown into the thin air trying to find a solution to a simple problem, that somehow is just notoriously difficult in C++… You get the gist of it.
Visual Studio is a wonderful IDE. Mind you, due to it’s heavy weight and feature-rich nature, my development process was always limited to my desktop PC. And the same lately goes for Visual Studio Code. Even though, majority of my work and side-projects is done on desktop PCs, I do want to sometimes work on stuff, while I am nowhere near my home and my PC. For those situations I own an entry level Surface Go 2 with some really really shoddy hardware. It kind of holds it’s own for browsing and remoting to a work PC, if there is an emergency, but installing Visual Studio or Visual Studio Code on it is out of the question as there is not nearly enough diskspace, CPU power or memory for that.
I did think to crate a VM on my home lab server to run Windows and mentioned IDE, but I really don’t want to waste so much resources just to use it occasionally. Plus, I don’t like to expose my home network to outside incoming traffic.
But, I don’t need a full fledged IDE to develop stuff. I mean, it is a nice feature to have, but realistically, all you need is something with basic highlighting and formatting and a decent compiler. I cannot imagine this tablet to compile anything dotnet related in reasonable amount of time, however, it should be totally fine compiling C++ code. I mean, if C++ and C code compile reasonably fast on my Pi Zero 2W…
Hence, I went with Notepad++ as my editor, MinGW as compiler and cMake as build tool. And I lost a day just trying to build a Hello World project. I never used MinGW or cMake, but I heard good things about them from nice folk of the internets.
MinGW
Installing MinGW is a piece of cake. I just typed MinGW in my favorite search engine, clicked first link and downloaded it from SourceForge. It was only after several hours of trying to make cMake cooperate with MinGW, that I noticed, my version of MinGW is totally wrong. You see, MinGW is stuck at version 6.x and is not maintained anymore. In order to get latest and greatest features, what you really need is MinGW-64. So I removed old MinGW and went to the page, looking for install package. Except, binaries on Github are not latest and greatest and, according to VirusTotal page, contain a trojan. Hence, I went the way, VS Code page recommends. Installing MySYS2 first and then use pacman to install MinGW-64.
cMake
For those who do not know what cMake is, it is basically a tool that helps you generate make files and build your project using your desired compiler. It supports wide variety of compilers including VC++ and MinGW.
Installing cMake was way easier. I downloaded and installed a package from projects official site. Simple enough. The problem with cMake though, is that it has some steep learning curve and subpar documentation. Specially, if you are a beginner, you will lose numerous hours, for simple tasks that could be explained in one code snippet.
How cMake works in a nutshell is, you need a CMakeLists.txt file in your source directory. That file tells cMake, what should compile, using what compiler and linker and which libraries should include and whatnot. Of course, to make it a tad more interesting, you must use cMake scripting syntax. Have I mentioned, their documentation is really subpar?
Putting it all together
For demo purposes, I created a simple Hello World program in C++. I named the file main.cpp, as that is how you named main CPP file when I started to learn the language. You can name it foo.cpp, if you like.
#include <stdio.h>
int main()
{
fprintf(stdout, "Hello World!\n");
return 0;
}
Next to that file I created a file named CMakeLists.txt with following contents. The name cannot be foo.txt in this case, as far as I know.
# Minimum cMake version for build process
cmake_minimum_required(VERSION 3.28)
# I set PROJECT_NAME variable to example1
set(PROJECT_NAME example1)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Define project and tell cMake it is a C/C++ project
project(${PROJECT_NAME} CXX)
# Set different output directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin")
# Get all source files recursively and store it into SOURCES variable
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "*.cpp")
# Add the executable with all found sources in SOURCES
add_executable(${PROJECT_NAME} ${SOURCES})
As far as I know, that is the most minimalistic cMake script you need to compile a simple program.
To create a Makefile, I created a new directory named “build”, because I am weird that way and believe that build scripts have nothing to do with my source code. In command line, I went to that “build” directory and ran:
cmake .. -G "MinGW Makefiles"
Command tells cMake to take parent directory (“..”), search for CMakeLists.txt file and use “MinGW Makefiles” generator to generate Makefile. And it did just that. And some other files it needs to compile the project.
To compile my very interesting project, I needed to then run:
cmake --build .
And voila! About 30s later (my tablet is not THAT great) binary named “bin\example1.exe” has been built and outputs “Hello World!” as expected.