QEF home page
Issues in Large Scale Porting

This page contains slides from lectures given on porting at various locations including the 1991 Data Processing Institute.

QEF Home Page
An Quick Introduction to Software Construction and QEF
Technical Documentation, Overviews, Tutorials, and Papers
QEF Papers, Talks, and Presentations

Introduction

The presentation is composed of:

  1. Introduction
  2. Presentation's Objectives
  3. The Porting Problem
  4. The Universe of Discourse
  5. Specific Problems to be Resolved
  6. Porting Goals
  7. Strategy and Mechanisms
  8. Specific Problem Solving
  9. Dr. Tuna's Porting Nostrums
  10. Conclusions

Presentation's Objectives

Present my approach to the porting problem w.r.t.:

The principle objective is to instil one adage:

Think before you port!

Caveats

The applicability of my solution to your problem may be difficult!

My solution is extensive and geared to large software systems.

Through familiarity, I have bred the expected feelings towards the suppliers, but I will not air these feelings publicly, as the suppliers do seem to strive for a uniform level of quality.

The Porting Problem

Historically:

Why Port?

One ports to:

The Universe of Discourse

Specific Problems to be Resolved

Problems with porting may be partitioned into the following classifications. Variations in:

  1. system architecture -- byte order, word size, pointer size, word alignment, and so on
  2. the tool interfaces and/or semantics
  3. libraries
  4. headers
  5. environment

Variations in performance, cost, robustness, reliability, availability, support, and the honesty of supplier should be considered, but are not relevant to this discussion.

Variations in Tools

Variations in Libraries

Variations in Header Files

Environment

Cc issues

Two Splendid Examples

Seven variations of rename(2):

  1. Existence proof that it can be done
  2. Not provided
  3. Provided but is no-op, but documentation is Posix compliant, but the example contains a bug.
  4. rename(from,to) fails when from file is busy
  5. Times out far too frequently
  6. Parallel renames crash kernel
  7. Parallel renames corrupt file system

So you want to use struct tm and/or struct timeval!

You might have to:

Porting Goals

Repeat after me ...


``There's no such thing as portable code!
There's only code that's been ported!''

I had code that had been successfully ``ported'' to thirty platforms, yet failed on the thirty-first.

The only achievable goal is:

Adaptable Code

that is, code that can be quickly and easily adapted to work on a new target platform.

So ...

How does one make code adaptable?

One:

What one is trying to do -- through experimentation, experience, and folklore, -- is to:

Nota Bene

Direct your efforts towards:

all targets:
not just the one you are currently doing!
all sources:
not just that one file that's currently presenting problems!

In other words, once you've have discovered a problem:


		Solve it once,
		and only once,
		for all time.
 

but you must ensure that the solution is conveyed to any developers who might invoke the discrepancy in the future.

Caution

When changing code to adapt to a new target ...

Do not break any previous adaptation!!!

Strategy and Mechanisms

The following sections describe the major strategies and mechanisms I use.

Adopt them as is feasible.

Single Sourcing

All products, for all platforms, for all configurations, for all concerned parties (e.g., developers, Q.A., release engineers) are built from a:


Single
Universal
Shared
Source
File
System
 

such as [Korn 89], [Tilbrook 90a], [Glew 89], build(1).

Comprehensive Incremental Construction

The software construction system should provide a comprehensive approach to incremental construction that ensures that any modification causes the appropriate constructions to be applied.

This should incorporate full dynamic transitive closure dependency tracking (e.g., mkdepends is a half-hearted attempt at this, but a good start).

If you are forced to use make, know ye well its many limitations.

A Compatibility Library

Add your own compatibility library as the penultimate library (i.e., immediately before libc) for every program.

This library should contain any subroutine mappings that are required to compensate for libc deficiencies.

In some instances, it must come between two libcs (one from each universe).

A Environment Header File

Insert at the beginning of every C file, (be it source or generated) an include of one of your own header files.

All our sources contain as the first C statement:


#include <envir/system.h>

This header file contains, in part:

Foreign Header File Wrappers

Never include a supplier's header file directly. Always wrap in one of your own idempotent header files, as in:


#ifndef ENVIR_STDIO_H
#	define ENVIR_STDIO_H

# undef NULL # include <stdio.h> # undef NULL # define NULL (0) /* missing prototypes */ #endif /* ENVIR_STDIO_H */

This allows one to correct their mistakes and omissions, and deal with discrepancies (e.g., type of sprintf) in single location.

In some cases, provide capability based name for header to deal with discrepancies. For example create <envir/open.h> to include header that contains open(2) arguments or define them if not provided.

A Single Parameterization File

