Building Software Systems. Multi-module C Programs. Example Multi-module C Program. Example Multi-module C Program



Similar documents
How to Write a Simple Makefile

Developing Platform Independent Software using the AutoTool Suite

PetaLinux SDK User Guide. Application Development Guide

Basic C Shell. helpdesk@stat.rice.edu. 11th August 2003

GNU Make. A Program for Directing Recompilation GNU make Version 3.80 July Richard M. Stallman, Roland McGrath, Paul Smith

C Programming Review & Productivity Tools

Documentation Installation of the PDR code

To reduce or not to reduce, that is the question

Setting up PostgreSQL

CMPT 373 Software Development Methods. Building Software. Nick Sumner Some materials from Shlomi Fish & Kitware

Magento Search Extension TECHNICAL DOCUMENTATION

pbuilder Debian Conference 2004

Brent A. Perdue. July 15, 2009

Advanced Bash Scripting. Joshua Malone

TNM093 Practical Data Visualization and Virtual Reality Laboratory Platform

Microsoft Windows PowerShell v2 For Administrators

Channel Access Client Programming. Andrew Johnson Computer Scientist, AES-SSG

GTk+ and GTkGLExt Build Process for Windows 32- bit

An Embedded Wireless Mini-Server with Database Support

Code::Block manual. for CS101x course. Department of Computer Science and Engineering Indian Institute of Technology - Bombay Mumbai

Running your first Linux Program

CSC230 Getting Starting in C. Tyler Bletsch

Professional. SlickEdif. John Hurst IC..T...L. i 1 8 О 7» \ WILEY \ Wiley Publishing, Inc.

#!/usr/bin/perl use strict; use warnings; use Carp; use Data::Dumper; use Tie::IxHash; use Gschem 3; 3. Setup and initialize the global variables.

CPSC 226 Lab Nine Fall 2015

Mike Shal

Supported platforms & compilers Required software Where to download the packages Geant4 toolkit installation (release 9.6)

Learn Perl by Example - Perl Handbook for Beginners - Basics of Perl Scripting Language

USENIX'04 / UseBSD Using OpenBSD and Snort to build ready to roll Network Intrusion Detection System Sensor

Informatica e Sistemi in Tempo Reale

Object systems available in R. Why use classes? Information hiding. Statistics 771. R Object Systems Managing R Projects Creating R Packages

GNU Automake. For version 1.15, 31 December David MacKenzie Tom Tromey Alexandre Duret-Lutz Ralf Wildenhues Stefano Lattarini

Maven or how to automate java builds, tests and version management with open source tools

COMP 356 Programming Language Structures Notes for Chapter 4 of Concepts of Programming Languages Scanning and Parsing

Andreas Burghart 6 October 2014 v1.0

Memory Management Simulation Interactive Lab

Introduction. dnotify

MOVES Batch Mode: Setting up and running groups of related MOVES run specifications. EPA Office of Transportation and Air Quality 11/3/2010

MatrixSSL Getting Started


Sonatype CLM Enforcement Points - Continuous Integration (CI) Sonatype CLM Enforcement Points - Continuous Integration (CI)

Manage2 API. by: J. Nick Koston

CMake/CTest/CDash OSCON 2009

GNU Make. A Program for Directing Recompilation GNU make Version 4.1 September Richard M. Stallman, Roland McGrath, Paul D.

Programming with the Dev C++ IDE

ML310 Creating a VxWorks BSP and System Image for the Base XPS Design

Q N X S O F T W A R E D E V E L O P M E N T P L A T F O R M v Steps to Developing a QNX Program Quickstart Guide

Code Estimation Tools Directions for a Services Engagement

Programming Database lectures for mathema

A Crash Course on UNIX

lug create and edit TeX Local User Group web pages

AES Crypt User Guide

Advanced Customisation: Scripting EPrints. EPrints Training Course

Lab Exercise Part II: Git: A distributed version control system

Object Oriented Software Design

Perl in a nutshell. First CGI Script and Perl. Creating a Link to a Script. print Function. Parsing Data 4/27/2009. First CGI Script and Perl

IEEEXTREME PROGRAMMING COMPETITION PROBLEM & INSTRUCTION BOOKLET #3

Web Services for Management Perl Library VMware ESX Server 3.5, VMware ESX Server 3i version 3.5, and VMware VirtualCenter 2.5

