Step 1: Project Setup¶
Read time: 14 minutes (3719 words)
By now you should be aware that every project you create should live in a folder named after that project. Furthermore, that project should immediately be placed under Git management! No exceptions!
Warning
Never take one project and morph it into another one. You may regret that later. You will remember that you did something cool in that first project only to discover you wrecked that project when you moved on. I have every project I wrote during two years in the Texas State CS graduate program (including my thesis project, the biggest Python program I have written!) on a backup HD. It is fun to resurrect some of those and run them again, even after 15 years!
The Project Folder¶
For this project, you should have already cloned your new repository for Lab2. The result is a new folder named “Lab2-CPU-Factory-username”. Personally, I hate names like that. I would rather keep names short, and to the point. We can fix that:
$ cd cosc2325
$ mv lab2-cpu-factory-username cpu-factory
Git does not care what the project folder name is, it only cares about what is inside of that folder. Furthermore, when you clone something, you can pick some other name by adding that name after the URL:
$ git clone https://githib.com/ACC-COSC2325-003-SP19/lab2-cpu-factory-rblack42 cpu-factory
Now the working repository folder is named cpu-factory
.
Let’s write some simple code:
1 2 3 4 5 6 7 8 9 10 | #include <iostream>
#include "version.h"
int main(int argc, char *argv[]) {
std::cout
<< "CPU Factory"
<< " Version: "
<< version
<< std::endl;
}
|
Notice that I placed this code file in a new subdirectory named src
. I will
use this directory to hold all code that interacts with a human. This is the
primary application code, and this is the entry point for our simulator
program. In our testing, we will not try to test the complete application. That
can be a hard thing to do. We will focus on testing the components of this
application. We do not have any of those yet.
Versions¶
It is very common to include a version number in your project. You have seen this in action: Windows 7, Windows 8, etc. This is the third evolution of this simulator project, so I gave it a version number of “3.0”. Rather than place that in main.cpp, I pulled it out and placed it in a header file.
All header files we create for this project will be stored in a directory named
include
. That will make it easy to find them later.
1 2 3 4 | #include <string>
// current project version number
const std::string version = "3.0";
|
Test It!¶
We have written enough code to try running it. Since the code so far is just a minor variation of “Hello, World!” it better run!
$ g++ -o test src/main.cpp
src/main.cpp:2:10: fatal error: 'version.h' file not found
#include "version.h"
^~~~~~~~~~~
1 error generated.
Well, that is annoying. We “included” a header file, but the compiler cannot find it. We could fix this by specifying the correct path to that file, but that clutters up the code and makes it hard to change later. Instead, let’s just tell the compiler where to look for it:
$ g++ -o test -I include src/main.cpp
That -I
option tells the compiler to look here if it cannot find a header
file anywhere else.
Since the compiler exited with no errors, we should be able to run our code:
$ ./test
CPU Factory Version: 3.0
All this proves is that we can build a really simple C++ program. At the very least, that proves that our development tools are properly set up! This is not the kind of testing we want to do, and testing the complete application is not what we will do either.
Too Much Typing¶
At this point in our project, we are ready for a cool new tool, one that will save you a ton of typing on the command line!
You need to read the notes on using Make one of the oldest and still most powerful build tools in all od programming. There are new contenders to the throne, but understanding Make will make to a better developer.
With that background, this Makefile
should not be too scary:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | TARGET = demo
SSRCS = $(wildcard src/*.cpp)
LSRCS = $(wildcard lib/*.cpp)
OBJS = $(SSRCS:.cpp=.o) $(LSRCS:.cpp=.o)
CFLAGS = -I include -std=c++11
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJS)
g++ -o $@ $^
%.o: %.cpp
g++ -c $(CFLAGS) -o $@ $<
.PHONY: run
run: $(TARGET)
./$(TARGET)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)
|
Warning
Copy-and-paste at your own peril! The web does not honor tab characters.
Make is extremely pick about tabs, so your copied Makefile
will not
work until you get those tabs back in where they belong. gVim can help you
if you edit the file with the right name. gVim knows where tabs belong!
With this file added to your project, you should be able to do this:
$ make clean
rm -f demo src/main.o
$ make
g++ -c -I include -std=c++11 -o src/main.o src/main.cpp
g++ -o demo src/main.o
$ make run
./demo
CPU Factory Version: 3.0
Looks like we have a decent start! Now for some real code!