C++ Development Environments


1. Introduction

Since this is a 3000-level course, I do not prescribe a particular development environment, instead I want you to decide for yourself which environment you would like to use. However, C++ development environments are often large and complex, and it is easy to spend a lot of time learning them and working (i.e., fighting) with them. Thus, I will recommend certain development environments listed below, and I will try to support all of them, although to various degrees.

There is value in using multiple C++ compilers (and multiple development environments) on your programs. Different compilers provide different warnings; writing code that is warning free for multiple compilation systems can improve your code's quality considerably. Also, different compilers have different quirks and deficiencies. Writing code that works with many compilers helps you to stay clear of the darker corners of the language. Finally, the standard allows for different compilers to behave differently in certain respects. A program that avoids "implementation defined" and "unspecified" behavior may be more stable and more robust overall. It will certainly be more portable.

Lemuria

Since I will be using g++ on Lemuria to evaluate your programs, you will need, at a minimum, to test your work on that system. It makes sense, therefore, to consider using Lemuria as your development environment. However, since Lemuria access is via an SSH connection using a text-mode terminal, no graphical development environment is available there. Instead, you'll need to use a plain text editor (with a text-only interface) and invoke the compiler directly by typing commands (we will actually be using the make utility to build our programs, but it's the same idea).

The experience of using a plain text editor and running the compiler by hand may seem tedious, archaic, and inefficient. However, as with many things, it is not as bad as it might first appear once you get used to the environment and how to manage it. There are also good reasons for getting comfortable with such an environment.

  1. Sometimes it is the only environment available to you. For example, if you are remotely accessing the development system and have no GUI to work with. This describes Lemuria's case, and it isn't unique.

  2. It can be faster in some situations. The processing power required to run a simple text editor is vastly less than that required for a large development environment. This makes certain operations more efficient than when done with a more complex environment.

  3. It can work even on a slow and limited machine. We all like having powerful computers as workstations, but there are times when that isn't feasible. Trying to run a complex development environment on an under-powered computer is torture.

It is good to become comfortable with the simple editor+compiler environment so that when such an environment is the only one available, you are still able to be productive.

Text Editors

On Lemuria I recommend that you use one of three text editors:

There is a playful rivalry between Emacs users and Vim users as to which editor is the best. Both are good. However, they work very differently. Emacs uses many obscure control character sequences as commands. Vim is a moded editor; you must switch back and forth between "command mode" and "insert mode" as you use it. In both cases you can do your editing without touching the mouse or even lifting your hands from the home position on the keyboard, which is why they can be very fast.

You will find Nano quick and easy to use. However, I invite you to consider taking the plunge and really learning either Emacs of Vim (pick one). Install the editor of your choice on all your systems and start using it for all your editing needs. It will be excruciating at first, but by the end of the semester you might be surprised to find that you like it!

Session Management

What you want to avoid doing is this:

All text editors suitable for programming allow you to load multiple files at once and switch between them. This includes Nano, Emacs, and Vim. Spend the time to find out how that works for your editor. If you are starting your editor for each file you want to edit, you are definitely not doing things the right way.

You also want to avoid this:

