Systems Programming/ C and UNIX Alice E. Fischer Lecture 5 Makefiles October 2, 2017 Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 1/14 October 2, 2017 1 / 14
Outline 1 Modules and Makefiles Modular Construction Makefiles 2 Fingerprints: A SHA1 demo program Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 2/14 October 2, 2017 2 / 14
Modules and Makefiles Modular Construction Compiling and Linking A Makefile Defines the Project Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 3/14 October 2, 2017 3 / 14
Modular Construction Modular Programming: Keep It Short and Simple In the old days, people wrote entire programs in one file, and most of the code was inside main(). Such programs are easy to write and difficult to debug. Today, professionals use a highly modular coding style. A project comprises several code files, each with its own definable purpose and its own header file. Functions, including main() are kept short one screen at most. Complexity is handled by writing many short functions. In C++, many short functions are defined as inline functions to improve performance. Within a function, code is restricted to one idea per line. Highly nested or convoluted code is avoided. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 4/14 October 2, 2017 4 / 14
Modular Construction How to Compile and Link Modules We use IDE s to manage our multi-module programs. However, when working on a remote machine, that does not work. For this situation, you need to know how to create and use a makefile. To compile and link a multi-module program, list all the source files in the g++ command: g++ -o p4 -Wall *.cpp../tools.cpp Or, use a makefile (explained later in this lecture). Each module you list will be compiled, in order. After all modules compile correctly, the system will attempt to link all the object files together with the library functions. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 5/14 October 2, 2017 5 / 14
Modular Construction Way is a Modular Style Important? My general rules: If I cannot look at a piece of code and understand it, the code is too complex. Maximize the amount of code you can see on one screen at one time. Use blank lines sparingly. In all cases, you should be able to see the variable declarations from all parts of the code that use them. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 6/14 October 2, 2017 6 / 14
Makefiles A Makefile Defines the Project Every modern IDE gives you a way to specify a set of code files that are all part of a complete application. It lets you add code and header files to the project, compile, build, run, and clean out a project. IDE s are a great invention, but they don t work from a command line, when you are logged into a remote machine. So, even now, it is worth figuring out what a makefile does and how to write one. A makefile is a simple text file that contains shell commands, definitions, and comments. The tab character is NOT the same as a series of spaces; it has special meaning. (Yuk!) A makefile lists all the file dependencies, that is, which files are needed for each step of the build process. The make system will skip a recompiling or relinking step when no file in its list of dependencies has changed. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 7/14 October 2, 2017 7 / 14
Makefiles Writing a Makefile Refer to Chapter 23.1 of Applied C (paper edition) or Chapter 20 of the online version: http://eliza.newhaven.edu/cprog2/chapters/chapter20.pdf. You find these kinds of lines in a makefile: Comments start with # and occupy the entire line. To define a symbol, write the name followed by = and the meaning. The newline ends the definition To use a symbol, write $(symbolname) A target is one compilation, linking or cleanup step. Defining a target takes two lines. The first gives the name of the target, followed by a colon and a list of files on which that target depends. The second line must start with a tab, and it gives the command to execute to create this target. Additional indented lines may follow, if more than one command is necessary. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 8/14 October 2, 2017 8 / 14
Makefiles A Makefile for the SHA1 demo program. # Define flags for compiler. CXXFLAGS = -g -O1 -Wall # Use clang++ for OS-X Lion or Mountain Lion # Change this to g++ for Linux and earlier OS-X versions CXX = clang++ # The crypto library must be explicitly linked in. LIBS = -lcrypto # This program has two modules, shuffle (main) and tools. OBJ = shafile.o tools.o # Get any object file by compiling its source file. shafile: $(OBJ) $(CXX) -o $@ $(OBJ) $(LIBS) Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 9/14 October 2, 2017 9 / 14
Makefiles A C++ Makefile continued. To use this makefile, put it in the same directory as your source code and make that your current active directory. Then type in: make depend This command will scan your files, find the dependencies, create a list of dependency declarations, and append them to this file. To avoid duplication, delete the old dependencies first. On my test application, the dependencies generated were: shafile.o: shafile.cpp tools.hpp tools.o: tools.cpp tools.hpp To build your application, type in make or make game To clean out.o files and the executable type make clean Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 10/14 October 2, 2017 10 / 14
Fingerprints: A SHA1 demo program Fingerprints: A SHA1 demo program What is a fingerprint? Why are they useful? Creating a fingerprint Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 11/14 October 2, 2017 11 / 14
Fingerprints: A SHA1 demo program Fingerprinting a File - crypt A fingerprint (also called a hash ) is a string or integer that is calculated (like a checksum) from all the data in a file. The old, original way to calculate a fingerprint for a text file as follows: Allocate a buffer that is large enough for the whole file Read in the entire file. (Use fread or read, not scanf.) Call char * crypt (const char *data, const char *salt) where data is the buffer that stores your file and salt is the string A1 or any other 2-character string. The resulting fingerprinting can be stored and later used to identify whether the file has been changed without authorization. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 12/14 October 2, 2017 12 / 14
Fingerprints: A SHA1 demo program Is it a Duplicate? One way to detect a file copy is to compare the two files, byte by byte. This is efficient and makes sense if the two files are attached to the same computer. For two files that are stored in different locations, one file would need to be transmitting across the network before it could be compared to the other. This would be much to slow to be practical as a way of detecting duplicates. The cryptographic algorithms used for fingerprinting make it very unlikely that the fingerprints of two different files will match. Thus, we can be fairly confident that if two files have the same length and the same fingerprint, they are copies of the same file. Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 13/14 October 2, 2017 13 / 14
Fingerprints: A SHA1 demo program Fingerprinting a File - SHA SHA256 (a 32-byte hash) and SHA3 are more modern encryption algorithms, but they have no advantage for our purposes and SHA3 may not be universally supported yet. Please use either SHA1 or SHA256. man 3 SHA1 #include <openssl/sha.hpp> unsigned char* SHA1( const unsigned char* d, unsigned long n, unsigned char* md); d is the buffer that stores your file, n is the file length, in bytes, and md is a buffer to hold the answer. It must have space for SHA_DIGEST_LENGTH == 20 bytes. The return value is a pointer to the array that contains the digest. If md is NULL, the digest is placed in a static array. See the demo code: Sha-c++: Alice E. Fischer Lecture 5 Makefiles Lecture 5 Makefiles... 14/14 October 2, 2017 14 / 14