Separate Compilation of Multi-File Programs

Similar documents
CS2141 Software Development using C/C++ Compiling a C++ Program

Project structure - working with multiple les

CS 247: Software Engineering Principles. Modules

Comp Sci 1570 Introduction to C++

OBJECT ORIENTED PROGRAMMING USING C++

2 Compiling a C program

CPSC 427: Object-Oriented Programming

Starting to Program in C++ (Basics & I/O)

The University Of Michigan. EECS402 Lecture 09. Andrew M. Morgan. Savitch Ch Compiling With Multiple Files Make Utility.

QUIZ. What are 3 differences between C and C++ const variables?

INTERMEDIATE SOFTWARE DESIGN SPRING 2011 ACCESS SPECIFIER: SOURCE FILE

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

C++ Programming Lecture 11 Functions Part I

Understanding main() function Input/Output Streams

1.1 The hand written header file

Cpt S 122 Data Structures. Introduction to C++ Part II

Suppose that you want to use two libraries with a bunch of useful classes and functions, but some names collide:

Lab # 02. Basic Elements of C++ _ Part1

Chapter 1 - What s in a program?

Lab 1: First Steps in C++ - Eclipse

Reliable C++ development - session 1: From C to C++ (and some C++ features)

Programmazione. Prof. Marco Bertini

Chapter 1 Introduction to Computers and C++ Programming

The Compilation Process

C++ Basics. Lecture 2 COP 3014 Spring January 8, 2018

Compiling with Multiple Files The Importance of Debugging CS 16: Solving Problems with Computers I Lecture #7

2 nd Week Lecture Notes

Slide Set 5. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

PIC 10A Objects/Classes

COMP322 - Introduction to C++

CE221 Programming in C++ Part 1 Introduction

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

do { statements } while (condition);

Introduction to Programming

Your First C++ Program. September 1, 2010

QUIZ. Source:

11.1 Modular Organization and makefiles.

C++ Code Structure. Cooperating with the Compiler

Binomial pricer (1.1)

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 19 Introduction to C++

Tutorial-2a: First steps with C++ programming

Crash Course in C++ R F L Evans. www-users.york.ac.uk/~rfle500/

Short Notes of CS201

The C Pre Processor ECE2893. Lecture 18. ECE2893 The C Pre Processor Spring / 10

Deitel Dive-Into Series: Dive-Into Cygwin and GNU C++

CSI33 Data Structures

CSE au Midterm Exam Nov. 2, 2018 Sample Solution

CS201 - Introduction to Programming Glossary By

y

5. Applicative Programming. 1. Juli 2011

Intro to Programming & C Why Program? 1.2 Computer Systems: Hardware and Software. Why Learn to Program?

Introduction to C++ Programming. Adhi Harmoko S, M.Komp

OBJECT ORIENTED PROGRAMMING USING C++

CHAPTER 1.2 INTRODUCTION TO C++ PROGRAMMING. Dr. Shady Yehia Elmashad

How to engineer a class to separate its interface from its implementation and encourage reuse.

Computer Programming & Problem Solving ( CPPS ) Turbo C Programming For The PC (Revised Edition ) By Robert Lafore

C: Program Structure. Department of Computer Science College of Engineering Boise State University. September 11, /13

Advanced Programming & C++ Language

C++ Programming for Non-C Programmers. Supplement

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

Programming. Computer. Program. Programming Language. Execute sequence of simple (primitive) instructions What instructions should be provided?

Programming Language. Functions. Eng. Anis Nazer First Semester

LAB: INTRODUCTION TO FUNCTIONS IN C++

Unit 4 Preprocessor Directives

CSE 303: Concepts and Tools for Software Development

Introduction to C++ Introduction to C++ 1

Functions and Recursion

CS242 COMPUTER PROGRAMMING

Object-oriented Programming in C++

1. Describe History of C++? 2. What is Dev. C++? 3. Why Use Dev. C++ instead of C++ DOS IDE?

Chapter 1 INTRODUCTION

CS11 Advanced C++ Fall Lecture 4

Chapter 2: An Introduction to Makeles 5 2 An Introduction to Makeles You need a le called a makele to tell make what to do. Most often, the makele tel

Basic memory model Using functions Writing functions. Basics Prototypes Parameters Return types Functions and memory Names and namespaces

ANSI C. Data Analysis in Geophysics Demián D. Gómez November 2013

Due Date: See Blackboard

Lecture 7. Log into Linux New documents posted to course webpage

Chapter 2: Basic Elements of C++

Objectives. Chapter 2: Basic Elements of C++ Introduction. Objectives (cont d.) A C++ Program (cont d.) A C++ Program

Intermediate Programming, Spring 2017*

Functions in C++ Problem-Solving Procedure With Modular Design C ++ Function Definition: a single

Chapter 2: Basic Elements of C++ Objectives. Objectives (cont d.) A C++ Program. Introduction

Object Oriented Design

Due Date: See Blackboard