There are several ways to avoid this tedious process. I will describe them in order from the simplest to the fanciest. All the methods below can work well, however.

  1. You can create multiple SSH sessions with Lemuria and log into Lemuria in each session. Run your editor in one session and keep the other session open for compiling and testing your program. When you want to try compiling, save your changes in the editor without exiting the editor, then switch to the other SSH session to run the compiler. This also allows you to keep the error messages in view (with their line numbers) while you fix the errors in the other SSH window.

  2. Use job control. You can suspend the foreground process, such as your text editor, using ^Z. This does not terminate your editor, it only pushes it into the background in a suspended (non-executing) state. You can then issue commands to compile your program. When you want your editor back, use the fg command to return it to the foreground.

    This procedure is similar to the first one except that it only requires a single SSH session and doesn't require that you manage multiple windows. Do a Google search for "linux job control" to find links to tutorials on the details of how to do this.

  3. Use the features of your editor. Both Emacs and Vim (I'm not sure about Nano) have the ability to launch the make utility from inside the editor. They can show you the error messages produced in a separate pane and even jump to the location of those errors in your source files (in a very IDE-like manner). You can execute arbitrary programs while staying inside those editors, so you can even test your program without leaving the editing environment.

  4. Use tmux. This is a terminal multiplexer utility that is installed on Lemuria. It allows you to create multiple pseudo-terminals with the output of each displayed in separate panes of a single SSH session window. Tmux also allows you to create multiple virtual "windows" each holding a collection of one or more pseudo-terminals. Although only one virtual window at a time can be displayed in a single SSH session window, the other virtual windows (and their associated pseudo-terminals) are still active. Tmux allows you to detach from a window, log out, return at a later time, and then reattach to the same window. This lets you start a long-running process on Lemuria without having to sit by the SSH session the entire time waiting for it to end before you can leave.

You should familiarize yourself with one of these methods for session management to make your experience using Lemuria easier and more productive. Perhaps you believe that using Lemuria as a development environment would be too difficult. But if you are unfamiliar with the powerful editors and session management tools available there, you may be trying to use a needlessly inefficient workflow.

Cygwin

This section is only relevant if you are using Windows! Also note that Visual Studio (as opposed to Visual Studio Code) and CodeBlocks both come with a C++ compiler.

Several of the development environments that I describe (Visual Studio Code, Eclipse, and CLion) need to have a compiler separately installed. On Windows, it is often convenient to use the Cygwin environment for that purpose. You can install into Cygwin one or more of gcc, g++, clang, and clang++, in addition to many other development tools and libraries.

Cygwin is a Unix-like environment for Windows. It is important to understand that Cygwin is not a virtualization of Linux or any other Unix-like system. Cygwin programs are perfectly ordinary Windows executables. However, they make use of a dynamic link library that provides the Unix API on your Windows system. Thus, the Cygwin environment can compile many Unix programs directly, which then work in a Unix-like manner. In effect, the system behaves as if you are using Unix.

Start by going to the Cygwin home page and downloading the Cygwin installer. The base installation is quite minimal. You will need to explicitly add the g++ compiler (or whichever other compiler(s) you want). You should also add the make utility, and the gdb debugger as well.

It is important to add the Cygwin bin folder, typically C:/cygwin64/bin to the end of your user account's PATH. This allows the Cygwin programs to be found in an ordinary Windows console. You may want to log out and then log back on to be sure the PATH changes take effect. (Is this really necessary?)

Visual Studio Code on Windows, Mac, or Linux

Visual Studio Code is a cross-platform power editor from Microsoft. It provides advanced editing support for many languages. It requires that you install a C++ compiler separately.

One appeal of VSCode is that it supports Windows, macOS, and Linux. On Windows, it is helpful (and more consistent) to set up Visual Studio code to work with Cygwin. Steven Zeil at Old Dominion University has written a nice description of how to set up VSCode to work with Cygwin.

In addition to the VSCode extensions mentioned by Steven Zeil, I suggest the following:

When working on a C++ project with Visual Studio Code, you will want to set up an appropriate IntelliSense configuration that reflects your build environment. This allows VSCode to correctly draw the red squiggles under problems it finds in your code.

In VSCode, open the command palette and search for the command "C/C++: Edit Configurations (UI)." In the form that appears, fill in the various fields appropriately. Alternatively (and equivalently) you can copy the following material into a file named c_cpp_properties.json in the .vscode folder off the root of your project folder:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/g++",
            "cStandard": "c99",
            "cppStandard": "c++20",
            "intelliSenseMode": "linux-gcc-x64",
        },
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c99",
            "cppStandard": "c++20",
            "intelliSenseMode": "macos-clang-arm64",
        },
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.19041.0",
            "compilerPath": "C:/cygwin64/bin/g++.exe",
            "cStandard": "c99",
            "cppStandard": "c++20",
            "intelliSenseMode": "linux-gcc-x64",
       }
    ],
    "version": 4
}

