Using Programming Tools for Ubuntu - Programming Linux - Ubuntu Unleashed 2017 Edition (2017)

Ubuntu Unleashed 2017 Edition (2017)

Part V: Programming Linux

Chapter 38. Using Programming Tools for Ubuntu


In This Chapter

Image Programming in C with Linux

Image Using the C Programming Project Management Tools Provided with Ubuntu

Image Using the GNU C Compiler

Image Graphical Development Tools

Image References


If you’re looking to learn C or C++ programming or Java programming, this part of the book isn’t the right place to start. Unlike Perl, Python, PHP, or even C#, it takes more than a little dabbling to produce something productive with languages like these, so this chapter is primarily focused on the tools Ubuntu offers you as a programmer.

Whether you’re looking to compile your own code or someone else’s, the GNU Compiler Collection (gcc) is there to help. It understands C, C++, Fortran, Pascal, and dozens of other popular languages, which means you can try your hand at whatever interests you. Ubuntu also ships with hundreds of libraries you can link to, from the GUI toolkits behind GNOME and KDE to XML parsing and game coding. Some use C, others C++, and still others offer support for both, meaning you can choose what you’re most comfortable with.


Why use C or C++?

Every language has its benefits and its shortcomings. Some languages make life easier for the programmer, but at the expense of runtime. Languages such as Perl and Python and even Java make it hard for the user to guarantee that memory is fetched sequentially or that it fits in cache, due to things such as checks on the bounds on each access. They are useful languages, but they run slower than languages that are harder for the programmer, but faster at runtime like C or Fortran.

For some programs, such as short shell scripts or a quick one-liner in Perl to search text in a file, the difference in the runtime speed is negligible. On a desktop computer, it might not matter that your music player is written in Python, and if it seems slow, then buying a newer, faster desktop system might be an acceptable solution.

There are some applications, however, where the time needed to run your program can make a big difference. For example, using a slow-to-run language to perform calculations on scientific data, especially if you are doing it on High-Performance Computing (HPC) resources like a supercomputing cluster is foolish; to take advantage of the platform, it is both time- and cost-effective to use the fastest language available to you, like C.

This idea was reinforced in a 2011 conversation between Matthew Helmke and Dan Stanzione, then deputy director of the Texas Advanced Computing Center at the University of Texas at Austin. Stanzione said that HPC computing resources are expensive, so it is often wiser to spend grant money to hire a good C programmer for a year than it is to run a bioinformatics program written in Perl or Python on an HPC system. As he put it, “If your computer costs $2,000, the programmer’s time is the dominant cost, and that is what drives software development. If your computer costs $100 million or more, then having a programmer spend an extra month, or year, or decade working on software optimization is well worth it. Toughen up and write in C.”


Programming with Linux

C is the programming language most frequently associated with UNIX-like operating systems such as Linux or BSD. Since the 1970s, the bulk of the UNIX operating system and its applications have been written in C. Because the C language doesn’t directly rely on any specific hardware architecture, UNIX was one of the first portable operating systems. In other words, the majority of the code that makes up UNIX doesn’t know and doesn’t care which computer it is actually running on. Machine-specific features are isolated in a few modules within the UNIX kernel, which makes it easy for you to modify them when you are porting to different hardware architectures.

Because it is so important to UNIX and Linux, we will use C as our example here. Much of what is discussed will apply to other languages, perhaps with slight variations for language-specific features.

C is a compiled language, which means that your C source code is first analyzed by the preprocessor and then translated into assembly language before it’s translated into machine instructions that are appropriate to the target CPU. An assembler then creates a binary, or object, file from the machine instructions. Finally, the object file is linked to any required external software support by the linker. A C program is stored in a text file that ends with a .cextension and always contains at least one routine, or function, such as main(), unless the file is an include file (with a .h extension, also known as a header file) containing shared variable definitions or other data or declarations. Functions are the commands that perform each step of the task that the C program was written to accomplish.


Note

The Linux kernel is mostly written in C, which is why Linux works with so many different CPUs. To learn more about building the Linux kernel from source, see Chapter 22, “Kernel and Module Management.”


C++ is an object-oriented extension to C. Because C++ is a superset of C, C++ compilers compile C programs correctly, and it is possible to write non-object-oriented code in C++. The reverse is not true: C compilers cannot compile C++ code.

