To be a good programmer, you need good tools to help you craft your code. Your choice of tools and your ability to use them effectively is critical to working effectively. If all you have is a hammer, even tasks that should be easy become difficult or impossible.
This page reflects some of the strong preferences of Professor Pisan. Check with your instructors in case they have specific preferences. This short video demonstrates some of the tools from this toolchain.
The information below explores several tools. Not all the tools is necessarily needed. If you’d like a concise set of instructions to setup your Visual Studio Code environment, see this detailed instructions.
Choosing a good set of tools is the first step, and then you have to learn how to use them well. I don’t like switch between Mac and Windows, because every time I do, it takes me extra effort to remember how to do things in that environment. I use Emacs as my text editor, so a lot of the shortcuts are at the tip of my fingers. I do not have to think about them. The less you have to think about the tool, the more energy and focus you have for the actual task you are trying to accomplish.
Tools change. Each company has its own toolchain for its software developers. Each new version of the same program can even introduce slight differences. You need to be flexible enough to learn and use different tools.
Different courses will require you to use different set of tools. This page describes one possible way. Unless you are a seasoned programmer with well-established toolchain, you should follow the recommendations on this page. Even if you are seasoned programmer, there are probably a few things you can learn from the approach described.
We will use several tools such as Visual Studio Code, g++ compiler, GitHub for storing code and tracking changes, clang-tidy to ensure our programs adhere to C++ standards, clang-format to check our code style, CSS Linux Lab as a shared environment to test our programs, valgrind to check for memory leaks, llvm to check for code coverage, and others.
Learning to use the tools effectively takes time, but it is time that will come back to you 100-fold in the future. Every time you do something the hard way, you are wasting time, potentially introducing errors, reducing your ability to iterate. For example, learning the keyboard command to save a document (CTRL-S for most editors) can take some time, but ends up saving much more in the long run. StackExchange has a discussion that with references to several research paper showing for frequents tasks keyboard is much more efficient than using the mouse.
Compiler
A program starts out as a text file, by convention a file with a .cpp extension for C++ programs. The compiler, which is just another program, converts this text file into an executable file. On Windows, executables have a .exe extension. On MacOS and Unix, the executable files do not have a specific extension.
Compilation Stages
Compiling a C++ program happens in several distinct steps
- Preprocessing – Handle special preprocessing commands such as
#include
,#define
,#ifndef
, etc - Compilation – C++ source code is parsed and turned into assembly code. A binary object file with a .o extension is created. Each source file is converted into a separate object file. If you have a large project with 100 files and you change one file, then only a single file needs to be recompiled into object code.
- Linking – The object files and system libraries are linked together to create an executable file.
Most of the time we do not have to think of the different compilation stages. We compile the project to create an executable, but knowing the different stages can be useful when debugging since you get different types of error messages in each stage.
Different error messages:
- Preprocessing – Missing
#include
file, misspelled file name, incorrect name for a system library - Compilation – Syntax error (such as missing semicolon), undefined function or class, etc.
- Linking – Duplicate definitions or missing definition for a function
g++
, the GNU C++ Compiler, is the most commonly used compiler. clang++
is a newer compiler from the LLVM project that is designed for easy experimentation. For our purposes, g++
and clang++
are often undistinguishable.
Installing a Compiler
Installing a Docker image that is identical to the CSS Lab machines is the best option. Follow the instructions at https://csswiki.uwb.edu/css-linux-lab-docker-image/ on installing an image.
Alternatively, you can install a compiler that runs on your own machine.
Linux: CSS Linux Lab already has g++
and clang++
compilers installed. Once you login, you can execute g++
(or clang++
) from the command line. See Connecting to the Linux lab machines on details of how to connect. If you are running Ubuntu Linux, or another flavor of Linux, on your own machine, search for instructions specific to your operating system.
Windows: Several options are available:
- Install MSYS2 which creates a unix like environment on your Windows machine. install llvm in that environment using
pacman -S –needed mingw-w64-x86_64-clang mingw-w64-x86_64-clang-analyzer mingw-w64-x86_64-clang-tools-extra mingw-w64-x86_64-lldb mingw-w64-x86_64-llvm
- Install Visual Studio comes with MSVC which is a compiler for Windows.
- Install MinGW, MinGW-w64 or Cygwin. Both of these provide minimal unix like environments.
- If you are running Window 10, install the Windows Subsystem for Linux
Mac: Install brew package manager to download g++
and additional tools. brew is a flexible package manager and will make it much easier to download and install other programs. Alternatively you can download XCode and then install the XCode Command Line tools using xcode-select –install
.
g++ on CSS Linux Lab
See Basic Linux Commands on how to use some linux commands and compile a program under unix.
There is an easier way to do all this, but it is important to do it the hard way at least once to understand the process from start to finish. Next, we will look at tools to streamline this process.
IDE
An IDE, an Integrated Development Environment, is a text editor that provides additional facilities to programmers for software development. A good IDE will highlight keywords with different colors, prove code completion suggestions, show function documentation and parameter while typing a function, indent code automatically, provide integrated commands to run and debug the program, have keyboard shortcuts to refactor code, jump to function definitions and help us catch programming mistakes as we type.
IDEs come in different shapes and sizes. Some IDEs come with their own compiler while others can be configured to use different compilers. Web based IDEs allow us to write and execute our programs through the browser interface. Some IDEs are work with only a single programming language while others use plugins to work with many languages.
Some of the popular IDEs for C++ are: Visual Studio Code, Visual Studio, CLion, Eclipse, Code:: Blocks, Sublime Text, Xcode (only for Mac), Emacs, Vim
Your IDE must have at least the following features:
- Reformat code to fix any indentation problems
- Refactor function name and variable names
- Compile and Run code easily
- Step through code in debugging mode and show the value of local variables
- Comment/Uncomment a line or a block of code easily
- Jump to the definition of a function easily
- Find all occurrences of a string and replace them easily
An alternative to having an IDE running on your local machine is to use your web browser to access a site that provides an online IDE. Some of the popular online programming environments are: Repl.it, CodeAnywhere, AWS Cloud9, Visual Studio Codespaces, Ideone, Codepad, Codechef, Jdoodle, Codiva, and many others,
We are going to use Visual Studio Code to edit and compile files directly on the CSS Linux Lab.
If you would like to work offline, you can use Visual Studio Code on your own local machine. However, you must always test your programs on the CSS Linux Lab before submitting them. It is not good enough for your program to work on your machine. Your program has to work on the CSS Linux Lab.
Repl.It
See Repl.it a web based IDE that also provides a unix shell for compiling programs.
Visual Studio Code
Visual Studio Code is currently the most popular IDE. Make sure you do not confuse VSC with Visual Studio or Visual Studio Codespaces as each one offers a different set of features.
The power of VSC comes from the large number of plugins there are in the VSC Marketplace. VSC can edit files on a remote machine and provide a terminal to execute commands on the remote machine. We are going to make use of this functionality to write our “Hello World” program CSS Linux Lab.
If you have a docker image installed, you can compile your programs in that container, so you can skip the below instructions on connecting to the CSS Linux Lab remotely.
- Install Visual Studio Code
- Instal ssh client
- Windows: Install the Windows OpenSSH Client.
- Mac:
ssh
should already be installed
- Confirm that Husky OnNet is connected. You need UW VPN service when connecting to UW machines.
- Check
ssh
. Open aTerminal
(CMD for Windows, Terminal application with bash shell for MAC) and issue this command:ssh <YourNetId>@csslab7.uwb.edu
- Windows: If
ssh
is not in your path, you will have to add it manually. In most cases,ssh.exe
will be installed inC:\Windows\System32\OpenSSH
. Follow the instructions at this web page, to add this folder to your PATH.
- Windows: If
- Follow the instructions on Remote Development using SSH to install the Visual Studio Code Remote Development Extension Pack. CSS Linux Labs already have the SSH client installed, so you can ignore the “Install an OpenSSH compatible SSH client if one is not already present.” step
Here is a short video demonstrating how to connect to CSS Linux Lab.
If you try to connect to multiple csslab machines and you are getting an error message from VSC, then the files VSC has installed in csslab might have been corrupted. Login to any csslab machine using Putty
, MobaXterm
or Terminal
(see instructions at Connecting to the Linux lab machines if necessary. Once logged in, execute rm -rf .vscode-server/
to delete all files that were installed by VSC.
This is also a good time to install a terminal program, other than VSC, to connect to CSS Linux Lab. See instructions on Connecting to the Linux lab machines. Having a terminal program to access your files in the CSS Linux Lab and a file transfer program (ftp program) to transfer files easily from your local computer to CSS Linux Lab will come in handy. For Windows, MobaXTerm and Putty are popular clients for logging into unix machines. MobaXTerm also allows you to transfer files as well. For Mac, you can use the builtin Terminal with ssh to login, scp to transfer files. Other programs for transferring files that work for both Windows and Mac are Filezilla client and Cyberduck.
Connect to csslab1.uwb.edu using the “Remote Explorer” in VSC. The first time you connect, ssh will ask you if you trust this machine as well as your password. If you do not want to enter your password every time, you can create an ssh key pair. The Quick SSH setup for linux lab has some basic information on how you might do it.

Once the ssh connection has been setup and the configuration information added to /usr/netid/.ssh/config
(on your local computer), You can establish a connection in VSC, by clicking on the “Connect to Host in New Window” icon.

When you are connected to the CSS Lab, you should see the name of the machine you are connected to on the bottom left of VSC.

When you are connected to the remote machine, using “New File” or “Open” in VSC will open a file on remote machine.
Choose Terminal > New Terminal from the VSC menu to create a terminal on the remote machine and follow the steps in the image below to create your 342 directory.

$ mkdir 342 $ cd 342 $ ls -al total 4 drwxrwxr-x 2 pisan pisan 10 Aug 9 13:04 . drwx------ 33 pisan pisan 4096 Aug 9 13:04 .. $ mkdir hello $ cd hello $ pwd /home/NETID/pisan/342/hello $ ls -al total 0 drwxrwxr-x 2 pisan pisan 10 Aug 9 13:04 . drwxrwxr-x 3 pisan pisan 27 Aug 9 13:04 .. csslab1:hello$
Now that we have a directory for our project and a shell to compile it, we are ready to write our “Hello World” program. Create a New File in VSC, copy the content below and save it with the name “helloworld.cpp” into the 342/hello directory.
#include <iostream> using namespace std; int main() { cout << "Hello, World" << endl; return 0; }
Check in the shell that your file is in the correct location.
$ ls -al total 0 drwxrwxr-x 2 pisan pisan 36 Aug 9 13:12 . drwxrwxr-x 3 pisan pisan 27 Aug 9 13:04 .. -rw-rw-r-- 1 pisan pisan 0 Aug 9 13:12 helloworld.cpp
You can now compile and execute your program.
$ g++ -o helloworld helloworld.cpp $ ls -al total 16 drwxrwxr-x 2 pisan pisan 58 Aug 9 13:19 . drwxrwxr-x 3 pisan pisan 27 Aug 9 13:04 .. -rwxrwxr-x 1 pisan pisan 8776 Aug 9 13:19 helloworld -rw-rw-r-- 1 pisan pisan 107 Aug 9 13:19 helloworld.cpp $ ./helloworld Hello, World $
Time for some experimentation to learn about compiler error messages:
- What is the error message you get, if you change “iostream” to “xxx”?
- What is the error message you get, if you delete a “;”
- What is the error message you get, if you change “«” to “<”?
- What is the error message you get, if you delete a quotation mark?
- What is the error message you get, if you comment out the “using namespace std;” line?
The compiler processes the file line by line. If there is a missing semicolon on line-10, its processing for all the lines after line-10 goes wonky. It might generate 10s or 100s of error messages. The only error message that you need to pay attention to is the first error message. All error messages after the first one are often meaningless.
Let’s examine the contents of “Hello World” program.
1. #include <iostream> 2. 3. using namespace std; 4. 5. int main() { 6. cout << "Hello, World" << endl; 7. 8. return 0; 9. }
Line-1: #include
is a pre-processor command. It tells the pre-processor that the program will use the iostream
library. The Standard Input / Output Streams Library defines the cout
functions for printing. See cplusplus reference for additional details.
Line-3: C++ functions reside in different namespaces, so that functions with the same name do not overwrite each other. cout
is in the namespace std
(the standard namespace). To reference the cout
command, we need to use std::cout when we refer to it. Using std::
can make our programs harder to read, so for our class programs, we are going to include the statement using namespace std;
at the beginning of our programs. For large projects, where there are multiple connected systems, it is better not to have using
statements and reference each function with its full name.
Line-5: int main ()
All programs must have one, and only one, main function. The main function is where execution of the program will start. By default, the main function returns 0 to indicate successful termination of the program. The main function can be defined not to take any parameters, as is the case in our example, or it can be defined as int main(int argc, char* argv[])
when a program takes command line arguments.
Line-6: cout << "Hello, World" << endl;
. cout
is the insertion operator. We are inserting some text into the standard output stream. When we have multiple items to insert, we can chain the <<
operator. The endl
inserts a newline and flushes the stream. You might also see “\n” used as the newline character. For compatibility, it is better to use endl
since Windows defines end-of-line as “\r\n” while Unix defines it as “\n”.
Line-8: The return
statement exits the function, and in our case exits the program.
For a more detailed look at transition from Java to C++, see Professor Zander’s notes on what used to be the CSS 332 course.
Another popular IDE is CLion. CLion can also edit files on a remote host as well as let you compile and run programs on a remote host. See https://www.jetbrains.com/help/clion/editing-individual-files-on-remote-hosts.html for details.
Troubleshooting VSC
“VSC Server Error” or “Disk Quota Exceeded” when trying to connect to CSSLab machines
Short version, login to a csslab machine using PuTTy or Terminal and try these commands:
- Clear out cache files:
rm -rf ~/.cache
- Clear out any VSC files:
rm -rf ~/.vscode-server
- Check your total disk usage:
du -sh ~
- Check how much space each directory is taking:
cd; ls -a | du | sort -n or alternatively find ~ -maxdepth 1 -execdir du -s {} \; | sort -n
- See who is using lots of CPU:
ps aux | head -1 ps aux --cols 160 | sort -nr -k3 | head ps aux --cols 160 | sort -nr -k3 | head | awk '{ print $1}' | sort | uniq | xargs getent passwd
- See who is using lots of Memory:
ps aux | head -1 ps aux --cols 160 | sort -nr -k4 | head ps aux --cols 160 | sort -nr -k4 | head | awk '{ print $1}' | sort | uniq | xargs getent passwd
- Check if you have any processes you need to use `
kill -9
` on the current machine ps aux | grep $USER - Kill any vscode processes you have on the machine
ps aux | grep $USER | grep vscode | awk '{print $2}' | xargs kill -9
- Check the load on the different machines (assuming you have ssh set to automatically log you in. Save the commands below into a .sh file, make it executable and run it)
#!/bin/sh
ssh -q csslab1.uwb.edu 'uname -n; uptime';
ssh -q csslab2.uwb.edu 'uname -n; uptime';
ssh -q csslab3.uwb.edu 'uname -n; uptime';
ssh -q csslab4.uwb.edu 'uname -n; uptime';
ssh -q csslab5.uwb.edu 'uname -n; uptime';
ssh -q csslab6.uwb.edu 'uname -n; uptime';
ssh -q csslab7.uwb.edu 'uname -n; uptime';
ssh -q csslab8.uwb.edu 'uname -n; uptime';
ssh -q csslab9.uwb.edu 'uname -n; uptime';
ssh -q csslab10.uwb.edu 'uname -n; uptime';
ssh -q csslab11.uwb.edu 'uname -n; uptime';
ssh -q csslab12.uwb.edu 'uname -n; uptime';ssh -q csslab13.uwb.edu 'uname -n; uptime';
ssh -q csslab14.uwb.edu 'uname -n; uptime';
ssh -q csslab15.uwb.edu 'uname -n; uptime';
ssh -q csslab16.uwb.edu 'uname -n; uptime';
ssh -q csslab17.uwb.edu 'uname -n; uptime';
ssh -q csslab18.uwb.edu 'uname -n; uptime';
ssh -q csslab19.uwb.edu 'uname -n; uptime';
ssh -q csslab20.uwb.edu 'uname -n; uptime';
ssh -q csslab21.uwb.edu 'uname -n; uptime';
ssh -q csslab22.uwb.edu 'uname -n; uptime';
GitHub
See GitHub
Code Style
See C++ Code Style
Code Coverage
Memory Leaks
See C++ Memory Leaks
Unix
The toolchain we have covered is for developing programs in the CSS Linux Lab with
g++
compiler- Visual Studio Code running on our local machine but editing files on the CSS Linux Lab
- GitHub for version control and to store our projects
clang-tidy
andclang-format
to enforce code stylellvm-profdata
andllvm-cov
to check code coveragevalgrind
andg++
flags to detect memory leaks
We can automate a lot of these manual tasks. The sample project https://github.com/pisan342/hello-factorial includes create-output.sh and check-code-coverage.sh scripts that run all these test for us.
The create-output.sh
script is intended to be run on the CSS Linux Lab, but you can modify it to run on your desktop machine as well. If you have a Mac and have already installed brew getting this script to work should not be too hard. For Windows, there are many different configuration options depending on whether you are using mingw, WSL or some other combination.
We’d like to make sure that our programs run not just on our machine, not just on CSS Linux Lab, but run successfully on any machine.
GitHub Actions
GitHub Actions provide a way to test our programs on a virtual machine. The sample project https://github.com/pisan342/hello-factorial has a file buildrun.yml under .github/workflows/ directory. This file defines a set of instructions to execute every time we “push” our code to GitHub. The results from the script can be found under “Actions” on the repository web page.

Unix Tutorials
There are many free unix tutorials available, such as:
- https://folk.uio.no/tiago/teaching/unix2018/unix-exercises/,
- https://heim.ifi.uio.no/gisle/staging2/drupalprimer/unix/unix_ix.html,
- http://www.ee.surrey.ac.uk/Teaching/Unix/unixintro.html,
- https://www.tutorialspoint.com/unix/index.htm,
- http://staff.washington.edu/waldrw/linux-101.htm
- https://kcls.org/blogs/post/learning-paths-on-lynda-com/ – If you have a King County library card, you can access Lynda for free
Another exercise/tutorial that was developed locally is at 50 Step unix
Miscellaneous
You can write your own scripts to customize your unix environment. Here are some example scripts
top-cpu
#!/bin/shVisit Site # top-cpu # find out who is using all the cpu ps aux | head -1 ps aux --cols 160 | sort -nr -k3 | head ps aux --cols 160 | sort -nr -k3 | head | awk '{ print $1}' | uniq | xargs getent passwd
top-mem
#!/bin/sh # top-mem # find out who is using all the memory ps aux | head -1 ps aux --cols 160 | sort -nr -k4 | head ps aux --cols 160 | sort -nr -k4 | head | awk '{ print $1}' | uniq | xargs getent passwd
uptimes
#!/bin/sh # Find out the load on all the csslab machines ssh csslab1.uwb.edu 'uname -n; uptime'; ssh csslab2.uwb.edu 'uname -n; uptime'; ssh csslab3.uwb.edu 'uname -n; uptime'; ssh csslab4.uwb.edu 'uname -n; uptime'; ssh csslab5.uwb.edu 'uname -n; uptime'; ssh csslab6.uwb.edu 'uname -n; uptime'; ssh csslab7.uwb.edu 'uname -n; uptime'; ssh csslab8.uwb.edu 'uname -n; uptime'; ssh csslab9.uwb.edu 'uname -n; uptime'; ssh csslab10.uwb.edu 'uname -n; uptime'; ssh csslab11.uwb.edu 'uname -n; uptime'; ssh csslab12.uwb.edu 'uname -n; uptime';
To find out how much disk-space you are using, use du -sh ~
To find out your largest directories, use du -s `(ls -A ~)` | sort -n
To use these scripts:
- Save them to ~/local/bin/
- Make them executable using
chmod 755 filename
- Add the path to your
.bashrc
using exportPATH=“${PATH}:/home/NETID/my-net-id/local/bin”
replacing my-net-id with your actual netid
This wiki page was mostly written by Yusuf Pisan pisan@uw.edu.