You may already have this information in that file, or you may have other information in that file. Be careful to merge the information above appropriately. Note that the above shows IntelliSense configurations for all three platforms: Linux, Mac, and Windows. If you are only using one platform, the other configurations are not necessary. The names "Linux," "Mac," and "Win32" are special; VSCode should auto-select the right configuration based on the OS you are using. If, for some reason, VSCode is using the wrong configuration, you can click on the configuration name (right-hand side of the status bar at the bottom of the screen), and select the correct one from the pop-up menu.

Debugging in Visual Studio Code

There are a couple of different ways one might configure C/C++ debugging in Visual Studio Code. This can be confusing as the instructions relevant for one approach are not applicable, and sometimes even incompatible with, the instructions relevant for another approach.

In this class, we are using Makefiles to build our programs. This means you should use the command "Makefile: Debug the selected binary target" from the command palette. The first time you use this command, it will ask you which target you want to debug. The command will then build ALL using make before launching the debugger.

Information about the debugging configuration is put into the settings.json file in your project's .vscode folder. It is fairly easy to edit that file later to adjust the settings.

Note that this approach means you are not using the debugging features built into the C/C++ extension. Instead, you are using the debugging features built into the Makefile Tools extension. If you search online for information about debugging C++ in VSCode, be careful: a lot of what you will find pertains to the C/C++ extension and is not relevant for Makefile users such as us.

Eclipse/CDT on Windows, Mac, or Linux

Eclipse is a powerful IDE framework from which, with the help of plugins, many different IDEs can be created. The Eclipse ecosystem contains a large number of plugins allowing for many different kinds of development to be done. For our purposes, we are interested in the CDT (C Development Tools) plugin. Despite the name, it also includes support for C++.

Start by downloading the Eclipse installation from the Eclipse home page. As a convenience, Eclipse comes pre-packaged with many different combinations of plugins. When you run the installer, you will be able to choose which package you want. The C/C++ development package is your best choice for this class, but any package that contains the CDT should work (for example, "Eclipse for Scientific Computing" also contains the CDT).

The Eclipse installer puts your selected package into an eclipse folder in your home location. It installs the package into a package-specific subfolder, so it is possible to install multiple Eclipse packages without a conflict. If you want to explore some of the other packages available, for example for web development, feel free.

When you first run Eclipse, it asks you for a workspace. Eclipse workspaces are containers for projects. I recommend that you create a workspace specifically for this class. You can create multiple workspaces at different locations on your system as you desire.

When you want to create a project, you can either create an empty project or you can create a project based on some existing code. The code does not need to be in your workspace, but could be elsewhere on your system (in fact, it is not recommended that you commit the Eclipse workspace folder to version control... but you might want to commit your projects to version control). When creating a project, specify a "Makefile project." Such projects are controlled by a Makefile in the usual way.

If you are a Windows user, you will need to have Cygwin installed. Eclipse should automatically find your Cygwin version of g++ without any additional help from you. However, you can specify to Eclipse the location of the compiler if necessary. Note that on Windows you are using Eclipse to build Cygwin executables. They won't run without the Cygwin dynamic link library in the path. You may need to run them inside a Cygwin shell. However, if you've adjusted your path to include the Cygwin bin directory, as you should do, the executables should be able to find the dynamic link library without any extra help.

Here is an ancient page about Eclipse v4.2.

CLion on Windows, Mac, or Linux

JetBrains has a C/C++ IDE called CLion that also supports all three platforms of interest. However, CLion is a commercial product that normally requires a commercial license; there is no community edition. However, as a student, you can get an educational license from JetBrains that allows you to use all of their commercial tools free of charge for as long as you remain a student (you need to renew the license annually).