C++ extends the capabilities of C by providing the necessary features for object-oriented design and code. C++ also provides some features, such as the capability to associate functions with data structures that do not require the use of class-based object-oriented techniques. For these reasons, the C++ language enables existing UNIX programs to migrate toward the adoption of object orientation over time.

Support for C++ programming is provided by gcc, which you run with the name g++ when you are compiling C++ code.

Using the C Programming Project Management Tools Provided with Ubuntu

Ubuntu is replete with tools that make your life as a C/C++ programmer easier. There are tools to create programs (editors), compile programs (gcc), create libraries (ar), control the source (Git, Mercurial, Subversion), automate builds (make), debug programs (gdb and ddd), and determine where inefficiencies lie (gprof).

The following sections introduce some of the programming and project management tools included with Ubuntu. If you have some previous UNIX experience, you will be familiar with most of these programs because they are traditional complements to a programmer’s suite of software.

Building Programs with make

You use the make command to automatically build and install a C program, and for that use it is an easy tool. If you want to create your own automated builds, however, you need to learn the special syntax that make uses; the following sections walk you through a basic make setup.

Using Makefiles

The make command automatically builds and updates applications by using a makefile. A makefile is a text file that contains instructions about which options to pass on to the compiler preprocessor, the compiler, the assembler, and the linker. The makefile also specifies, among other things, which source code files have to be compiled (and the compiler command line) for a particular code module and which code modules are needed to build the program—a mechanism called dependency checking.

The beauty of the make command is its flexibility. You can use make with a simple makefile, or you can write complex makefiles that contain numerous macros, rules, or commands that work in a single directory or traverse your file system recursively to build programs, update your system, and even function as document management systems. The make command works with nearly any program, including text processing systems such as TeX.

You could use make to compile, build, and install a software package, using a simple command like this:

Click here to view code image

matthew@seymour:~$ sudo make install

You can use the default makefile (usually called Makefile, with a capital M), or you can use make’s -f option to specify any makefile, such as MyMakeFile, like this:

Click here to view code image

matthew@seymour:~$ sudo make -f MyMakeFile

Other options might be available, depending on the contents of your makefile. You might have a source file named hi.c and just run make hi, where make figures out what to do automatically to build the final executable. See make’s built-in rules with make -p.

Using Macros and Makefile Targets

Using make with macros can make a program portable. Macros allow users of other operating systems to easily configure a program build by specifying local values, such as the names and locations, or pathnames, of any required software tools. In the following example, macros define the name of the compiler (CC), the installer program (INS), where the program should be installed (INSDIR), where the linker should look for required libraries (LIBDIR), the names of required libraries (LIBS), a source code file (SRC), the intermediate object code file (OBJS), and the name of the final program (PROG):

Click here to view code image

# a sample makefile for a skeleton program
CC= gcc
INS= install
INSDIR = /usr/local/bin
LIBDIR= -L/usr/X11R6/lib
LIBS= -lXm -lSM -lICE -lXt -lX11
SRC= skel.c
OBJS= skel.o
PROG= skel

skel: ${OBJS}
${CC} -o ${PROG} ${SRC} ${LIBDIR} ${LIBS}

install: ${PROG}
${INS} -g root -o root ${PROG} ${INSDIR}


Note

The indented lines in the previous example are indented with tabs, not spaces. This is important to remember! It is difficult for a person to see the difference, but make can tell. If make reports confusing errors when you first start building programs under Linux, check your project’s makefile for the use of tabs and other proper formatting.


Using the makefile from the preceding example, you can build a program like this:

matthew@seymour:~$ sudo make

To build a specified component of a makefile, you can use a target definition on the command line. To build just the program, you use make with the skel target, like this:

Click here to view code image

matthew@seymour:~$ sudo make skel

If you make any changes to any element of a target object, such as a source code file, make rebuilds the target automatically. This feature is part of the convenience of using make to manage a development project. To build and install a program in one step, you can specify the target of install like this:

Click here to view code image

matthew@seymour:~$ sudo make install

Larger software projects might have a number of traditional targets in the makefile, such as the following:

Image test—To run specific tests on the final software

Image man—To process an include or a troff document with the man macros

Image clean—To delete any remaining object files

Image archive—To clean up, archive, and compress the entire source code tree

Image bugreport—To automatically collect and then mail a copy of the build or error logs