CHAPTER 4 FUNCTIONS. Dr. Shady Yehia Elmashad

Computer Programming C++ Classes and Objects 6 th Lecture

COSC345 Software Engineering. Make

Chapter 2: Introduction to C++

C/C++ Programming. Session 10

Chapter 2: Special Characters. Parts of a C++ Program. Introduction to C++ Displays output on the computer screen

Objectives. In this chapter, you will:

Computing and Statistical Data Analysis Lecture 3

COMP322 - Introduction to C++ Lecture 02 - Basics of C++

BITG 1233: Introduction to C++

Implementing an ADT with a Class

Programming with C++ as a Second Language

UEE1303(1070) S 12 Object-Oriented Programming in C++

Multimedia-Programmierung Übung 3

Data Structures using OOP C++ Lecture 3

Tutorial 13 Salary Survey Application: Introducing One- Dimensional Arrays

Transcription:

1 About Compiling What most people mean by the phrase "compiling a program" is actually two separate steps in the creation of that program. The rst step is proper compilation. Compilation is the translation of high level programming instructions into machine language instructions. The input to compilation is a source code le in a high level language such as C or C++. Source code les have extensions such as ".c", ".cpp", or ".cc". The output of compilation is an object le, which is not quite an executable le. Object les usually have a ".o" or ".obj" extension. Consider the C++ code fragment #i n c l u d e <iostream> #i n c l u d e <math. h> using namespace std ; double number ; cout << " Enter a p o s i t i v e number here : " ; c i n >> number ; cout << "The square root i s " << s q r t ( number ) << endl ; The rst two lines (called include directives) tell the compiler to copy the contents of the header les iostream and math.h into the program at those points in the le where the include directive is written. The third line tells the compiler to use the std namespace for resolving symbols. This is necessary because the iostream objects cout and cin are dened within this std namespace. Every declaration and denition in the iostream header le is contained within the namespace known as std. A namespace is essentially just a scope, so all of iostream has scope std. In particular, cout and cin are really known to the world outside of the std scope by their fully scoped names, std::cout and std::cin. If you wrote std::cout instead of cout, std::cin instead of cin, and std::endl instead of endl, you could eliminate the need to use the std namespace. The "using namespace std" instruction tells the compiler that whenever it nds a symbol in the program that is not dened in the program, it should search the std namespace in case it is dened there. Names like cin, cout, and endl are called external symbols in a program because their denitions are not contained in the program itself. The inclusion of the header les <iostream> and <math.h> in the program allows the compiler to determine whether the names cin, cout, and sqrt are being used properly, thereby allowing it to compile the code, but it cannot create an executable module, because the objects associated with the names cin and cout are not dened in your program, nor is the code for the sqrt function. These objects are dened in the library les associated with the header les <iostream> and <math.h>. Because the object cin is dened in a separate le and its extraction function (>>) is dened in that le also, the compiler cannot create a jump instruction to jump to the code that does this stream extraction, because it does not have the memory address of the start of this function. Names like cin and cout that are dened outside of the program module are said to be unresolved at compile time. Figure 1 illustrates how these names are related to tghe collection of libraries stored on the computer. The best that the compiler can do is to create an entry in a table in the code that allows the second stage to solve the problem. This table contains the location of every instruction in the program that refers to a This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Int'l License. 1

name whose location is unresolved, or external, to the program. The second stage is called linking, and it is performed by, not surprisingly, the linker. The linker's job is to nd the unresolved names listed in the table in the executable module and to link them to the actual objects to which they refer. To link a name means to replace it with the address to which it refers. Of course a name cannot be associated with an address unless the object that it names actually has an address, which implies that before the name can be resolved, the associated object must be incorporated into the address space of the executable le. There is a special type of linking called dynamic linking that is an exception to this rule, but how that works is a subject for a dierent chapter. Static linking is the type of linking in which all code needed at runtime is actually copied into the program. Figure 1: Conceptualization of a Program Using a Software Library. 2 What is Separate Compilation? A project should be organized as a collection of small les that can be compiled individually. This is what we mean by separate compilation. Typically, large classes are given their own les and smaller classes may be grouped together into a single le. Sometimes collections of functions that are not members of any class are placed into a separate le. As long as each of the les is included in the project le, the compiler will usually compile each of them when it is given the instruction to compile the project. A set of functions that all provide various forms of randomization, for example, would be placed into two les named myrandstuff.h and myrandstuff.cpp. The myrandstuff.h le contains the function prototypes.. Files that end in a ".h" are called header files. They are also called interface les. They are usually not compiled by the compiler. Instead they are included in other les so that the compiler will have access to the symbols dened in these header les at compile time. The myrandstuff.cpp le contains the denitions of the functions dened in the header le. The les will usually have the following form. #i f n d e f MYRANDSTUFF_H #d e f i n e MYRANDSTUFF_H Listing 1: myrandstu.h // whatever header f i l e s need to be included go here // any t y p e d e f s or other type or c l a s s d e f i n i t i o n s go here // d e s c r i p t i o n o f func1 void func1 (... ) ; This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Int'l License. 2