Proceed as follows:

  1. Apply for an educational license from JetBrains by following the instructions on the linked page. You will need to create a JetBrains account to do this (creating the account is free). Be sure to use your school email address that ends with .edu.

  2. Download and install the JetBrains Toolbox application for your platform. Windows, macOS, and Linux are all supported. You can log into the toolbox application with your JetBrains account. This application makes it easy to install and update any of the JetBrains IDEs. Your educational license allows you to use all of their commercial tools, not just CLion.

  3. Once the toolbox application is installed, use it to install CLion. You can launch CLion from the toolbox application as well. When it first launches, it will ask about license information. Provide your JetBrains account credentials and tell the tool to access your license online.

CLion defaults to using the CMake meta-build system. CMake creates build control files for various development environments, including GNU Makefiles, from a single primary source. While powerful, we are not using CMake for this course. It is possible, however, to open a Makefile in CLion and say that you want to use it as the build system. CLion will then configure the project as a "Makefile project." Note also that CLion does not come with a compiler. It can use a natively installed g++, however, either on a Unix-like system or via Cygwin on Windows.

Visual Studio on Windows

Visual Studio is Microsoft's flagship development environment. The Community Edition can be freely used for personal projects and by small teams. It comes with the Visual C++ compiler. It supports programming in all of Microsoft's languages (C, C++, and .NET languages), as well as database development and web development. As a result, it is quite large, complex, and heavy-weight. However, experience with Visual Studio is a valuable skill, so learning your way around the system is worthwhile.

Start by going to the Visual Studio web site and downloading the Community Edition. The C/C++ development tools are not necessarily installed by default, so you may have to select them during the installation procedure.

Visual Studio organizes code in "projects." Multiple projects are gathered into "solutions." The projects in a solution can be of different types: C++ program, SQL project, C# project, etc. Even simple programs follow this organization. It is common for student projects to be the only project in a solution with the same name. This duplication of names for the project and solution can be confusing to novice users. Keep in mind that the tool is optimized for large teams where a single "solution" might contain dozens of projects.

Although Visual Studio is a great development environment, it has two problems for this class:

  1. It is only available for Windows (yes, there is a macOS version, but that version only supports .NET development).

  2. It doesn't use GNU Makefiles (to my knowledge). If you want to use Visual Studio for this class, you would have to create a Makefile separately so that your program can be built with make on Lemuria.

If you see yourself as a Windows developer in the future, you will definitely want to experiment with Visual Studio at some point. However, I can't recommend it as a primary development environment for this class because of the issues above. I do intend to demonstrate it at some point during lecture, however.

Here is an ancient page about Visual Studio 2005.

Code::Blocks on Windows or Linux

Code::Blocks is a relatively lightweight IDE that still contains a rich collection of features. It thus sits in a "sweet spot" between using a plain text editor, on one hand, and a large, heavy-weight IDE such as Visual Studio on the other. It is also 100% open source.

Code::Blocks can be configured to use a C++ compiler that you already have installed. A fairly long list of compilers is supported. In particular, Code::Blocks supports g++ and clang++, as well as many others (even Open Watcom). However, you can also download Code::Blocks (for Windows) with a bundled version of gcc/g++ making it a stand-alone development environment.

On Linux, you can likely install CodeBlocks using your distribution's package installer. On Windows, start by going to the CodeBlocks homepage to download the latest binary version (version 20.03 at the time of this writing). Several different installers are provided. Consider the one that contains the bundled version of gcc/g++ based on MinGW ("minimum GNU for Windows"), unless you specifically want to use CodeBlocks with a compiler you already have installed.

Be aware that the 20.03 version, while the latest, is not particularly recent. The bundled version of gcc/g++ has weak C++ 2020 support. In particular, instead of using -std=c++20, you need to use the older -std=c++2a compiler option to turn on what C++ 2020 support the compiler does have. This is because at the time the bundled compiler was written, C++ 2020 was so immature that it wasn't known when it would be released!