Software documentation systems

NaviCell Data Visualization Python API

How to use PDFlib products with PHP

HPC Wales Skills Academy Course Catalogue 2015

10 STEPS TO YOUR FIRST QNX PROGRAM. QUICKSTART GUIDE Second Edition

1 Introduction. 2 An Interpreter. 2.1 Handling Source Code

Integrating TAU With Eclipse: A Performance Analysis System in an Integrated Development Environment

gbuild: State of the LibreOffice build system

Programming Languages CIS 443

AP Computer Science Java Subset

Porting CodeWarrior Projects to Xcode. (Legacy)

CS 241 Data Organization Coding Standards

Parallel Programming for Multi-Core, Distributed Systems, and GPUs Exercises

Embedded Software Development

Meister Going Beyond Maven

Evaluation of the CMT and SCRAM Software Configuration, Build and Release Management Tools

FOO := $(warning Right-hand side of a simple variable)bar BAZ = $(warning Right-hand side of a recursive variable)boo

Purely top-down software rebuilding

DiskPulse DISK CHANGE MONITOR

USING HDFS ON DISCOVERY CLUSTER TWO EXAMPLES - test1 and test2

Member Functions of the istream Class

32-Bit Workload Automation 5 for Windows on 64-Bit Windows Systems

INTEGRAL OFF-LINE SCIENTIFIC ANALYSIS

Cygwin: getting the setup tool

Version Control Your Jenkins Jobs with Jenkins Job Builder

Installing (1.8.7) 9/2/ Installing jgrasp

Creating a Java application using Perfect Developer and the Java Develo...

Transcription:

Building Software Systems Multi-module C Programs Software systems need to be built / re-built during the development phase if distributed in source code form (change,compile,test,repeat) (assists portability) Simple example: systems implemented as multi-module C programs: multiple object files (.o files) and libraries (libxyz.a) compiler that only recompiles what it s told to Large C programs are implemented as a collection of.c and.h files. A pair of a.c and a.h generally defines a module: a.c contains operations related to one particular kind of data/object a.h exports definitions for types/operations defined in a.c Why partition a program into modules at all? as a principle of good design to share development work in a large project to create re-usable libraries Example Multi-module C Program Example Multi-module C Program Imagine a large game program with an internal model of the game world (places, objects, actors) code to manage graphics (mapping the world to the screen) The graphics code would... typically be separated from the world code (software eng) need to use the world operations (to render current scene) Then there would be a main program to... accept user commands, modify world, update display