Large applications can require hundreds of source code files. Compiling and linking these applications can be a complex and error-prone task. The make utility helps you organize the process of building the executable form of a complex application from many source files.

Using the autoconf Utility to Configure Code

The make command is only one of several programming automation utilities included with Ubuntu. There are others, such as pmake (which causes a parallel make); imake (which is a dependency-driven makefile generator that is used for building X11 clients); automake; and one of the newer tools, autoconf, which builds shell scripts that can be used to configure program source code packages.

Building many software packages for Linux that are distributed in source form requires the use of GNU’s autoconf utility. This program builds an executable shell script named configure that, when executed, automatically examines and tailors a client’s build from source according to software resources, or dependencies (such as programming tools, libraries, and associated utilities) that are installed on the target host (your Linux system).

Many Linux commands and graphical clients for X downloaded in source code form include configure scripts. To configure the source package, build the software, and then install the new program, the root user might use the script like this (after uncompressing the source and navigating into the resulting build directory):

Click here to view code image

matthew@seymour:~$ ./configure ; make ; sudo make install

The autoconf program uses a file named configure.in that contains a basic ruleset, or set of macros. The configure.in file is created with the autoscan command. Building a properly executing configure script also requires a template for the makefile, named Makefile.in. Although creating the dependency-checking configure script can be done manually, you can easily overcome any complex dependencies by using a graphical project development tool such as KDE’s KDevelop or GNOME’s Glade. (See the “Graphical Development Tools” section, later in this chapter, for more information.)

Debugging Tools

Debugging is both a science and an art. Sometimes, the simplest tool—the code listing—is the best debugging tool. At other times, however, you need to use other debugging tools. Three of these tools are splint, gprof, and gdb.

Using splint to Check Source Code

The splint command is similar to the traditional UNIX lint command: It statically examines source code for possible problems, and it also has many additional features. Even if your C code meets the standards for C and compiles cleanly, it might still contain errors. splint performs many types of checks and can provide extensive error information. For example, this simple program might compile cleanly and even run:

Click here to view code image

matthew@seymour:~$ gcc -o tux tux.c
matthew@seymour:~$ ./tux

But the splint command might point out some serious problems with the source:

Click here to view code image

matthew@seymour:~$ splint tux.c
Splint 3.1.2 -- 29 Apr 2009