// d e s c r i p t i o n o f func2 void func2 (... ) ; // and so on #e n d i f // MYRANDSTUFF_H #i n c l u d e " myrandstuff. h" Listing 2: myrandstu.cpp void func1 (... ) { // implementation f o r func1 } void func2 (... ) { // implementation f o r func2 } // and a l l implementation code f o r remaining f u n c t i o n s here The main program only includes the header les, not the.cpp les, so that it can make reference to functions declared there and used in.. Therefore, the main program will contain a line of the form among the other header les included by it. Notice that the header le name is enclosed in double quotes, not angle braces. When the le to be included is in the same directory as the program, its name should be in double quotes. When the compiler is run to compile the main program, it begins by calling the macro preprocessor (named cpp). The macro preprocessor creates a temporary copy of the main program as its output. As it reads the main program le, it looks for lines that begin with #. When it sees the #include directive, it nds the le that is to be included and copies it into the copy of the main program at the point at which the #include directive was found. Every included le is copied into this temporary copy of the main program. Suppose that you have a second implementation le, say mylist.cpp, that uses the functions declared or the types dened in myrandstuff.h. It is possible that the header le mylist.h needs to include myrandstuff.h. Supoose also that the main program uses the functions declared in mylist.h. Then mylist.h has the line and the main program has the two lines #include "mylist.h" When the compiler runs, it calls the macro preprocessor, cpp, rst. cpp sees the #include directive to copy myrandstuff.h and will copy the myrandstuff.h le into its temporary copy of main. It would copy it twice, unless we prevented it, because when it includes mylist.h, it would copy mynode.h again because of the #include directive in that le. But in fact we did prevent this from happening. This was why the following three lines must appear in your header les. This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Int'l License. 3

#ifndef MYNODE_H #define MYNODE_H #endif The rst line #ifndef MYNODE_H translates to if the macro symbol MYNODE_H is not dened then continue reading and processing until the matching occurrence of endif. If it does exist, then skip reading code until immediately after that matching endif. If there is no symbol already dened, then the next line #define MYNODE_H denes it, and the code is read and processed. By dening the symbol here, the user prevents the macro preprocessor from reading the code reference in the mynode.h le twice. These lines are often called a header guard. You can use whatever symbol you want in this directive, but it must be unique in your project. It is best to follow a convention that ensures this uniqueness. The most common is to use the symbol consisting of the le name. in caps, with an underscore between the root and the extension. Some people use a leading underscore also. 3 Compiling and Linking the Program When a project consists of a collection of les, some of which are header les and their corresponding implementation les, and of course a single le containing the main() function, it is compiled and linked in a specic way. Assume the project contains the les f1.h, f2.h, f3.h, f1.cpp, f2.cpp, f3.cpp, and main.cpp and that main.cpp includes all header les, but that the remaining.cpp les include only their own header les. The set of steps that must be taken if this is to be done manually, using g++, for example, is g++ -c f1.cpp g++ -c f2.cpp g++ -c f3.cpp g++ -c main.cpp This creates the object les f1.o, f2.o, f3.o, and main.o. Then the main program executable would be created by linking these together, using which would name the executable progname. Although we call g++ a compiler, it is not actually compiling in this last step; it is just linking the les and create the program named progname. g++ is just one of many components of the Gnu Compiler Collection, and it is smart enough to know that only linking is required in this last command. Suppose after creating the executable that you decide to make changes to f2.cpp and that you then edit the le f2.cpp. In this case, you only need to do two steps to rebuild the program: This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Int'l License. 4

g++ -c f2.cpp because only the object le f2.o must be changed, and the main program needs to be relinked to it. If you edit a header le, such as f3.h, then you would also do two steps: g++ -c f3.cpp because presumably f3.cpp includes f3.h with an #include directive, which means that a change to f3.h causes a change to the temporary le created by the preprocessor when it reads f3.cpp and hence the object le f3.o needs to be rebuilt, and the program relinked. All of this can be simplied by using a makele. A makele is a le that is read by the make program. It contains a set of instructions for carrying out various tasks, usually for building programs. This tutorial on separate compilation does not cover how to create makeles, but I include one here that could be used to keep the program progname up to date whenever any of the les change, with minimal recompilation and linking: CXX := /usr/bin/g++ CXXFLAGS += -Wall -g OBJECTS := main.o f1.o f2.o f3.o all: progname progname: $(OBJECTS) <TAB>$(CXX) $(CXX_FLAGS) -o progname $(OBJECTS) main.o: f1.h f2.h f3.h clean: <TAB>$(RM) $(OBJECTS) The <TAB> means that there should be a literal tab character in this position. Anything else and make will not work. To build the program or update it, one just types "make" on the command line in the directory containing this makele and the program les. The makele should be named either makefile or Makefile. This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Int'l License. 5