Setting Up Your Linux Environment ================================= Before diving into C++ programming, we need to spend some time setting up our program environment. In this course the programming environment is `Linux `_, and we assume you will be using a text editor to edit your programs and command-line window to compile and run them. You can certainly use other tools if you wish, but we can't promise to help you with them. Getting Linux ------------- If you want to use Linux on your own computer --- something we strongly recommend! --- then we recommend you install `Ubuntu Linux `_. That's the version of Linux we'll be using in the lectures and labs. Here are some options for running Ubuntu on a Windows computer: - Try `Wubi `_. This may be the easiest way to get Ubuntu running on Windows. - Run Ubuntu as a virtual machine on a Windows computer using, for instance, `VirtualBox `_. Then you can run an entire Linux system as a regular Windows program in its own window. If you want to try this, start by looking at the `VirtualBox End-user documentation `_. - Dual-boot your PC to run both Windows and Linux. - Install Ubuntu on a CD or USB drive, and then run Ubuntu from that. - Install Ubuntu on a spare computer. See the `Ubuntu download page `_, or the `Ubuntu Installation Wiki page `_, for (much) more information. **If you are using a Mac**, then, because it is already a Unix-based (although not Linux) system, and `XCode `_ is what you should use. Using the Command-line Window ----------------------------- Most of what we will do in this course can easily be done with a **command-line** window, sometimes called a **shell** window. The command-line window lets us type commands to run programs. By default, command-line windows in Ubuntu uses the `BASH `_ command-line, and when you first launch it you will see a prompt something like this:: tjd@tjd-ubuntu-desktop:~/cmpt125$ This prompt has a lot of parts: - ``tjd@tjd-ubuntu-desktop`` is the user name and computer name. This is useful when you are using multiple computers or multiple accounts. - ``~/cmpt125`` is the current working directory, i.e. the directory that the command-line will look in first when you run a program. The ``~`` is shorthand for you personal directory. - ``$`` marks the end of the prompt and the beginning of where the user types commands. In these notes we will usually denote the shell prompt using just a ``$``. .. note:: It turns out that command-line prompts are highly customizable (e.g. `see this posting as a start `_). You are curious you can configure your prompts to provide lots of useful information. Some Useful Shell Commands -------------------------- The shell has dozens and dozens of commands, although to get started you only need to know a few simple ones. Here is a brief summary of the commands we'll discuss here: +---------+-----------------------------------+ | Command | Summary | +=========+===================================+ | ``pwd`` | returns present working directory | +---------+-----------------------------------+ | ``ls`` | lists files and folders of pwd | +---------+-----------------------------------+ | ``cd`` | change the pwd | +---------+-----------------------------------+ | ``rm`` | delete a file | +---------+-----------------------------------+ | ``cp`` | copy a file | +---------+-----------------------------------+ | ``man`` | print a manual page | +---------+-----------------------------------+ |``less`` | print contents of a file | +---------+-----------------------------------+ - ``pwd`` prints the **present working directory**, e.g.:: $ pwd /home/tjd/cmpt125 The present working directory is also sometimes called the **current working directory**. - ``ls`` and ``ls -l`` list all the files and folders in the present working directory, e.g.:: $ ls a1/ readme.txt $ ls -l total 8.0K drwxr-xr-x 2 tjd tjd 4.0K 2011-12-01 16:15 a1/ -rw-r--r-- 1 tjd tjd 30 2011-12-01 16:15 readme.txt In this example, ``a1`` is a folder, and ``readme.txt`` is a file. - ``cd`` changes the current working directory, e.g.:: $ ls a1/ readme.txt $ cd a1 $ pwd /home/tjd/cmpt125/a1 $ cd $ pwd /home/tjd Note that ``cd`` on its own returns you to your home directory. ``cd ..`` changes the current working directory to be the parent of the directory the shell is in now. Running ``cd ..`` multiple times in a row is an easy way to "walk up" a folder structure to some top-level folder. - ``rm`` deletes a file. For example, suppose ``temp.txt`` is in the current directory. Then this command deletes it forever:: $ rm temp.txt Beware that ``rm`` truly deletes the file: it does not put the file in the desktop trash! - ``cp`` makes a copy of a file. For example, suppose ``a1q1.cpp`` is in the current directory. Then this command makes a copy of it called ``a1q1.cpp.old``:: $ cp a1q1.cpp a1q1.cpp.old - ``man`` prints a help page (called a **manual page**, or **man page** for short) for a command. For example, ``ls`` many options:: $ man ls LS(1) User Commands LS(1) NAME ls - list directory contents SYNOPSIS ls [OPTION]... [FILE]... DESCRIPTION List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor --sort. Mandatory arguments to long options are mandatory for short options too. -a, --all do not ignore entries starting with . -A, --almost-all do not list implied . and .. This only shows the first few lines of the ``ls`` man page: ``ls`` has lots of options! Note that for some commands ``man`` is not helpful, e.g.:: $ man cd No manual entry for cd Commands like ``cd`` are part of the BASH shell language, and there are no man pages for shell commands. However, if you type ``man bash``, then you will get (a very long) man page documenting all the BASH commands (including ``cd``). - ``less`` displays the contents of a text file:: $ less helloworld.cpp // helloworld.cpp #include using namespace std; int main() { cout << "Hello, world!\n"; } If the file being displayed doesn't fit on the screen, then a single page of the file is displayed at a time. Press: - *spacebar* to go to the next page - *b* to go the previous page - *q* to quit ``less`` immediately - */banana* to search for the string ``banana`` .. note:: You can also manipulate files and folders interactively in the GUI. Just open the folder you want to change, and use the typical drag-and-drop actions you are probably already familiar with. In practice, it is sometimes easier to use the GUI instead of the command-line. For example, copying a folder it is easier in a GUI. Sometimes the command-line is best. For example, if you want to delete all the files ending with ``.bak``, then you can type this:: $ rm *.bak The ``*`` is a special meta-character that matches any string of characters, and so ``*.bak`` matches all file names ending with ``.bak``. Using g++ in Linux ------------------ In this course we'll be using the `GNU C++ compiler `_, aka ``g++``, throughout the course. We recommend you use it too. .. note:: You are, of course, free to use any other standards-compliant C++ compiler you wish, but we can't promise to provide help with compilers other than ``g++``. Keep in mind that different compilers will also have different error messages, options, and bugs. .. warning:: Your assignments will be marked by compiling and running them on Linux. It is *your* responsibility to make sure your programs compile and run correctly in Linux. If your assignment does not compile and run on Linux, the TA may not mark your assignment. To test if ``g++`` is installed on your computer, type ``g++`` at the command-line:: $ g++ g++: no input files If you see a message like "g++: command not found", then you will need to install g++. The easiest way to do this in Ubuntu is to type this command (you'll be asked to enter your password):: $ sudo apt-get install g++ After this finishes downloading and installing, test it by typing ``g++`` as above. .. note:: Another way to install software on Ubuntu is to use the Synaptic Package Manager program that comes with it (look for it in the ``System`` menu). This is essentially a graphical shell for the ``apt-get`` program that makes it much easier to search for, and select, the software you want. Editing C++ Files ----------------- C++ programs are stored as text files that end with ``.cpp`` (or sometimes ``.cc``) and ``.h``. These are ordinary text files that you can edit with any text editor. Ubuntu has a number of text editors you might want to try: - **Sublime Text 2** is a new editor that is quickly gaining in popularity due to its useful feature set and good performance. It's currently free, and runs on Windows, Mac, and Linux systems. Technically it is not free, however you can freely evaluate the complete editor for as long as you like. You can `download it from here `_. - **Kate** is a good programming editor for Linux that is quite easy to start using. On Ubuntu, it is available for download through the "Ubuntu Software Centre", or by running the command in a terminal window:: $ sudo apt-get install kate - **emacs** is a very old but still very popular text editor designed for programmers. It's easy to run:: $ emacs hello.cpp .. note:: If emacs is not on your Ubuntu system, you can install it by typing this command:: $ sudo apt-get install emacs Out of the box, emacs has excellent support for C++ programming, including syntax-coloring, bracket-matching, and GDB debugger integration. It also has special modes for writing makefiles, editing plain text, and so on. It can even do things like read your email, browse the web, and play games. Emacs extremely customizable, with hundreds and hundreds of add-ons available for it. Emacs comes with lots of documentation and help, and it's relatively easy to use right away. However, it has quite a steep learning curve and so is probably best for programmers who plan to use it frequently and for a variety of different editing applications. - **vim** (or **vi**) is another very old but still extremely popular programming editor:: $ vi hello.cpp Like emacs, vim has good support for programming out of the box, and it also extremely customizable with lots of add-ons already written. vim uses a **modal** style of editing which is different than emacs and other text editors. This takes some getting used to since you can't just start typing in vim: you need to first selection a text-entering mode. Once you get used to it and learn a few commands, vim may be the fastest editor around. It loads very quickly (in contrast to emacs and IDEs) and experienced vim users can do amazing things in just a few keystrokes. .. note:: Vim and emacs users often have "religious wars" about which editor is better. Ultimately, either editor is fine, and you might want to give both a try. The important thing is that you take some time to learn the features of a good programming editor: you will be a better and more efficient programmer if you do. - **Bluefish** is a more modern-looking editor that provides good support for a number of programming languages. To install it type this at the command-line:: $ sudo apt-get install bluefish - **gedit** is a relatively simple text editor that works much like Notepad on windows. It should be installed by default, and you use like this:: $ gedit hello.cpp While you can certainly use gedit to write C++ programs, we **don't recommend** it. gedit is designed for editing regular text files, and doesn't provide as many special features for writing code that the editors below do. - Integrated development environments, such as **Eclipse** or **Code::Blocks**, are popular with many programmers. Eclipse, for instance, works well with many programming languages. As with any programming editor, it takes time and effort to learn all the useful features of an IDE. Eclipse, for instance, has hundreds of features and tools. Another issue with IDEs is that they hide many of the lower-level details of the software creation process that are useful to know about. Thus, **we recommend for this course that you don't use an IDE**, and instead use just a programming editor and the command-line to edit and create your programs. You'll not only learn more about the software creation process, but you may even find it sometimes preferable to using an IDE. Compiling a Program with make ----------------------------- Now lets see how to compile and run a C++ program. Cut-and-paste the following into a file called ``helloworld.cpp``:: // helloworld.cpp #include using namespace std; int main() { cout << "Hello, world!\n"; } Save the file, and then in the same directory type the following command:: $ make helloworld g++ helloworld.cpp -o helloworld .. note:: If ``make`` is not on your Ubuntu Linux system, then install it using this command:: $ sudo apt-get install make This compiles ``helloworld.cpp`` and creates an executable file called just ``helloworld``:: $ ls helloworld* helloworld.cpp To run the executable file, type this:: $ ./helloworld Hello, world! Notice you must put ``./`` in front of the executable file name. This is a simple safety precaution to avoid accidentally running an executable file. Something interesting happens if you try to re-compile the program:: $ make helloworld make: `helloworld' is up to date. The ``make`` program is smart enough to know that the executable file already exists, and so there is no reason to compile it again. It knows this by checking the time-stamps on the files: the last change to ``helloworld.cpp`` was before the creation of of ``helloworld``, and so there is no need to re-compile it. In other words, ``make`` only re-compiles a program if it has changed since the last compilation. For large projects consisting of 100s, or even 1000s, of files, ``make`` can dramatically decrease the compile time. If you didn't enter the program correctly, you might get an error message. For example, suppose we forgot the second ``;``:: // helloworld.cpp #include using namespace std; int main() { cout << "Hello, world!\n" // oops: forgot a semi-colon } Here's what happens when you try to make it:: $ make helloworld g++ helloworld.cpp -o helloworld helloworld.cpp: In function ‘int main()’: helloworld.cpp:9: error: expected ‘;’ before ‘}’ token make: *** [helloworld] Error 1 If you read this error message carefully you'll see that it refers to line 9 of the program, i.e. the last line of the program (that has a ``}`` on it). Unfortunately, error messages in C++ are often messy and perplexing. One of the difficulties of generating good error messages is that the line where the program *fails* might not be the same line as where the error is located. For instance, in the error above the point of failure is line 9, but the error is located on line 8. Compiling Without make ---------------------- If you prefer, you can run ``g++`` directly when you compile your programs. For example:: $ g++ helloworld.cpp This creates an executable file called ``a.out`` which you can run like this:: $ ./a.out Hello, world! If you want the executable file to be named something other ``a.out``, use the ``-o`` option:: $ g++ helloworld.cpp -o hello $ ./hello Hello, world! Unlike using ``make``, compiling directly with ``g++`` *always* re-compiles the source file, even if it hasn't changed. That doesn't make much difference for small programs, but for large multi-file C++ programs you'll soon discover that unnecessary re-compilation can eat up a huge amount of time. Using make with a Simple Makefile ---------------------------------- Another useful thing to do with ``make`` is to include a *makefile* that sets the options we want to use to compile our programs. For example, the ``g++`` compiler has an option called ``-Wall`` that turns on all warnings. This is often a useful way to help you find bugs in your code. Also, if you want to use a debugger (such as ``gdb``) to examine your executable programs, you need to compile them with the ``-g`` option. So to use these options, create a file called ``makefile`` in the same directory as ``a1q1.cpp`` and put the following into it:: # set the C++ compiler options # -Wall turns on all warnings # -g puts debugging info into executables (makes them larger) CPPFLAGS = -Wall -g ``CPPFLAGS`` is a special pre-defined ``make`` variable that is meant to contain the options we want to pass to the C++ compiler. Lines that begin with a ``#`` character are comments to the reader of the makefile. Now when you make ``a1q1`` it uses the options listed in ``CPPFLAGS``:: $ make a1q1 g++ -Wall -g a1q1.cpp -o a1q1 Speeding Up make ---------------- If your computer has more than one CPU (quite common these days), then you can try running ``make`` with the ``-j`` option:: $ make -j This will cause make to try to use multiple CPUs to make your programs. This can significantly speed up compile times when more than one program is being compiled. Of course, if ``make`` is only compiling a single program then the ``-j`` option isn't useful (but it doesn't usually cause any problems). Optional: Automatically Generating Dependency Rules --------------------------------------------------- Note that the compiler can generated makefile rules for you using the -MM option:: $ g++ -MM a1q1.cpp a1q1.o: a1q1.cpp std_lib_cmpt125.h While we won't be using this feature in this course, it can be useful for large projects where it might not be at all obvious what the makefile dependency rules should be. Questions --------- #. Briefly explain what each of the following BASH shell commands do: ``pwd``, ``ls``, ``cd``, ``rm``, ``cp``, ``man``, ``less``. #. Why is a non-programming text editor such as gedit *not* a good way to edit programs? #. Suppose the file ``matrix.cpp`` is in the current working directory. What would you type at the command-line to create an executable called ``matrix`` using ``make``? What about using ``g++`` directly? #. What are two advantages of using ``make`` instead of directly using ``g++``? #. How would you install ``make`` on Ubuntu Linux if it was not already installed? #. What does the ``-j`` option do for ``make``?