Changing symbols to "static"

Doug Gwyn gwyn at smoke.brl.mil
Fri Nov 2 12:04:54 AEST 1990


In article <783 at nixbur.UUCP> jobrien at nixbur.UUCP (John O'Brien) writes:
>	ld -r -o big.o one.o two.o
>Part of the design requirements is that I link in this code and not copy
>the source (this is to avoid having to maintain two pieces of code that
>do the same thing).

Thanks for the additional information.  I don't think in most environments
this approach can be made to work, because while you're still outputting a
.o file the final link-image relocation has not yet been done, and if your
compiler generates external linkages in certain commonly-encountered ways,
you simply can't get "ld" to provide "position-independent code" for the
linkages between one.o and two.o; it will be necessary to retain the
relocation information.  I think that some, maybe all, versions of "ld"
would fail to complete the relocation if you were to somehow change the
intermodule references to have the STATIC attribute.

Here is one possibility that doesn't require playing tricks with the linker:

	/* file one.c: */
	#ifndef STATIC
	#define	STATIC	/* nothing */
	#endif
	STATIC int c, d;
	STATIC a()
	{
	  ...
	}
	STATIC b()
	{
	  ...
	}

	/* file two.c: */
	#ifdef STATIC
	#include "one.c"
	#else
	external a(), b();
	external int c, d;
	#endif
	spot()
	{
	   ...
	   a();
	   b();
	   ...
	}

Thus, if you type
	cc -c one.c
	cc -c two.c
you get the same object code that you started with, but if you type
	cc -c -DSTATIC=static two.c
you get one object "two.o" that contains only one external name, "spot".

Of course, you can make this approach more aesthetically appealing by
using an auxiliary header file that defines the interface to the "one.c"
facilities; you should in general do that anyway as a matter of good
program design.  So, for example,

	/* file one.c: */		/* file one.h: */
	#include "one.h"		#ifndef STATIC
	STATIC int c, d;		#define STATIC	/* nothing */
	STATIC a()			extern int c, d;
	{				extern a(), b();
	  ...				#else /* STATIC = "static" */
	}				#ifndef BEEN_HERE
	STATIC b()			#define BEEN_HERE
	{				#include "one.c"
	  ...				#endif
	}				#endif

	/* file two.c: */
	#include "one.h"
	spot()
	{
	   ...
	   a();
	   b();
	}

We've used similar methods here to control whether or not some subset
of potentially external symbols get "hidden" when modules are added to
a library; some of our debuggers are more helpful when the symbols are
not hidden, i.e., not file-static, so we like to leave them visible
until we've finished debugging the modules.  This nice thing is that
this method is portable.  (If you use a configuration header, say,
"config.h" or "std.h", to optionally predefine STATIC and to set up
flags for other environmental dependencies, then it becomes fully
portable, and you don't have to specify "-DSTATIC=static" to the
compiler.)



More information about the Comp.unix.questions mailing list