However, for many of the programs we'll be working on in this class -std=c++17 should be fine, and that is supported. Also, you can configure Code::Blocks to use a more recent g++ from Cygwin.

After installation, you may need to adjust the paths to the compiler. Go to "Settings-> Compiler-> Toolchain executables" and verify that the "Compiler's installation directory" is correct and that the names of the various programs are actually in that directory. I had a situation where, for some reason, Code::Blocks wanted to use the 32-bit compilers, but none where installed. Just changing the names in this dialog box fixed the problem. Also, if you have Cygwin installed, you may find that Code::Blocks is using the Cygwin folder even for the generic "GCC" compiler. Change the folder to C:\Program Files\CodeBlocks\MinGW if you want to use the bundled compiler (or just let Code::Blocks use the Cygwin compiler!).

Code::Blocks organizes programs in "projects" where multiple projects can be collected into a "workspace." It is possible to create multiple workspaces. Each project has multiple targets; typically there is a "Release" target that is compiled with optimization, and a "Debug" target that is compiled with debugging information. You can define additional targets. I will demonstrate some of the details of how to use Code::Blocks in class.

Although I like Code::Blocks, I'm not recommending it for this class because the bundled C++ compiler is too old and will cause problems for you in relation to certain assignments. Installing and using Cygwin could work around this, however. Also, Code::Blocks on Linux will use the native compiler which may be much newer.

XCode on Mac

XCode is Apple's flagship development environment for macOS. It has a similar role in the Mac world as Visual Studio has in the Windows world. If you are a Mac user, you will need to install XCode for this class (free from the Apple App Store) because installing XCode will also install the "command line tools" including the compiler, the make utility, etc.

As with Visual Studio, XCode prefers to use its own build system. Although it does support projects using "external build systems" (meaning make), I have not been able to get that working as well as I would like. I was able to get XCode to use make to build a project, but XCode's code assistance technology did not work because XCode didn't realize it needed to index my source files.

I found some information about how to fix this here, but that approach did not work for me. There are many other pages to be found online related to using XCode with Makefiles, but they tend to describe very complicated procedures (aka "hacks") or they pertain to much earlier versions of XCode than what I'm trying to use. Figuring this out is still an open question for me.

However, using XCode's built-in build system on a cross-platform application is also awkward. XCode wraps the source code of a project in a directory structure that is specific to XCode. In contrast, Visual Studio's build control files can exist in a largely unobtrusive way inside the directory structure of the project. This means if one developer of a cross-platform program wanted to use XCode, that would impose XCode's project structure on all other team members, including those on other platforms using other tools.

In summary, XCode assumes that everyone on the team is also using XCode. That assumption is very reasonable for many projects, especially Mac-only projects, but it is not a good assumption for cross-platform projects. For this reason, I can't recommend XCode as a development environment for this class.

Open Watcom on Windows and Linux

Open Watcom's claim to fame is that it continues to support various legacy OS targets such as MS-DOS, 16-bit Windows, and OS/2. Although these platforms are obsolete, there are still people using them and trying to write new programs for them. Those people have very limited choices for what compiler to use, and that's where Open Watcom comes in.

Open Watcom supports 32-bit Windows and Linux targets as well (no macOS support), allowing it to also be used on modern systems. However, the Open Watcom C++ compiler only supports, at the time of this writing, C++ 1998, and even that support is incomplete. For this reason Open Watcom is not a viable development environment for this class.

Note that Open Watcom does come with a simple (and light-weight) IDE, a graphical Vim clone, and a graphical debugger, but for the most part, the system is a collection of command-line tools. Some of the development environments above, notably Code::Blocks, can be configured to use the Open Watcom compilers. There have also been some developers who have used Visual Studio Code with Open Watcom, but that is not a configuration for the feint of heart.

For more information about Open Watcom see my Open Watcom pages.


Last Revised: 2023-08-03
© Copyright 2023 by Peter Chapin <peter.chapin@vermontstateedu>