An engine to encapsulate the core logic of the program is highly recommended. That engine consists of one or more source code files. Each source file contains programming statements that conform to the C++ language standard as well as comments that explain parts of the code. All those code files are to be translated into a binary form that unites them all as one operating whole. A good practice is to create a binary version of the engine source code and then setup a command-line interface that will allow you to exercise the engine code in a direct way. Doing this can ensure that the non-visual code supporting a GUI (graphical user interface) is solid. You then eliminate a distraction to building a good GUI when you know the underlying logic layer is reliable.
The purpose of this article is not to make C++ software development universally accessible to all readers. On the contrary, the persons who will get the most benefit from this article have put in the work in the first 6 articles and have worked through the prerequisite materials in the form of books on the topic of C++ (or Java or C# or Python) and software development. That audience is then seeking the material that converts the general topics described in those books into a practical form in which a C++ program can be built effectively.
Refer to 3 following general topic articles. They describe user interfaces in general as well as overall meta-level thoughts that assist you when approaching the process:
- Perspectives on User Interfaces – UI Core
- Perspectives on User Interfaces – UI Frameworks and Toolkits
- Perspectives on User Interfaces – Five GUI/Graphics Library Levels
Refer to the 6 topical articles. They lead up to this article are the necessary cognitive and process prerequisites that you can apply to build a better program:
- Create a C++ UI – The System Exists in Your Mind
- Create a C++ UI – Data Flow
- Create a C++ UI – Program Flow
- Create a C++ UI – Communication and Data Exchange
- Create a C++ UI – Data Organization
- Create a C++ UI – Build the Engine
This article is 16 printed pages and is the main article in this series for creating C++ programs in the most direct way possible on Linux. However, the information presented implies a process that also applies to Microsoft Windows and Apple. You can build a C++ program in a fundamental way (without the extra bells and whistles) across the 4 major desktop operating systems today (Linux, UNIX, Windows, and Apple). What I cover in this article are the concrete, tangible steps needed to achieve this but I use Fedora Workstation 29 as the operating system from which I demonstrate and discuss these steps. With appropriate documentation and other sources, you can make the relevant translations to other operating systems though the majority of what I present applies uniformly to Linux, UNIX, and Apple without modification. However, the same elements exist in almost the same form on Microsoft Windows’ command-line (called Command Prompt with or without PowerShell) and folders and files browser (known as Windows Explorer).
Application Desktop and UI Programs
Programs on a computer can use sophisticated graphics (called a UI); show only text (a command-line interface); or simply run without any display output (background program). A few examples will clarify beginning with UI programs.
Most UI programs are launched from a “master UI” program called a desktop. The following is an screenshot of the Fedora Linux Desktop (version 29). Notice the icons, spacing between icons, the caption labels, and overall options available. You can download Fedora Workstation at the https://getfedora.org. Other articles on the web describe how to install it in detail. I discuss that process in a more general way in later sections in this article.
When we click, touch, or speak on one of these icons, a program launches and shows on the screen. An example, is when we activate the program represented by the icon labeled Text Editor. The following program screen appears. This is a program represented in a user interface.
Command-Line Environment and Command-Line Programs
Another group of programs can be used through what is called a command-line environment. The way they work is you type a command. That command may be the name of a program. When that program is found, any text output it provides is shown on the command-line. Obviously, a command-line program can accept input in the form of a program’s name. The called up program can accept input you type in the same command-line environment.
An empty command-line.
Run a program named date. The output is text. Basically, many command-line programs take an input and present an output. The output can be simple like the one shown here, or complex such as when you run the program named top.
The output from the program named top.
All Programs Are Visible to the Operating System
A clear difference exists between UI and command-line programs. Both however can often be seen through a system monitor program. The following is like a visual version of top. The equivalent in Microsoft Windows is Task Manager. The system monitor on Fedora Linux appears as follows. Notice that there are many programs running. More than can be shown in a single screen shot. At the time of this screen shot, I counted 65 non-visual programs running in the background and 3 UI programs.
These local system monitoring programs show most programs (except super clever malware / spyware) running on a computer whether they are visual programs bearing a UI; command-line programs; or background programs without any visual text output. Among the 3 types of programs, the UI programs require additional code to show output with greater visual variety as well as handle input through mouse, touch, speech, and keyboard. The other 2 types are practically all logic handling data input from files, databases, networks, and command-line streams with output designated to the same or similar input types.
Our focus in the beginning is to build a command-line program. That eliminates the added burden of creating a UI at the same time. It will give us the basic means to execute C++ code, gather output, and work out how well our core logic is defined. If you do this right, the command-line program will be a program in its own right. The benefit of that is a faster, quicker alternative to a user interface.
Tools to Build a Command-Line Program
A couple of things are needed but what you do not need is expertise in C++. Familiarity maybe, but if you are not well experienced in C++, the minimum needed is to try and write C++ code. These articles define a structure within which you can safely work out any roadblocks creating either a UI or command-line program in C++. The articles do not constitute a language book but rather an approach to work through the planning, tools, and steps to build a C++ program from start to finish. By definition, expertise in writing C++ is not needed.
We need an operating system, a text editor, and developer build tools in that order. At its essence, an operating system (OS) is a program that runs other programs by managing how those programs access computer hardware. The OS achieves this by establishing rules the programs must obey (malware / spyware by definition bends / breaks these rules) in order to properly execute in the OS’ environment. For example, an OS defines the min/max RAM a program may access. When 70 programs are running simultaneously, they all access the same RAM pool. The OS determines who gets which piece of RAM. An OS can have logins and file permissions (such as read-only or modify) which the programs must respect. The OS does allow and block/deny access to pieces of hardware based on rules.
A given OS has a core nature disavowed by most organizations. You only have to look at the origin of each OS to understand its core nature. Microsoft Windows is fundamentally about a single user. Sure, there are server versions of Windows but they don’t scale to the cloud. Microsoft Windows generally maxes out to about 1,000 maybe 10,000 active users accessing a singled installed version of Microsoft Windows Server. However, that single user focus at its core is great for UI programs or even command-line programs that are slanted more towards single user scenarios.
UNIX or Linux is essentially a telecommunications OS. The design origin was about multiple, simultaneous data streams, users, and programs to the maximum extent the hardware will allow. That led to a fundamentally modular design in which parts can be arranged, removed, and optimized as long as core POSIX interfaces were maintained. The OS originated out of AT&T and became the collective work of universities, science and engineering non-profits, standards bodies, numerous talented volunteers, and highly motivated commercial services companies. Today, it is the foundation for cloud computing, embedded hardware, networking, and computer based hardware that do not require a Microsoft-based user interface.
The guidance in this article will provide brief pointers to how to engage this process using Microsoft Windows. I am no stranger to Microsoft Windows as I have used it at deep technical level for decades but for the purposes of creating software using either Microsoft COM or Microsoft .NET. As such, I will briefly explain use of Microsoft Visual Studio.
Given the preceding, most of the screen shots and instructions shown involve a Linux environment. The process described is largely independent of OS. You can apply the overall process to Apple, Windows, UNIX, and Linux, but the latter is emphasized. A Linux-based OS is what I privately and personally use. That includes open source projects defined through a C++ software development process. The primary reason for favoring Linux in my case is flexibility.
You never want to be limited to 1 copy of an operating system. Microsoft Windows is super expensive. You also should not have to prove you are a developer in order to have more flexibility. Microsoft Windows can also be quite expensive on a mobile data plan. It can be easier to reduce the size of a Linux environment which benefits backup, recovery, stability, and security. Running multiple copies of Linux “at the same time” on a single computer can be less of an issue. The installs and setup of certain kinds of software on Linux is faster and often more repeatable (over longer time periods) than the equivalent process on Microsoft Windows. At a practical level, Linux works better in certain areas.
A software developer can more smoothly automate software development preparation on Linux. That can take the form of a simplified processes. Those processes include: OS setup; OS maintenance; OS day-to-day use; OS integration with development; software tools setup; software coding and binary file creation; software testing, debugging, and quality assurance; application development life cycle; and data management (databases and files). Every last bit of that is available on Microsoft Windows, but with the right approach, it executes more smoothly on Linux leading to better immersion in software development when needed. By way of example, on Linux software development is not just a click, but a keystroke away.
Operating System Choices
At the end of the previous section, I established that this guide emphasizes a UNIX-centric approach to software development. Several choices exist in that direction. The option I use is listed last.
UNIX based Software Development on Apple
An Apple laptop or desktop offers a UNIX based environment. Everything I mention in this article can be done on an Apple laptop or desktop. The advantage of an Apple environment is you have commercial support from Apple if you encounter hardware and software problems. It is also a direct route to the Apple App Store. If you also want to test your software on Microsoft Windows and Linux, you can use a virtual machine to accomplish this on the same Apple hardware.
UNIX based Software Development on Windows
Much earlier versions of Microsoft Windows had a UNIX layer that did not really see wide adoption. It was called Services for UNIX. Microsoft Windows 10 introduced a Linux layer based on Ubuntu Linux. That is one way to apply the same tools mentioned in this document. Another is to use a virtual machine to run a full Linux distribution. Last, you can install CygWin and GNU tools to accomplish the same. I am not a fan of CygWin but do advocate the virtual machine approach.
UNIX based Software Development on Linux
A laptop or desktop does not have to run Windows. You can erase Windows and install a Linux-based OS instead. That is what I have done on my own computers for the last 9 years. I am not a fan of dual-boot setups. I am also not suggesting you replace Microsoft Windows on a whim as that does carry huge risks for the unprepared. However, the procedure is well documented on the Internet. It consists of downloading an ISO file for the relevant Linux distribution and applying it to a USB flash drive in a particular way. You then boot the computer off the USB flash drive to install Linux as the primary OS.
UNIX based Software Development on Linux using a VM
Another option exists if you already use Linux but would like to further isolate the software development aspects. Setup a virtual machine (VM) in your OS. The VM would contain a copy of the Linux OS of your choice. I once did this exclusively but I now do it partially. I think it is a good idea to strive for this but you definitely want to do this for package building (rpms and debs), web development, and database modeling. Know that fully containerized as well as fully isolated VM based software development in C++ is possible. This is a great option if you are only building command-line programs, engines, frameworks, and libraries as well as the aforementioned types of applications.
UNIX based Software Development on Fedora
The option I have use is to maintain active C++ development tools on my main OS install. I prefer the approach using VMs. Isolation of the code compile, build, and test process works very well in a VM except when dealing with desktop user interfaces. You can do it, but it is not as smooth as directly running the desktop UI program on your main OS and cycling through code edits, compiles, debugging, and subsequent runs of the program. I chose Fedora because it comes from Red Hat but is more bleeding edge but yet more stable than Ubuntu while retaining high compatibility with a lot of hardware. Also, I heard the person who created Linux tends to use it.
Other Operating System Tasks
I will discuss the following items later in the article. I introduce them here so you know that we are not finished with the operating system topic. When we refer to the OS again, it will be in the context of using it as part of actual software development processes. The follow-on tasks include OS updates, folders, and files in general. However, now we turn our attention to text editors. The assumption is you have chosen an OS and have it fully installed at this point.
Text Editor Basics
Our coding tool of choice is not some big time software environment comprising gigabytes of files; long updates; and filled with distractions. Instead, we will use gedit found in the /bin directory on Fedora Workstation. It is a program that is 16 KB and automatically comes with Fedora. You can type in it and save what you typed to a file. That is basically what we need. Of course, it also allows us to search for text in a file, highlight text, cut, copy, and paste all of which helps when typing information.
When you open a text editor, it usually has a place in the middle where you can type anything you want. A menu exists somewhere in the text editor with a function to save what you have typed. An example of both conditions is shown here.
A useful aspect of the gedit text editor is each file shows in its own tab. A file list appears on the left side. You can double-click or finger tap a file on the left or click the open menu function to select a file in some other location. Again, the middle part of the screen is where you can type information. The save function at the top allows you to update the file with any new edits you have made. This is basically the tool you use to write C++ code. Similar tools like it exist on Microsoft Windows in the form of Notepad or Notepad++. Hundreds of text editors exist. Use the one you prefer. Most desktop operating systems automatically comes with a basic text editor requiring no additional install.
Text Editor Use in Software Development
If you understand how C++ code may be written and how a code file could be produced, then you are at the right point in this discussion. Otherwise, you need to make sure you understand all the preceding articles in this series and have the requisite ability to write C++ code. Once you are able to write C++ code with varying levels of confidence, a text editor is the tool you use to compose the code. The code you write is saved to one or more files.
You will create and edit other files in this process to include scripts, make files, configuration files, and a litany of other files. The program itself may create files you later inspect in the text editor. Source code is often opened in a tab adjacent to one containing the file created, modified, or accessed by the program based on that source code. The text editor is where code originates and the same place where it is changed, expanded, reduced, enhanced, or otherwise applied to a variety of purposes. Fluency in the use of a text editor has a huge impact on your productivity.
Whenever you see a code file or any text file you want to inspect or evaluate, a text editor is a primary tool to accomplish this. When you write your engine code as mentioned in the previous article, you are building it in the text editor. The command-line interface that is the topic of this article is also created in a text editor. With the command-line interface, you are writing a source code file or files that tie a main function directly or indirectly to all other functions and data defined in other source code files.
Recall that more elaborate software development tools called IDEs such as Microsoft Visual Studio, Apple Xcode, Eclipse, and Qt Creator also have a text editor at the heart of those code editing programs. The difference is those text editors have a significant amount of functionality to help you write the code faster, better, and smarter. Those editors automate a lot of the typing and evaluation of code. However, the extra functionality provided has costs I alluded to earlier. I will use an IDE in a work environment as there are aspects to IDEs that work well in a team environment. The principles involved in using a text editor still apply. Last, when an IDE is temporarily out of service due to a bug, a bad update, or other issues, skills in using a basic text editor can keep things moving along.
Folders and Files
In a desktop operating system, files are usually saved in a folder. A folder is not the only place a file can reside. They can also reside in other files; database columns; specialized chips; or copies migrating indefinitely between routes on a network like the Internet; and more places and conditions besides these. A file does not even have to be a file actually but that is a large topic. When writing C++ code, the source files that contain that code will reside in folders. The executable binaries that result from that code will also exist in folders. Folders can be navigated in two common ways.
Folders and Files using a Folder Browser
A folder browser has been a feature of desktop operating systems for a few decades. The basic way they work is they are a UI that shows a list of folders. Each folder you click, touch, or speak shows a list of folders and files organized under that folder. You can descend and ascend folders in this way and open the files that exist in a folder.
In the following example we descend from the main folder to the Music folder. Under the Music folder was a folder named Soweto Jams. We go into this folder and find a Playlist folder, a Lyrics file, and a few mp3s. The files are actually empty to illustrate that the folder browser program only really cares about folders. As long as the folder is in good shape (you have permission for example), you can browse whatever is inside.
You will use a folder browser to visit the folder where you keep your source code files. That directory will appear similar to the following. Certain files you double-click on, touch, speak open, or right-click and select an application for will open in the program associated with that file. It goes without saying you have to be able to find your files.
Folders and Files using a Terminal (Command-Line)
I am using the words terminal and command-line interchangeably but they are distinct things. Hereafter, I will refer to both as a command-line as that is the more common colloquial term widely used. You can also browse folders and files in a command-line environment. The largest difference between browsing files in a folder browser UI and a command-line is the way you browse and interact with folders and files.
A command-line lives up to its name 100%. You will type a command for everything. With that comes complete flexibility that is often useful in software development, data analysis, and time saving batch data manipulation. That is among the chief reasons the command-line still receives emphasis even after decades of visual editing and data manipulation tools. One does not replace the other entirely, they are complementary but the command-line tends to remain more consistent and thus serves as a reliable means to productively do things over time.
The following repeats what we did in the previous section where we used a visual UI to browse folders and files. Except, this time, we are going to use the command-line instead to do the exact same thing. We begin with browsing the music directory.
The first step is to open a program called the Terminal in Linux desktop OS’, UNIX desktop OS’ (including Apple), or the Command Prompt in Windows.
Next, we use type cd Music to go into the Music directory. Afterwards, we type the ls command to show what is in the Music directory. Please press enter after each command.
I use the ls command twice and add -gGh in order to list out the folders and directories a specific way.
If you never used the command-line before, that is the briefest of introductions. Entire books are written on them and I encourage becoming familiar with basic commands. I do not mean to go too off topic, but Linux and UNIX command-lines are programming environments in their own right. Knowledge of simple Bash shell scripting can be a way to do quick, simple automated tasks without writing a full fledged program to do the same thing. Returning to the topic at hand, the command-line environment is one in which a program we write can be called up and executed simply by going to the folder where that program resides; typing the file name of that program; and seeing what happens. A benefit of the command-line in this case is even if the program has a problem that prevents it from running, we will know that whereas in many cases we wouldn’t if we were only dealing with a UI activated through the folders and files UI.
This is the turning point in the article and the series. We now begin to accelerate our actions as the prerequisites has been discussed. Everything up to this point is to acclimate you to the tools and environments many software developers use. Since you have access to the command-line, we shall move full circle back to the operating system.
Operating System Updates using the Command-Line
You can install development tools, text editors, visual tools, office programs, and update the operating system in Linux using the command-line. The example we use here involves Fedora Workstation version 29, but a similar process exists in Ubuntu, SUSE, OpenBSD, CentOS, RHEL, and Apple.
Observe the following steps in Fedora OS. The dnf utility is useful in upgrading the operating system, installing and removing software.
At the command-line type sudo dnf upgrade. Press enter.
Once you press enter, the dnf utility contacts Fedora servers to pull down information about the latest updates that exist. It is not checking your system at this point, it is merely getting the latest updates database.
Once the updates database is updated on your computer, then the entries in that database is compared to the versions of the software you have installed. I am over simplifying what it is doing, but this is basically what we get. A list of updates; their cost in terms of download size; and control over whether or not to download and install them. Although we can do much more with the dnf utility than what I show here, I am only showing the most common way it is used to update your system.
I type Y for yes. Press enter and updates are downloaded. After they download, they are installed. The specific module being downloaded is shown on the left. The dnf utility will attempt to download multiple packages at the same time. The current network speed as the download occurs is shown on the right along with the amount of data downloaded until finished. Any hiccups are shown as well such as reset network connections, broken connections, and temporarily unavailable network locations.
At the conclusion of the update managed by the dnf utility, a summary is shown at the end. You can type exit to leave the command-line or otherwise log out.
Write a Development Tools Setup Script
You can do more with dnf than just apply updates. You can install software. In our case, we need additional software in order to develop software and dnf is one way to do it. Instead of typing the commands directly on the command-line, we will do this more carefully. We can type the commands into a file so that it is more convenient to edit the commands if we made a mistake.
Type the following in a text editor.
Save the file with a .sh extension. Linux does not care about extensions, but for us, it clearly identifies this file as a script that runs in the command-line.
After you have saved the file, you will notice that gedit color codes the text. Linux may not distinguish file extensions, gedit certainly does. The file is recognized as a shell script and gedit’s vocabulary identifies the parts that are actual commands or parameters of emphasis.
Run the Development Tools Setup Script using the Command-Line
Linux needs to identify the file as a kind of executable. We can go into the command-line and use the chmod command such as chmod += rwxX or we can use the properties window in the folder and files browser (which in this case is a program called Nautilus).
In the permissions tab, choose the option to “Allow executing as a program”. The benefit of doing it this way is it is quick and consistent as I am sure my chmod example has imperfections even though it will still work.
After you have set the right permission on the script file, it will be highlighted differently in the command-line when you run a list command to show files in the folder it resides. Not all command-lines highlight files in this way so you can also refer to the first column which shows an x in specific positions to denote the execute permission for relevant users and groups.
You can then run the script by typing ./dnf_install_development_tools.sh
If you did everything correctly up to this point, the script contents will be conferred to the command-line and run the same as if you typed them and pressed enter.
With that established, we are nearer the point of actually creating the command-line interface for the C++ engine we coded in the context of the previous article. Your actual engine may vary from the example, I presented in the article #6 (the previous article topic). The process for setting up the engine is generally the same as what was presented in that article. Building the command-line interface goes the same way in nearly all cases.
Command-Line Executable Warm-up
If you never created a command-line executable or it has been a long-time since you have done so, the following will walk you through creating one in Fedora Linux. This shows the most basic command-line example. All other command-lines you create will be a variation of this but often with more lines of code and possibilities for how this code module is structured. The importance of this example is that if you ever create a command-line interface it just turns out wrong, you can always fall back to this basic template and start again.
The example shows the most basic example of a program you can write for the command-line. I also show the most basic way to use a compiler on the command-line to turn the code into a command-line program file. You can then run the program represented by the program file. We start this process by opening a command-line interface (Terminal in Fedora Linux Workstation).
Type ~ and press enter.
Next, type ls -gGh to show all the folders and files in your home directory.
If you never added a folder or file to your home directory, then it will look like the following.
Type mkdir code_example and press enter.
Type reset && ls -gGh and press enter.
You will now see the folder titled code_example in the directory listing.
Navigate to that directory by typing cd code_example and press enter.
Type reset and press enter.
Your command-line screen should be completely clear except for the prompt.
Type ls -gGh to list the folders and files. You will see 0 folders and files.
We will use the touch command to make a blank file. Type touch cmdexmaple.cpp and press enter.
List the folder and files in the current folder to see the result. You should have 1 file listed.
We will not edit the blank file on the command-line using vi.
Type vi cmdexample.cpp and press enter.
You see nothing but blank lines. You are in command mode.
Type lower case i and press enter to go into edit mode. The status at the bottom will say INSERT.
Type out the following. When you are finished, typing out the example, press the ESC key.
Type :wq and press enter.
List out the folders and files to see the result.
You have created a single C++ source code file that specifies and command-line program.
Type g++ cmdexample.cpp -o test and press enter.
This translates the code into a program file name test.
You can run the new program as follows: Type ./test and press enter.
Notice that the program stays up until you press a number or letter followed by the enter key.
Once you press the enter key, the command-prompt returns to you.
You can also press Ctrl+C to exit the program (not recommended unless the program is truly stuck).
When you run ls -gGh, you will notice that the file named test is highlighted differently. Not all command-lines do this, but the default command-line environment in Fedora Linux’s Gnome Desktop highlights the executable files in green (if you have permission to run them). A program is not automatically executable just because it was compiled into a program file in Linux. No, in Linux, you have to grant files executable permission. Once you do that, then yes, those files should be able to execute computer or command-line shell instructions.
We can also skip the preceding steps by using a visual text editor. You can open gedit and either save a new document as cmdexample.cpp or open the one we created earlier by using the touch command.
A fresh install of Fedora Linux Workstation will have gedit show files as follows. Notice that gedit recognizes files based on their file extension and color codes the lines as appropriate.
You can change your preferences so that you see line numbers. This is a huge assist when you compile code and have errors that show the line number. You can then trace back to the line where the problem occurred.
Create a Build Script
Invoking the C++ compiler on the command-line in a basic way is all well and good for the most basic examples. Later, you will do more with the compiler and possibly directly use the linker as well. Going from a 4-part command statement such as g++ input-file -o output-file to a more extensive one involving multiple options, and a sequence of compilation and linking can become daunting to manage. Several tools exist to systematically address the translation of source code into binary executables.
The program known as make is available on multiple desktop and server operating systems. One of the valuable aspects of make is it does a great job in knowing which source files to re-apply if they have changed versus those that did not. That can greatly speed up rebuilding the executables for a larger project. You will need to apprise yourself of the make manual to get the best use of it.
Another approach is to use various build script assistants such as CMake, autotools, and others. Many individuals and groups use them and they can streamline the build process. Again, you will need to study the relevant build system carefully to apply it well.
A third approach and the one I currently use is also the simplest. You can create a direct build script. The benefit of a direct build script is you essentially write the build statements yourself in the manner most suited to your situation. It is very practical for small to medium projects as well as situations that can benefit from a quickly produced build script that can evolve. Nothing precludes the introduction of make or autotools into the direct build script. That means the direct build script can evolve into the other types.
The following is a basic build script.
Save the build script as buildcmd.sh
Notice that gedit color codes the script and the file is listed on the left side for easy access.
Go to the folders and files browser.
Navigate to the folder where you saved the build script.
Right-click on the script file. Go to the permissions tab and check the execute checkbox.
You can now run the script in the command-line and now whatever you placed in this script will run just as if you typed it. You did type it but if you typed it properly then it will run properly each time you run it.
Build a Command-Line Interface for the Engine
The following example shows a single source code file named news_cli.cxx that specifies the command-line interface to the Gautier RSS news engine that was used as an example in the previous article in this series. I highlighted the files on the left and their citations in the file in the main part of the text editor.
Notice the strategy I applied here in which the command-line interface is in the same folder as the visual user interface (news_reader.cxx). This allowed me to simplify the software development for a single project. However, you may prefer a different approach depending on the project.
The source code needs a build script and you will notice on the left side that there is a highlighted file named build_prog_newsc.sh that also pulls in 3 other build scripts. The reason it pulls in 3 others is that the build script for the visual user interface also uses those items referred to in those 3 scripts. Depending on the code update cycle, I want the build for the command-line or the user interface to proceed in an identical way regarding the software code for the main engine that fundamentally defines the program. In other words, I want the engine built the exact same way for both the user interface and the command-line.
I show the build script for the command-line interface. Notice that it is much more involved than the simple example earlier. If you do not immediately understand the parts used, no problem. Each piece is documented in the relevant documents for g++, bash, and ld. Most documentation for g++ can be found in reference to the GNU Compiler Collection. You will see 3 other tabs for the additional build scripts forked from this script.
The starting point for the external script execution process is line #12. See that on that line the script for the engine common to the command-line and user interface is built. If you inspect that script, you will see a similar pair of lines for file and http discussed in the 6th article in this series. What this ultimately means is the scripts run in sequence. File is built first, http is built second, followed by the engine and then the command-line interface. The sequence is not required but ensures you catch errors at the bottom of the code stack since modules further up depends on modules at the bottom.
Fix Build Errors
Though it took some effort to get to this point in the article, in many ways, what we have discussed is the easier part. The difficult part is designing, typing, and implementing code that works. Before you are able to run a program, you must compile the program (or have it in correct form). Since C++ programs are often “ahead-of-time-compiled”, you have the challenge of meeting the requirements of the compiler.
The initial goal is to attain a minimally running program. Minimally running refers to a program that can come up without an immediate crash. It may crash later, but the first user interface screen (or scenario) comes up and stays up until a follow on operation (that may or may not cause a crash) or in the case of a command-line program, the program runs to completion (with or without output) and returns to the prompt without a crash.
After you have written the code, you have a 3-part process you have to execute before you have a minimally working program:
- Finished source code
- Compiler translation of the source code
- Linking of the compiled code into an executable
Understand the Build Cycle
Step 1 is not complete until the code is fully recognized as having no technical syntax, grammar, and usage errors by the compiler in step 2.
Step 3 is not complete until the compiled code in step 2 is fully recognized as linkable by the linker in step 3. You will not get an executable for C++ source code until you fulfill the requirements of this step.
When you use g++, it gives you the option to declare which step applies to a given file you pass to g++. If you use g++ -c, then you are in step 2. When you use g++ without the -c, that implies step 2 and 3. You can also use another program (indirectly used by g++ or gcc) named ld for step 3 exclusively. However you go about it, you must meet the exacting requirements of these steps.
Other programming languages such as C# and Java have the same requirements but are often hidden behind an IDE. The same steps and similar compilers on a command-line are available for both of those languages for scenarios similar to those outlined in this document. I mentioned that to note that this process is active in many software languages to varying levels of obviousness.
After you pass the 3rd stage, you can attempt to run the program. You can have errors when you compile the code. If you compile the code on the command-line then you will see a list of errors you must address before you can proceed to the linking stage. Any errors you have at the link stage will show on the command-line and you must address them before you even have a program file you can run.
What we just discussed are technical errors. These errors, their resolution, mitigation, and prevention is what, in practice, differentiates someone who reads about programming versus someone who can do it all the way. Logic errors related to the situation the program addresses is a different matter that also requires skill but you cannot address them if there are technical errors preventing the creation, existence, and operation of a program in the first place. Once you can build programs that can run without regular crashes and premature exits are you in the domain of actual software development.
Subsequent to successfully creating program executables is unit and scenario testing. You almost never want to just create a program executable and release it without making sure, at a minimum, there are no technical errors. The program should not crash without a good reason. Test each new build of the program as thoroughly as time allows. That leads to the next section.
Run the Program
As you run the program, you are first on the look out for technical errors. Go through each command-line line scenario, or visual user interface screen and make sure that basic functions work properly. Your goal is to eliminate any hidden surprises such as the program crashing if a certain command option is typed, or a file is encountered, or a button is clicked, etc.
In the way of technical errors, the first class of errors you are looking for are Invalid Access Errors. They are called by different names (segmentation faults, null reference exceptions, access violation errors, etc) but they are generally have the same result, premature exit of the program. When these occur with regularity, then you have missed an important detail; coding practice; and design perspective in the program.
All invalid accesses should be designed out of the program or otherwise mitigated unless they should exist on purpose. A good reason to selectively allow invalid accesses is when addressing them could result in the creation of corrupted data or improper security access. In that case, a premature program exit is preferred to somehow allowing things to continue.
After invalid access, you are observing the program for obvious indications of bad situation logic. They generally take the form of missing or incorrect output. Fix missing or incorrect output. Usually, addressing this will take longer than working out invalid accesses. You will often have to run the program many, many times along with numerous data and parameter resets before you can be 100% certain that the code works perfectly. Yes, perfection is possible in computer programs, but requires a tremendous amount of knowledge, thought, patience, commitment, and most of all huge reservoirs of energy over periods of hours to weeks and sometimes months and years to achieve. You want to achieve as much situation logic perfection as possible within the time you have available.
Debug the Program
A special program called a debugger exists that allows you to run your program and observe how it changes data within it. Linux operating systems can have access to a debugger program called gdb. You can use this program to trigger stops at certain points in the code. When the code reaches that point, you can then enter commands to see what the data looks like to determine if the program’s state is correct. You will know if the program is correct because you designed it. Go back to the first 3 articles in the series, you will have a strong sense of what should occur at a given point in a program you have just written. A debugger helps with this by giving you an interactive way to inspect a live running program either at the command-line or in an IDE.
The stops I mentioned earlier are called breakpoints in most debuggers. Again, you can come up with many strategies to apply breakpoints to determine the proper execution of a program. Based on what you learn examining code at various points in its execution, you may decide to adjust the design or make alterations to the source code to specify a better sequence for the program.
Not all problems can be understood by waiting on the code to pause at various points. Oftentimes you just have to let it crash and many debuggers will pause the code right at the point it crashed. You can then use another tool in the debugger called a stack trace to see what path the program traveled to get to that point. For example, gdb has a command called backtrace you can type when it detects a true crash. The information it brings back can assist you in establishing a new breakpoint that triggers a pause right at the line of code immediately before the one that crashes the program. You can then inspect the code at that point to see what data is missing or improperly setup that leads to the crash.
Stack traces can also be written to log text files. That becomes a form of debugging after the fact. There are many things you cannot or did not account for in a given program’s release. Any crash that occurs then is logged to a file you can inspect. Just like the print out in gdb when you type backtrace, this information can be used to devise a test scenario for the program to reproduce the error and identify the flaw that led to the crash. Fixing them then raises the quality and usefulness of the program.
Achieve a Competent Technical Result
Throughout this article and the one immediately preceding it, you have seen the entire process of building a computer program in C++ that you can run on the command-line. We began with understanding how to setup, navigate, and use our overall operating system environment to build programs. We established the prerequisites for software development by ensuring we had a text editor and the right command-line tools. I mentioned the alternative use of visual tools such as Apple XCode, Microsoft Visual Studio, and Qt Creator but emphasized the use of command-line tools in this article.
We walked through the responsibility to keep our operating environment up-to-date. Afterwards, individual steps involved in the use of the command-line environment was covered. That included navigating folders and files; creating a C++ source code file in vi (you can use emacs or nano if you prefer); and compiling that C++ source code file into a program file that we can run.
The article ended with us examining a completed command-line program that ties into the engine described in the previous article. You then observed how a C++ project was organized (knowing it was not the only approach possible) and accessed by build scripts to create a C++ program file. The article ended with the concept of what defines core software development. It is not just writing code but includes the machinery and process to turn that code into working form that you further certify as accurate and functional. The steps, concepts, and overall process described here applies to our next set of articles in this series that describe the creation of a user interface.