Jamie's Blog

Compiling C++/OpenGL on Windows with MSYS2

Tags: Programming

This guide was originally written for people taking the CS324 Computer Graphics course wishing to compile the Linux OpenGL lab code or their own coursework on a Windows machine. However, you may find it useful if you’re trying to build cross-platform OpenGL apps with C++ on Windows. The original PDF is available here, but this web version is easier to follow and features a few minor corrections and readability enhancements.

1. Introduction

There are two main ways to develop C++ applications on Windows. In this guide, we’re only going to look at one: shutting our eyes and pretending very hard that we’re using a unix-like system. We will compile code with a Windows port of GCC called MinGW, which provides its own independent C++ runtime. MinGW runs in a posix compatibility layer, provided by a collection of programs called msys2.

The other way is to use Microsoft’s own C++ runtime, which is distributed as part of the .NET framework, and will typically use their C++ compiler as shipped with the Visual Studio IDE and Visual C++. This is heavily discouraged, for two reasons: one, it is actually less convenient to set up than MinGW, with per-project settings buried in opaque Windows forms; and two, the final coursework requires you to submit a Makefile which compiles your code on the DCS machines, which will require additional porting effort on your part.

2. msys2

msys2 is a posix compatibility layer which provides a unix/Linux-like environment on Windows. This means that it gives you a command-line interface from which you can run specially-converted Linux programs, the most important of which is the MinGW C/C++ compiler. This option doesn’t permit the use of an IDE to compile your code (without some additional setup) but it does make setting up libraries quite simple.

This will give you three different shells (command line interfaces):

  • MinGW32
  • MinGW64
  • msys2

For our purposes, you probably want to run the MinGW64 shell and forget about the others.

Opening it, you should see something like this:

Figure 1: The MinGW64 Command Prompt
Figure 1: The MinGW64 Command Prompt

Now, we need to install some libraries and build-tools through the shell to get the CS324 labs working.

2.1 Pacman

msys2 uses a package manager called pacman, which has some simple commands.

If you want to install something, e.g. GLUT, you can search the package repository using the -Ss flag:

$ pacman -Ss glut

In this case, you will see an entry for both MinGW32 and MinGW64. You want to install (-S) the version corresponding to your shell (MinGW64):

$ pacman -S mingw-w64-x86_64-freeglut
Figure 2: Installing a package with Pacman
Figure 2: Installing a package with Pacman

Over time, you may need to update the local package list and your installed packages. To do so, you can use the -Sy and -Su flags:

$ pacman -Sy # update package list
$ pacman -Su # update installed packages
$ pacman -Syu # combine both operations

Finally, you may want to remove a package. To do this, use the -Rs flags:

$ pacman -Rs mingw-w64-x86_64-freeglut

2.2 Required Packages

You want to install the following programs with pacman:

base-devel # make, and other devtools
openssh # for copying files from joshua
unzip # for extracting the labs
mingw-w64-x86_64-gcc # 64 bit gcc, our C compiler

and libraries

mingw-w64-x86_64-freeglut # freeglut
mingw-w64-x86_64-glew # glew
mingw-w64-x86_64-libpng # png

You can combine this into one -S command:

$ pacman -S base-devel openssh unzip mingw-w64-x86_64-{gcc,freeglut,glew,libpng}

There are a number of other packages you may find useful, such as cmake, git, zsh, and glm (OpenGL Mathematics). To read about a command, e.g. gcc, you can run man gcc just as in Linux.

3. Compiling the CS324 Labs

3.1 Getting the Lab Files

Once you have everything installed, the next task is to compile the labs. Whether or not you intend to do the labs on your computer, this is a good test to see if everything is set up correctly. First, download the labs from the DCS network and extract them:

$ scp DCS_USERNAME@joshua.dcs.warwick.ac.uk:/modules/cs324/cs324-labs.zip .
$ unzip cs324-labs.zip

Note the . at the end of the first command! You can also use scp to copy files from your DCS home directory. For example, to transfer my personal copy of the labs, I can run

$ scp -r phulgm@joshua.dcs.warwick.ac.uk:~/cs324-labs my-cs324-labs

where phulgm is my DCS username. These files will be created in your msys2 home directory. If you want to access the files outside of the terminal, you can find them at C:\msys64\home\[windows username].

3.2 Changes to Makefiles

Now, you want to compile the labs. As msys2 emulates a unix-like system, you should compile with the Makefile.linux makefiles.

However, there are a few small changes required before this will compile. The OpenGL libraries used have slightly different names, and some libraries aren’t available. You can correct this yourself, but to speed up the process I’ve written a small script to do it for you. Navigate to the cs324-labs directory:

$ cd cs324-labs