tux.c: (in function main)
tux.c:2:19: Return value (type int) ignored: putchar(t[++j] -...
Result returned by function call is not used. If this is intended, can cast
result to (void) to eliminate message. (Use -retvalint to inhibit warning)
Finished checking -- 1 code warning

You can use the splint command’s -strict option, like this, to get a more verbose report:

matthew@seymour:~$ splint -strict tux.c

gcc also supports diagnostics through the use of extensive warnings (through the -Wall and -pedantic options):

Click here to view code image

matthew@seymour:~$ gcc -Wall tux.c
tux.c:1: warning: return type defaults to 'int'
tux.c: In function 'main':
tux.c:2: warning: implicit declaration of function 'putchar'

Using gprof to Track Function Time

You use the gprof (profile) command to study how a program is spending its time. If a program is compiled and linked with -p as a flag, a mon.out file is created when it executes, with data on how often each function is called and how much time is spent in each function. gprof parses and displays this data. An analysis of the output generated by gprof helps you determine where performance bottlenecks occur. Using an optimizing compiler can speed up a program, but taking the time to use gprof’s analysis and revising bottleneck functions significantly improves program performance.

Doing Symbolic Debugging with gdb

The gdb tool is a symbolic debugger. When you compile a program with the -g flag, the symbol tables are retained, and you can use a symbolic debugger to track program bugs. The basic technique is to invoke gdb after a core dump (a file containing a snapshot of the memory used by a program that has crashed) and get a stack trace. The stack trace indicates the source line where the core dump occurred and the functions that were called to reach that line. Often, this is enough to identify a problem. It isn’t the limit of gdb, though.

gdb also provides an environment for debugging programs interactively. Invoking gdb with a program enables you to set breakpoints, examine the values of variables, and monitor variables. If you suspect a problem near a line of code, you can set a breakpoint at that line and run gdb. When the line is reached, execution is interrupted. You can check variable values, examine the stack trace, and observe the program’s environment. You can single-step through the program to check values. You can resume execution at any point. By using breakpoints, you can discover many bugs in code.

A graphical X Window interface to gdb is called the Data Display Debugger, or ddd.

Using the GNU C Compiler

If you elected to install the development tools package when you installed Ubuntu (or perhaps later on, using synaptic), you should have the GNU C compiler (gcc). Many different options are available for the GNU C compiler, and many of them are similar to those of the C and C++ compilers that are available on other UNIX systems. Look at the man page or information file for gcc for a full list of options and descriptions.


Note

The GNU C compiler is a part of the GNU Compiler Collection, which also includes compilers for several other languages.


When you build a C program using gcc, the compilation process takes place in several steps:

1. First, the C preprocessor parses the file. To do so, it sequentially reads the lines, includes header files, and performs macro replacement.

2. The compiler parses the modified code to determine whether the correct syntax is used. In the process, it builds a symbol table and creates an intermediate object format. Most symbols have specific memory addresses assigned, although symbols defined in other modules, such as external variables, do not.

3. The last compilation stage, linking, ties together different files and libraries and then links the files by resolving the symbols that had not previously been resolved.


Note

Most C programs compile with a C++ compiler if you follow strict ANSI rules. For example, you can compile the standard hello.c program (everyone’s first program) with the GNU C++ compiler. Typically, you name the file something like hello.cc, hello.C, hello.c++, or hello.cxx. The GNU C++ compiler accepts any of these names.


Graphical Development Tools

Here we will branch out into information that more obviously applies to other languages. For example, Java is in widespread use and you can develop in Java from Ubuntu.

Ubuntu has a number of graphical prototyping and development environments available. If you want to build client software for KDE or GNOME, you might find the KDevelop, Qt Designer, and Glade programs extremely helpful. You can use each of these programs to build graphical frameworks for interactive windowing clients, and you can use each of them to automatically generate the necessary skeleton of code needed to support a custom interface for your program. If you want to program in Java using your favorite Integrated Development Environment (IDE) or a language with a standard Software Development Kit (SDK), you can do that, too.

Using the KDevelop Client

You can launch the KDevelop client (shown in Figure 38.1) from the application’s menu, or from the command line of a terminal window, like this:

matthew@seymour:~$ kdevelop &

Image

FIGURE 38.1 KDE’s Kdevelop is a rapid prototyping and client-building tool for use with Linux.

After you press Enter, the KDevelop Setup Wizard runs, and you are taken through several short wizard dialogs that set up and ensure a stable build environment. You must then run kdevelop again (either from the command line or by clicking its menu item under the desktop panel’s Programming menu). You then see the main KDevelop window and can start your project by selecting KDevelop’s Project menu and clicking the New menu item.

You can begin building your project by stepping through the wizard dialogs. When you click the Create button, KDevelop automatically generates all the files that are normally found in a KDE client source directory (including the configure script, which checks dependencies and builds the client’s makefile). To test your client, you can either first click the Build menu’s Make menu item (or press F8) or just click the Execute menu item (or press F9), and the client is built automatically. You can use KDevelop to create KDE clients, plug-ins for the Konqueror browser, KDE kicker panel applets, KDE desktop themes, Qt library-based clients, and even programs for GNOME.

The Glade Client for Developing in GNOME

If you prefer to use GNOME and its development tools, the Glade GTK+ GUI builder can help you save time and effort when building a basic skeleton for a program. You launch Glade from the desktop panel’s Programming menu.

When you launch Glade, a directory named Projects is created in your home directory, and you see a main window, along with two floating Palette and Properties windows (see Figure 38.2, which shows a basic GNOME client with a calendar widget added to its main window). You can use Glade’s File menu to save the blank project and then start building your client by clicking and adding user interface elements from the Palette window. For example, you can first click the Palette window’s Gnome button and then click to create your new client’s main window. A window with a menu and a toolbar appears—the basic framework for a new GNOME client.

Image

FIGURE 38.2 You can use the GNOME Glade client to build and preview a graphical interface for a custom GNOME program.

Use an IDE or SDK

Integrated development environments (IDE) and software development kits (SDK) have become extremely popular. While some still prefer to write and edit software using a standard text editor, like nano or vi (covered in Chapter 12, “Command-Line Master Class Part 2”), many programmers prefer using a tool that is more powerful. The first of these started out as a text editor, but as more and more features were added, it evolved into something more. This is Emacs, and it is also covered in Chapter 12. By adding tools and features to make the programmer’s life easier, Emacs unintentionally became the template for modern IDEs.

Some IDEs support multiple languages, like Emacs does. Others focus on only one language. Most include not only programming language specific features like code highlighting, to help you read and browse code more quickly and efficiently, but also contain a compiler and debugger and even build automation tools. If you read through the details earlier in this chapter of using make with C, you can understand the value added.

So, what is the downside? Well, you can’t run a typical IDE on a server because you need a graphical interface, so if you are working on code that will run on a server that only has a command line or text interface available to you, you want to make sure you are comfortable with traditional methods. That doesn’t mean you can’t use a local desktop machine for development using an IDE and then push your code out to the server. It just means you should cover your bases, just in case.

The most commonly used IDEs seem to also be used most frequently by Java developers. We will use three of them as examples in this chapter. Each should be downloaded directly from the provider as this will ensure you install the most current and standard version.

Oracle, which owns Java, provides an IDE for Java called Oracle JDeveloper. It is most commonly used in enterprise settings, where a team of developers work together using a standard tool. It is the least popular of the three mentioned here. You can learn more about it from http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.html.

NetBeans is an extremely popular IDE that works with multiple languages. It is now owned by Oracle, but was started by student programmers who were looking to create more useful tools for their needs. Others asked to contribute code and soon it developed into a commercial program with plugins to extend its capabilities, many contributed by a large supporting community. Sun Microsystems, who developed and owned Java, bought NetBeans and released it under an open source license. When Oracle acquired Sun, it also acquired NetBeans; due to its popularity, it is worth a look. You can learn about and download NetBeans from https://netbeans.org/.

Eclipse was originally created by IBM, but has been spun off to a foundation created just for it. The Eclipse Foundation is non-profit and exists to coordinate efforts of volunteers and companies that contribute time, money, and code to this open source project. Like NetBeans, Eclipse is very widely used and popular. It supports multiple languages and there are many plugins available to extend its capabilities.

An SDK is a set of software development tools that are focused not only on one language, but something narrower like one software package or framework, such as the Android development SDK described in Chapter 43, “Beginning Mobile Development for Android.” SDKs are provided by companies that want to encourage outsiders to write programs that run on the company’s product, such as their platform (like a game system from Nintendo or Sega) or operating system (like Android or iOS). Many open source enthusiasts will not participate in writing code for these platforms, so SDKs are less popular in this environment than they are on Windows and other platforms. Also, depending on the software license used to release the SDK, the potential uses of the code produced using the SDK can be limited and not everyone is comfortable with those limitations. However, many SDKs are in use and if you want to write code for a project that releases an SDK, they generally contain useful code examples, tools, and documentation to make the task much easier. Do your homework and make a choice that you are comfortable with.

Ubuntu has an SDK for developers who are interested in writing apps to run on Ubuntu. More information will be available from the website at https://developer.ubuntu.com/en/apps/.

References

Image www.cprogramming.com—A useful website for learning C and C++.

Image http://gcc.gnu.org/—The main website for gcc, the GNU Compiler Collection.

Image www.gnu.org/software/autoconf/autoconf.html—More information about the GNU Project’s autoconf utility and how to build portable software projects.

Image http://www.qt.io/—The main Qt website.

Image http://glade.gnome.org—Home page for the Glade GNOME developer’s tool.

Image www.kdevelop.org—Site that hosts the KDevelop Project’s latest versions of the KDE graphical development environment, KDevelop.

Image The C Programming Language, by Brian W. Kernighan and Dennis M. Ritchie (Prentice Hall), ISBN: 0-13-110362-8.

Image The Annotated C++ Reference Manual, by Margaret A. Ellis and Bjarne Stroustrup (ANSI Base Document), ISBN: 0-201-51459-1.

Image Programming in ANSI C, by Stephen G. Kochan (Sams Publishing), ISBN: 0-672-30339-6.

Image Sams Teach Yourself C in 21 Days, by Peter Aitken and Bradley Jones (Sams Publishing), ISBN: 0-672-32448-2.

Image Sams Teach Yourself C++ for Linux in 21 Days, by Jesse Liberty and David B. Horvath (Sams Publishing), ISBN: 0-672-31895-4.

Image C How to Program and C++ How to Program, both by Harvey M. Deitel and Paul J. Deitel (Deitel Associates), ISBNs: 0-132-99044-X and 0-132-66236-1.