Build a mechanism to construct and use a single platform parameterization file, that is a file that provides all platform specific settings or options for the software (e.g., appropriate type for a signed character, the include file that contains the open(2)'s second argument manifests).

F.Y.I.:
My parameterization file contains 112 settings which provide all required sub-routine and header file mappings, all site specific information (e.g., address, telephone), a variety of system specific constants and booleans (e.g., ANSI type token pasting, supports Prototypes).

A procedure (e.g., strfix at our site) is used to insert parameter values in specific configured files (e.g., <envir/system.h> and <envir/stdio.h>) which are then installed if the resulting file differs from the currently installed file.

A Single Configuration File

A single file is used to specify all construction specific information (i.e., destination directory, options, cc flags).

The construction system ensures that these values are applied universally and any change in their settings will result in the reapplication of any tool that uses them (again difficult to do with make).

Project/Software Hygiene

Apply Stenning's principles of Project Hygiene. In particular:

See [Stenning 90] and [Tilbrook 90b].

Specific Problem Solving

The following are some well known common discrepancies plus a short description of a possible solution.

Readdir
Create your own readdir.h that either includes appropriate header (if there is one) and defines common struct to be used on all systems. Provide macros to deal with missing name length in Posix definition. Create simulation for opendir, readdir, etc. for all seventh edition file systems.
string.h
Lose theirs. Create your own superset of all the versions you can find, incorporating appropriate macros or mappings to your routines for memcmp, bzero, strchr vs. index, etc.
Termcap
Create your own generalized capability-based interface library that hides differences between terminfo and termcap.
Getcwd
If you have getwd, use it. If you have getcwd() create getwd interface that calls getcwd to do the interesting stuff. Otherwise create getwd() that invokes pwd(1) and reads in its output.
Termio
Create your own header file with capability-based macros to provide basic functionality (e.g., stty, gtty, set or reset mode). Is tricky but can be done. Interaction with signals is a challenge.
Ar files
Create single routine that retrieves generalized structure describing archive members. Unfortunately has to be tailored for nearly every system individually, but you only do it once.
Linting
This is another paper. Too bad. It's an important porting aid.

Prototypes

ANSI C type prototype declarations should exist for every routine that you use or provide.

We have a boolean parameter that specifies whether or not prototypes should be used (__STDC__ not to be trusted).

<envir/system.h> contains (in effect):


#if PROTOTYPES_SUPPORTED
#	define  Prototype(x)  x
#else
#	define  Prototype(x)  ()
#endif

Procedures are then declared using something similar to:


int func Prototype((char *nm,int cnt));

It works and is extremely useful both as documentation and to validate routine usage.

Prototype Warnings

Some warnings regarding use of prototypes:

Dr. Tuna's Porting Nostrums

A list of unexplained rules:

Conclusions

Actually, not so much a conclusion as credentials.

Can you believe me, or am I just another consultant who is regurgitating other people's opinions without truly understanding them?

The strategy described is in use at Sietec O.S.D.

It has been applied to our three major products, which consists of about 390 directories containing 4,500 source files, which themselves contain approximately eight hundred thousand lines of code and about 21 Megabytes. The product directories contain about twenty-five hundred files. By Feldman's metrics, this is a large system.

Yet, there is one source file system and we maintain up to date product trees on nine different targets simultaneously. The only difference between two different configurations will be the platform parameterization file and the configuration control file.

If adaptation to a new platform takes more than a day, (and it takes upwards of eight hours to do the compiles) it's usually due to bugs in the target system's environment.

Bibliography

[Stenning 90]
Vic Stenning, ``Project Hygiene'', EurOpen Proceedings, Nice (Oct. '90).
[Tilbrook 90]
David Tilbrook, ``Quod Erat Faciendum'', EUUG & SUUG Conference Distributions, Nice & Moscow (Oct. '90),
[Tilbrook 90b]
David Tilbrook, ``Washing Behind Your Ears: The Principles of Software Hygiene'', EurOpen Proceedings, Nice (Oct. '90).
[Glew 89]
Andy Glew, ``Boxes, Links, and Parallel Trees: Elements of a Configuration Management System'', Software Management Workshop Proceedings, New Orleans (Apr. '89).
[Feldman 90]
Stuart Feldman, ``Large Scale Software Development Under Unix'', UKUUG Proceedings, London (June '90).
[Korn 89]
David Korn, ``The 3D File System'', Usenix Proceedings, Baltimore (June '89).

An Quick Introduction to Software Construction and QEF Technical Documentation, Overviews, Tutorials, and Papers QEF Papers, Talks, and Presentations
porting.qh - 1.14 - 03/10/24 QEF home page