and paste (Shift+Insert) this code directly into your MinGW64 terminal:

for f in */*.linux; do
    sed -i '
        s/lglut/lfreeglut/
        s/lGL/lopengl32/
        s/lGLU/lglu32/
        s/-lX11//
        s/lGLEW/lglew32/
        s|-L/modules/cs324/glew-1.11.0/lib||
        s|-L/usr/X11R6/lib||
        s|-I/modules/cs324/glew-1.11.0/include||
        /INCDIRS *= *$/d
        /LIBDIRS *= *$/d
        s/CPPFLAGS/CXXFLAGS/
        s/CXXFLAGS *=.*$/& -std=c++11/' $f
    rename .linux "" $f
done

The last line of the script renames Makefile.linux to Makefile for your convenience. Note that the instructions given in Lab 1 (Section 2.1 of the lab-script),

 $ ln -fs Makefile.linux Makefile

won’t work, as Windows does not support soft links.

You should now be able to compile the labs according to the instructions in the lab script:

$ cd lab-1
$ make simple
$ make double

You may need to delete the existing files simple and double before running make. Then, you can check that simple.exe and double.exe exist with the ls command, and run them just as on Linux:

$ ./simple

3.3 drand48 and srand48

As of the current set of labs (2015), there is a problem with labs 8 and 10 because they use the unix methods drand48 and srand48, which are not available on Windows. Attempting to compile the programs in these labs will result in the following error:

$ cd lab-8
$ make particles
g++ -O3 -std=c++11 -O3 -std=c++11 -std=c++11 particles.cpp -lfreeglut -lopengl32 -lglu32 -lm -o particles
particles.cpp: In function 'void make_particles(size_t)':
particles.cpp:238:20: error: 'srand48' was not declared in this scope
    srand48(time(NULL));
    ^
particles.cpp:246:32: error: 'drand48' was not declared in this scope
    float rand_r = float(drand48());
                         ^
<builtin>: recipe for target 'particles' failed
make: *** [particles] Error 1

To work around this, paste the following code after the #include blocks in the .cpp file (in this case, lab-8/particles.cpp):

#ifdef __WIN32__
#include <random>
void srand48(long) {};
double drand48() {
    static std::ranlux48 source(std::random_device{}());
    return std::uniform_real_distribution<double>(0,1)(source);
}
#endif

4 The CS324 Coursework

4.1 Building on Windows

For the coursework, you have to provide a Makefile to build your project. If you are unfamiliar with Makefiles, you can use the existing lab Makefiles as a skeleton. However, if you wish to split your code into many files, you can use this simple example as a skeleton instead (be careful to preserve indentation):

# the name of the executable created
PROGRAM_NAME = cs324_coursework

# Modify this variable as appropriate as you add .cpp files to your project
SRCS = main.cpp

# you shouldn't need to modify below here, but you can if you know what you're
# doing
CXXFLAGS= -O3 -std=c++11
LDFLAGS= $(CXXFLAGS) $(LIBDIRS) -std=c++11
LDLIBS = -lfreeglut -lopengl32 -lglu32 -lglew32 -lm
OBJS=$(SRCS:%.cpp=%.o)

default: $(PROGRAM_NAME)

$(PROGRAM_NAME): $(OBJS)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

clean:
    -@$(RM) $(OBJS) $(PROGRAM_NAME).exe

.PHONY: default clean

4.2 Converting for Linux

While you can develop on Windows, we require that your submission provides a Makefile which builds on Linux. If your Windows Makefile is called Makefile.windows, this script will create a file called Makefile.linux:

sed '
    s/lfreeglut/lglut/
    s/lopengl32/lGL/
    s/lglu32/lGLU/
    s/lglew32/lGLEW/
    s/LDLIBS *=.*$/& -lX11/
    s|LDFLAGS *=.*$|& -L/usr/X11R6/lib|
    s|LDFLAGS *=.*$|& -L/modules/cs324/glew-1.11.0/lib|
    s|LDFLAGS *=.*$|& -Wl,-rpath=/modules/cs324/glew-1.11.0/lib|
    s|CXXFLAGS *=.*$|& -I/modules/cs324/glew-1.11.0/include|
    s/\.exe *//
' Makefile.windows > Makefile.linux

To see if your coursework does indeed compile on Linux, you can transfer it to joshua and test it there:

$ scp -r my_coursework_folder DCS_USERNAME@joshua.dcs.warwick.ac.uk:~/remote_coursework
$ ssh DCS_USERNAME@joshua.dcs.warwick.ac.uk
$ cd remote_coursework
$ make -f Makefile.linux

5. Contact

If you have any problems, suggestions or corrections, please feel free to drop me an email at j.bayne@warwick.ac.uk.