Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!sdd.hp.com!uakari.primate.wisc.edu!aplcen!haven!adm!smoke!gwyn From: gwyn@smoke.brl.mil (Doug Gwyn) Newsgroups: comp.unix.questions Subject: Re: Changing symbols to "static" Keywords: coff ld Message-ID: <14310@smoke.brl.mil> Date: 2 Nov 90 01:04:54 GMT References: <781@nixbur.UUCP> <14294@smoke.brl.mil> <783@nixbur.UUCP> Organization: U.S. Army Ballistic Research Laboratory, APG, MD. Lines: 90 In article <783@nixbur.UUCP> jobrien@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.)