Building Large Programs make Building the example program is relatively simple: % gcc -c -g -Wall world.c % gcc -c -g -Wall graphics.c % gcc -c -g -Wall main.c % gcc -Wall -o game main.o world.o graphics.o For larger systems, building is either inefficient (recompile everything after any change) error-prone (recompile just what s changed + dependents) module relationships easy to overlook (e.g. graphics.c depends on a typedef in world.h) you may not know when a module changes (e.g. you work on graphics.c, others work on world.c) Classical tool to build software dating to 70s. Many variants and alternatives but still useful widely used. More recent tools heavily used for particular languages. E.g for Java maven or ant very popular. make Dependencies make allows youto document intra-module dependencies automatically track of changes make works from a file called Makefile (or makefile) A Makefile contains a sequence of rules like: target : source1 source2... commands to create target from sources Beware: each command is preceded by a single tab char. Take care using cut-and-paste withmakefiles The make command is based on the notion of dependencies. Each rule in a Makefile describes: dependencies between each target and its sources commands to build the target from its sources Make decides that a target needs to be rebuilt if it is older than any of its sources times) (based on file modification

Example Makefile #1 Example Makefile #1 A Makefile for the earlier example program: game : main.o graphics.o world.o gcc -Wall -o game main.o graphics.o world.o main.o : main.c graphics.h world.h gcc -c main.c graphics.o : graphics.c world.h gcc -c -g -Wall graphics.c world.o : world.c gcc -c -g -Wall world.c Example Makefile #1 How make Works Easily parsed in Perl: sub parse_makefile( { my ($file) = @_; open MAKEFILE, $file or die; my ($target, $depends) = /(\S+)\s*:\s*(.*)/ or next; $first_target = $target if!defined $first_target; $depends{$target = $depends; last if!/^\t/; $build_cmd{$target.= $_; The make command behaves as: make(target, sources, command): # Stage 1 FOR each S in sources DO rebuild S if it needs rebuilding END # Stage 2 IF (no sources OR any source is newer than target) THEN run command to rebuild target END

How make Works Additional functionalities of Makefiles Implementation in Perl: sub build( { my ($target) = @_; my $build_cmd = $build_cmd{$target; die "*** No rule to make target $target\n" if!$build_cmd &&!-e $target; return if!$build_cmd; my $target_build_needed =! -e $target; foreach $dep (split /\s+/, $depends{$target) { build $dep; $target_build_needed = -M return if!$target_build_needed; print $build_cmd; system $build_cmd; $target > -M $dep; # string-valued variables/macros CC = gcc CFLAGS = -g LDFLAGS = -lm BINS = main.o graphics.o world.o # implicit commands, determined by suffix main.o : main.c graphics.h world.h graphics.o : graphics.c world.h world.o : world.c # pseduo-targets clean : rm -f game main.o graphics.o world.o # or... rm -f game $(BINS) Additional functionalities of Makefiles Parsing Variables and comments in Perl # multiple targets with same sources stats1 stats2 : data1 data2 data3 perl analyse1.pl data1 data2 data3 > stats1 perl analyse2.pl data1 data2 data3 > stats2 # creating subsystems via make parser: cd parser && $(MAKE) # assumes parser directory has own Makefile sub parse_makefile( { my ($file) = @_; open MAKEFILE, $file or die; s/#.*//; s/\$\((\w+)\)/$variable{$1 /eg; if (/^\s*(\w+)\s*=\s*(.*)$/) { $variable{$1 = $2; next; my ($target, $depends) = /(\S+)\s*:\s*(.*)/ or next; $first_target = $target if!defined $first_target; $depends{$target = $depends; s/\$\((\w+)\)/$variable{$1 /eg; last if!/^\t/; $build_cmd{$target.= $_;

Command-line Arguments Command-line Arguments If make arguments are targets, build just those targets: % make world.o % make clean If no args, build first target in the Makefile. The -n option instructs make to tell what it would do to create targets but don t execute any of the commands Implementation in Perl: $makefile_name = "Makefile"; if (@ARGV >= 2 && $ARGV[0] eq "-f") { shift @ARGV; $makefile_name = shift @ARGV; parse_makefile $makefile_name; push @ARGV, $first_target if!@argv; build $_ foreach @ARGV; Example Makefile #2 Sample Makefile for a simple compiler: CC = gcc CFLAGS = -Wall -g OBJS = main.o lex.o parse.o codegen.o mycc : $(OBJS) $(CC) -o mycc $(OBJS) main.o : main.c mycc.h lex.h parse.h codegen.h $(CC) $(CFLAGS) -c main.c lex.o : lex.c mycc.h lex.h $(CC) $(CFLAGS) -c lex.c parse.o : parse.c mycc.h parse.h lex.h codegen.o : codegen.h mycc.h codegen.h parse.h clean : rm -f mycc $(OBJS) core Abbreviations To simplify writing rules, make provides default abbreviations: $@ full name of target $* name of target, without suffix $< full name of first source $? full names of all newer sources Examples: # one of above rules, re-written lex.o : lex.c mycc.h lex.h $(CC) $(CFLAGS) -c $*.c -o $@ # or... $(CC) $(CFLAGS) -c $<< -o $@ # update a library archive lib.a: foo.o bar.o lose.o win.o ar r lib.a $?

Abbreviations Generic Rules Implementation in Perl: my %builtin_variables; $builtin_variables{ @ = $target; ($builtin_variables{ * = $target) =~ s/\.[^\.]*$//; $builtin_variables{ ^ = $depends{$target; ($builtin_variables{ < = $depends{$target) =~ s/\s.*//; $build_command =~ s/\$(.)/$builtin_variables{$1 /eg; Can define generic rules based on suffixes:.suffixes:.c.o.java.pl.sh.c.o: $(CC) $(CFLAGS) -c -o $@ $<< i.e. to make a.o file from a.c file, use the command... Rules for several common languages are built in to make. Pattern-based rules generalise what suffix rules do. E.g. implementation of.c.o \%.o : \%.c $(CC) $(CFLAGS) -c -o $@ $<< Make in Perl - Version #0 Simple Make implementation in Perl. Parses makefile rules and storing them in 2 hashes. Building is done with a recursive function. /home/cs2041/public html/code/make/make0.pl #!/usr/bin/perl -w # written by andrewt@cse.unsw.edu.au for COMP2041 # Simple Perl implementation of "make". # # It parses makefile rules and stores them in 2 hashes. # # Building is done with a recursive function. $makefile_name = "Makefile"; if (@ARGV >= 2 && $ARGV[0] eq "-f") { shift @ARGV; $makefile_name = shift @ARGV; parse_makefile($makefile_name); push @ARGV, $first_target if!@argv; build($_) foreach @ARGV; exit 0; sub parse_makefile { my ($file) = @_; open MAKEFILE, $file or die "Can not open $file: $!"; my ($target, $dependencies) = /(\S+)\s*:\s*(.*)/ or next; $first_target = $target; $dependencies{$target = $dependencies; last if!/^\t/; $build_command{$target.= $_; sub build { my ($target) = @_; my $build_command = $build_command{$target; die "*** No rule to make target $target\n" if!$build_command &&!-e $target; return if!$build_command; my $target_build_needed =! -e $target; foreach $dependency (split /\s+/, $dependencies{$target) { build($dependency); $target_build_needed = -M $target > -M $dependency; return if!$target_build_needed; print $build_command; system $build_command; Testing make0.pl % cd /home/cs2041/public_html/code/make %./make0.pl -f Makefile.simple world.o %./make0.pl -f Makefile.simple clean rm -f game main.o graphics.o world.o %./make0.pl -f Makefile.simple world.o gcc -c world.c %./make0.pl -f Makefile.simple gcc -c main.c gcc -c graphics.c gcc -o game main.o graphics.o world.o %./make0.pl -f Makefile.simple %./make0.pl -f Makefile.simple clean rm -f game main.o graphics.o world.o

Make in Perl - Version #1 /home/cs2041/public html/code/make/make2.pl Testing make1.pl Add a few lines of code and we can handle variables and comments. A good example of how easy some tasks are in Perl. /home/cs2041/public html/code/make/make1.pl #!/usr/bin/perl -w # written by andrewt@cse.unsw.edu.au for COMP2041 # Add a few lines of code to make0.pl # and we can handle variables and comments. # # A good example of how easy some tasks are in Perl. $makefile_name = "Makefile"; if (@ARGV >= 2 && $ARGV[0] eq "-f") { shift @ARGV; $makefile_name = shift @ARGV; parse_makefile($makefile_name); push @ARGV, $first_target if!@argv; build($_) foreach @ARGV; exit 0; sub parse_makefile { my ($file) = @_; open MAKEFILE, $file or die "Can not open $file: $!\n"; s/#.*//; s/\$\((\w+)\)/$variable{$1 /eg; if (/^\s*(\w+)\s*=\s*(.*)$/) { $variable{$1 = $2; next; my ($target, $dependencies) = /(\S+)\s*:\s*(.*)/ or next; $first_target = $target; $dependencies{$target = $dependencies; s/#.*//; s/\$\((\w+)\)/$variable{$1 /eg; last if!/^\t/; $build_command{$target.= $_; % cd /home/cs2041/public_html/code/make %./make1.pl -f Makefile.variables world.o graphics.o gcc-4.3 -O3 -Wall -c world.c gcc-4.3 -O3 -Wall -c graphics.c %./make1.pl -f Makefile.variables gcc-4.3 -O3 -Wall -c main.c gcc-4.3 -O3 -Wall -o game main.o graphics.o world.o sub build { my ($target) = @_; my $build_command = $build_command{$target; die "*** No rule to make target $target\n" if!$build_command &&!-e $target; return if!$build_command; my $target_build_needed =! -e $target; foreach $dependency (split /\s+/, $dependencies{$target) { build($dependency); $target_build_needed = -M $target > -M $dependency; return if!$target_build_needed; print $build_command; system $build_command; Make in Perl - Version #2 Testing make2.pl Add a few lines of code and we can handle some builtin variables and an implicit rule. Another good example of how easy some tasks are in Perl. #!/usr/bin/perl -w # written by andrewt@cse.unsw.edu.au for COMP2041 # Add a few lines of code to make1.pl and we can handle some # builtin variables and an implicit rule. # # Another good example of how easy some tasks are in Perl. $makefile_name = "Makefile"; if (@ARGV >= 2 && $ARGV[0] eq "-f") { shift @ARGV; $makefile_name = shift @ARGV; %variable = (CC => cc, CFLAGS => ); parse_makefile($makefile_name); push @ARGV, $first_target if!@argv; build($_) foreach @ARGV; exit 0; sub parse_makefile { my ($file) = @_; open MAKEFILE, $file or die "Can not open $file: $!"; s/#.*//; s/\$\((\w+)\)/$variable{$1 /eg; if (/^\s*(\w+)\s*=\s*(.*)$/) { $variable{$1 = $2; next; my ($target, $dependencies) = /(\S+)\s*:\s*(.*)/ or next; $first_target = $target if!defined $first_target; $dependencies{$target = $dependencies; s/#.*//; s/\$\((\w+)\)/$variable{$1 /eg; last if!/^\t/; $build_command{$target.= $_; sub build { my ($target) = @_; my $build_command = $build_command{$target; if (!$build_command && $target =~ /(.*)\.o/) { $build_command = "$variable{cc $variable{cflags -c \$< -o \$@\n"; die "*** No rule to make target $target\n" if!$build_command &&!-e $target; return if!$build_command; my $target_build_needed =! -e $target; foreach $dependency (split /\s+/, $dependencies{$target) { build($dependency); $target_build_needed = -M $target > -M $dependency; return if!$target_build_needed; my %builtin_variables; $builtin_variables{ @ = $target; ($builtin_variables{ * = $target) =~ s/\.[^\.]*$//; $builtin_variables{ ^ = $dependencies{$target; ($builtin_variables{ < = $dependencies{$target) =~ s/\s.*//; $build_command =~ s/\$(.)/$builtin_variables{$1 /eg; print $build_command; system $build_command; % cd /home/cs2041/public_html/code/make %./make2.pl -f Makefile.builtin_variables clean rm -f game main.o graphics.o world.o %./make2.pl -f Makefile.builtin_variables gcc-4.3 -O3 -Wall -c main.c gcc-4.3 -O3 -Wall -c graphics.c gcc-4.3 -O3 -Wall -c world.c -o world.o gcc-4.3 -O3 -Wall -o game main.o graphics.o world.o %./make2.pl -f Makefile.implicit clean rm -f game main.o graphics.o world.o %./make2.pl -f Makefile.implicit gcc-4.3 -O3 -Wall -c main.c -o main.o gcc-4.3 -O3 -Wall -c graphics.c -o graphics.o gcc-4.3 -O3 -Wall -c world.c -o world.o gcc-4.3 -O3 -Wall -o game main.o graphics.o world.o

Configuration Autotools Systems need to be tailored to fit into specific computing environments. If we re lucky, this is handled by the execution engine. although we ll may still need to change e.g. file/user names If we re not so lucky, we need to... embded stuff in the code to cater for each environment ensure the compiler uses the right set of switches Best to do this automatically... GNU build system for assisting with portability of open source systems. Still widely used but many people dislike it. Many newer build tools available (e.g. Cmake, ninja) Autotools Configure/Autoconf Uses a generic configure command to interrogate the local system and determine configuration settings read simple templates for Makefile and/or config.h generate customised Makefile and/or config.h Once system is configured, simply run make to build it Configure shell script is distributed with the source code.

Configure/Autoconf Configure/Autoconf If the configure script was completely general it would be huge most of it would be irrelevant for a given system developers would need to tailor it for new systems The solution: generate the configure script automatically... Configure/Autoconf The autoconf command generates a configure script from a file called configure.in configure.in contains information such as names of all source code files for this system where should binaries and manuals be installed which libraries/processors (e.g. flex) are needed Configure/Autoconf Creating a configure.in file... requires developer to enter details about code much of this can be auto-extracted from code Hence, the autoscan command... extract config information from source code produce a first draft configure.in file developer manually completes configure.in

Configure/Autoconf The configure/autoconf system is a nice example of automating, routine aspects of software development. For more details about configure/autoconf, google or download software using it and experiment.