#include <stdio.h> #include <stdlib.h> extern char *Translate_en[]={"zero","one","two","three"}; int een(){return(1);} int twee(){return(2);} int drie(){return(3);}They compiled the program and made it into an object library:
$ cc one2 $ library/create one2.olb one2.objThen they wrote a linker options file with the vectors pointing to the global symbol entries, included the version and the identification, and called it one2_vector.opt.
GSMATCH=LEQUAL,1,0 CASE_SENSITIVE=YES IDENTIFICATION="one2 1.0" SYMBOL_VECTOR=( - DRIE=PROCEDURE, - EEN=PROCEDURE, - TRANSLATE_EN=DATA, - TWEE=PROCEDURE) CASE_SENSITIVE=NOThen they linked and created the shared library, and defined a logical one2shr pointing to it
$ link/share/exe=one2shr.exe one2.olb/lib, one2_vector.opt/opt $ define one2shr ''f$environment("default")'one2shr.exeThen they wrote a program called useone2.c that cleverly used the shared library:
#include <stdio.h> #include <stdlib.h> int een(); int twee(); int drie(); extern char *Translate_en[]; main() { printf(" een: %s\n",Translate_en[een()] ); printf("twee: %s\n",Translate_en[twee()] ); printf("drie: %s\n",Translate_en[drie()] ); }They compiled and linked it to the shared library:
$ cc useone2 $ link/exe=useone2.exe useone2.obj, sys$input:/opt one2shr/share $ run useone2 een: one twee: two drie: threeIt worked! They were 20% over budget and three weeks late, so everything was hastily put in to production.
So, they added a function to the shared library, vier, and extended the array with English translations, and called the source file one21.c:
#include <stdio.h> #include <stdlib.h> extern char *Translate_en[]={"zero","one","two","three","four"}; int een(){return(1);} int twee(){return(2);} int drie(){return(3);} int vier(){return(4);}
$ cc one21.c $ library/create one21.olb one21.objThen they wrote a new link options file one21_vector.opt:
GSMATCH=LEQUAL,1,1 CASE_SENSITIVE=YES IDENTIFICATION="one2 1.1" SYMBOL_VECTOR=( - DRIE=PROCEDURE, - EEN=PROCEDURE, - TRANSLATE_EN=DATA, - TWEE=PROCEDURE, - VIER=PROCEDURE) CASE_SENSITIVE=NOThey linked the library,and tested the old program:
$ link/share/exe=one2shr_1.exe one21.olb/lib, one21_vector.opt/opt $ define one2shr ''f$environment("default")'one2shr_1.exe $ run useone2 een: one twee: two drie: threeThat worked! To prove that the library could count to four, they also wrote fourtest.c, and linked it to the new shared library:
#include <stdio.h> #include <stdlib.h> int vier(); extern char *Translate_en[]; main() { printf(" vier: %s\n",Translate_en[vier()] ); }Compiling, linking and runnig proved succesful:
$ cc fourtest $ link fourtest, sys$input/opt one2shr/share $ r fourtest vier: fourThe shared library was put in to production, and everybody was happy.
After four weeks of meetings with product managers and architects, the one2shr library was introduced as a new standard, to be used by everyone.
Somebody remarked that that could be solved by relinking the shared library and add case sensitive aliases. The source should be compiled with /names=as_is, to produce case sensitive symbolnames. To maintain upward compatibility, the original vectors should be replaced by aliases pointing to the now case sensitive symbol entries at the end of the vector file. After an hour of typos, the new option file worked, and still the old useone2 and fourtest programs could use it:
$ cc one21/obj=one22.obj/names=as_is $ library/create one22.olb one22.obj $ link/share/exe=one2shr_2.exe one22.olb/lib, one22_vector.opt/opt $ define one2shr 'f$environment("default")'one2shr_2.exe %DCL-I-SUPERSEDE, previous value of ONE2SHR has been superseded $ r fourtest vier: four $ r useone2 een: one twee: two drie: threeThe new option file was called one22_vector.opt:
GSMATCH=LEQUAL,1,2 CASE_SENSITIVE=YES IDENTIFICATION="one2 1.2" SYMBOL_VECTOR=( - DRIE/drie=PROCEDURE, - EEN/een=PROCEDURE, - TRANSLATE_EN/Translate_en=DATA, - TWEE/twee=PROCEDURE, - VIER/vier=PROCEDURE, - Translate_en=DATA , - drie=PROCEDURE , - een=PROCEDURE , - twee=PROCEDURE , - vier=PROCEDURE ) CASE_SENSITIVE=NOThe OpenSource adept was happy, but the programmers were not. They now had to maintain the source code, but also the vector options file, which by a lot of accounts was far more complicated than the source file, as it had to be upward compatible and the order of the vector entries was not evident.
They came up with linkshrlib.com, a command procedure that contained two programs, listlib and vectorcompatible, that relieved the programmers of the maintenance of their vector files.
Using only the object libraries, they were able to demonstrate creating an upward compatible library could be done completely automatically. They even didn't need the first original linker options file, as the symbols had already been sorted alphabetically in the original:
$ @[-.linkshrlib]linkshrlib one2.olb one2shr_1_0.exe +version=1.0+id="one2shr V1.0" New linker vector options file will be called H:[T]ONE2_VECTOR.OPT; data symbol found: TRANSLATE_EN No demangler db used. Link H:[T]ONE2.OLB;3 to H:[T]ONE2SHR_1_0.EXE; Made and will use version option file H:[T]ONE2_VERSION.OPT; $ @[-.linkshrlib]linkshrlib one21.olb one2shr_1_1.exe +version=1.1+id="one2shr V1.1" New linker vector options file will be called H:[T]ONE21_VECTOR.OPT; data symbol found: TRANSLATE_EN No demangler db used. Link H:[T]ONE21.OLB;4 to H:[T]ONE2SHR_1_1.EXE; Made and will use version option file H:[T]ONE21_VERSION.OPT; $ @[-.-.linkshrlib]linkshrlib one21.olb one2shr_1_2.exe +version=1.2+id="one2shr V1.2" New linker vector options file will be called H:[T]ONE21_VECTOR.OPT; data symbol found: TRANSLATE_EN No demangler db used. Link H:[T]ONE21.OLB;4 to H:[T]ONE2SHR_1_2.EXE; Made and will use version option file H:[T]ONE21_VERSION.OPT;They used the original test executables and tested compatibility:
$ define one2shr 'f$environment("default")'one2shr_1_0.exe %DCL-I-SUPERSEDE, previous value of ONE2SHR has been superseded $ r [-.o]useone2 een: one twee: two drie: three $ r [-.o]fourtest %DCL-W-ACTIMAGE, error activating image ONE2SHR -CLI-E-IMGNAME, image file H:[T]ONE2SHR_1_0.EXE;1 -SYSTEM-F-SHRIDMISMAT, ident mismatch with shareable image $! $ define one2shr 'f$environment("default")'one2shr_1_1.exe %DCL-I-SUPERSEDE, previous value of ONE2SHR has been superseded $ r [-.o]fourtest vier: four $ r [-.o]useone2 een: one twee: two drie: three $ define one2shr 'f$environment("default")'one2shr_1_2.exe %DCL-I-SUPERSEDE, previous value of ONE2SHR has been superseded $ r [-.o]useone2 een: one twee: two drie: threeAs you can see, upward compatibility was established, by using the old vector option file as input when linking a new version of the shared image. In linkshrlib.com this works like this: After generating a new vector option file with listlib.exe, vectorcompatible generates a new, compatible vector options file using both the old and the newly generated option file.
#include <stdio.h> #include <stdlib.h> int libdum_Initialize_All_but_leave_the_clever_bits() { return( 17 ); } int libdum_Initialize_only_the_clever_bits_so_not_all() { #ifdef WIN32 return( 0 ); #endif return( 18 ); } int libdum_do_something_that_even_doesnt_look_clever() { return(1); }The administrators were not impressed and found out that compiling twice wasn't necessary, as they found the shortening in the comp.os.vms Usenet group, where Craig Berry published it. If you want both upper- and lowercase entries in you shareable library, make sure you compile all modules with /NAMES=(AS_IS,SHORTENED). The compiler will produce a cross reference of the actual and shortened function names in a subdirectory called CXX_REPOSITORY, in a file called CXX$DEMANGLER_DB.;
$ cc libdum/names=(as_is,shortened) $ dire .dir Directory H:[LIBDUM] CXX_REPOSITORY.DIR;1 Total of 2 files. $ dir [.cxx_repository] Directory H:[LIBDUM.CXX_REPOSITORY] CXX$DEMANGLER_DB.;1 Total of 1 file. $ ty [.cxx_repository]cxx$demangler_db.; libdum_Initialize_All_b3uu4cah$libdum_Initialize_All_but_leave_the_clever_bits libdum_Initialize_only_39lru31$libdum_Initialize_only_the_clever_bits_so_not_all libdum_do_something_tha3r1068u$libdum_do_something_that_even_doesnt_look_cleverTo keep the command line short, you can define a logical pointing to it. Now create the object library, and then link it to a shareable image:
$ library/create libdum.olb libdum.obj $ $ define demang [.CXX_REPOSITORY]CXX$DEMANGLER_DB.;1 $ $ @[-.linkshrlib]linkshrlib libdum.olb libdum_1_0.exe +demang=demang:+version=1.0+id="libdum V1.0" New linker vector options file will be called H:[LIBDUM]LIBDUM_VECTOR.OPT; %DCL-W-ACTIMAGE, error activating image H:[LIBDUM]LISTLIB.EXE -CLI-E-IMAGEFNF, image file not found H:{LIBDUM]LISTLIB.EXE; Compile and link listlib Link H:[LIBDUM]LIBDUM.OLB;1 to H:[LIBDUM]LIBDUM_1_0.EXE; Made and will use version option file H:[LIBDUM]LIBDUM_VERSION.OPT; $ $ $ ty libdum_version.opt GSMATCH=LEQUAL,1,0 CASE_SENSITIVE=YES IDENTIFICATION="libdum V1.0" CASE_SENSITIVE=NO $ ty libdum_vector.opt ! generated by listlib.exe Fri Jul 24 20:12:00 1970 CASE_SENSITIVE=YES SYMBOL_VECTOR=( - libdum_Initialize_All_b3uu4cah$=PROCEDURE, - LIBDUM_INITIALIZE_ALL_B3R3B4LC$/libdum_Initialize_All_b3uu4cah$=PROCEDURE, - libdum_Initialize_only_39lru31$=PROCEDURE, - LIBDUM_INITIALIZE_ONLY_1QUMGA1$/libdum_Initialize_only_39lru31$=PROCEDURE, - libdum_do_something_tha3r1068u$=PROCEDURE, - LIBDUM_DO_SOMETHING_THA33U2UN7$/libdum_do_something_tha3r1068u$=PROCEDURE) CASE_SENSITIVE=NOYou see that the procedure actually compiles and links listlib, one of the excutables if it cant find it.
#include <stdio.h> #include <stdlib.h> int libdum_Initialize_All_but_leave_the_clever_bits(); int libdum_Initialize_only_the_clever_bits_so_not_all(); int libdum_do_something_that_even_doesnt_look_clever(); main() { printf(" This should be 17 : %d\n", libdum_Initialize_All_but_leave_the_clever_bits()); printf(" This should be 18 : %d\n", libdum_Initialize_only_the_clever_bits_so_not_all()); printf(" This should be 1 : %d\n", libdum_do_something_that_even_doesnt_look_clever()); }We define a logical with a full filespec pointing to libdum, and compile testlibdum both with NAMES=(SHORTENED,AS_IS) and NAMES=(SHORTENED) and link and run it to verify that both upper- and lowercase vectors in the shareable library work:
$ define libdumshr 'f$environment("default")'libdum_1_0.exe $ cc testlibdum/names=(as_is,shortened) $ link testlibdum, sys$input/opt libdumshr/share Exit $ r testlibdum This should be 17 : 17 This should be 18 : 18 This should be 1 : 1 $ cc testlibdum/names=(shortened) $ link testlibdum, sys$input/opt libdumshr/share Exit $ r testlibdum This should be 17 : 17 This should be 18 : 18 This should be 1 : 1It worked.
+exclude_symbols="_*,inflate_fast"For libssh2, this list was very simple, as the libssh2 project had wisely decided, that all local procedures should be preceded by an underscore:
+exclude_symbols="_*"Nobody was looking forward to guessing what symbols might be meant to be global in zlib, and also nobody looked forward at maintaining this list. Then, with zlib 1.2.5, a file containing such definitions was made available in the zlib dirstribution: zlib.map Based on the zlib object library, the zlib.map file could be used to link a zlib shareable library, with only the global symbols needed, using this command line:
@linkshrlib LIBZ_1_2_5_32.OLB libz_1_2_5_shr32.exe +vmap=zlib.map+ident="LIBZ 1.2.5"+version="1.200500" - +new_vect=libz_1_2_5_vector.optAlso note the +version="1.200500" option. This makes sure the version of zlib is encoded in the shareable library, in a way that remains more or less readable:
$ analyze/image/inter libz_1_2_5_shr32.exe . IMAGE HEADER Fixed Header Information image format major id: 3, minor id: 0 header block count: 2 image type: shareable (EIHD$K_LIM) global section major id: %X'01', minor id: %X'030F34' match control: ISD$K_MATLEQ . . . $ a = %X030F34 $ show symbol a A = 200500 Hex = 00030F34 Octal = 00000607464As you can see, the actual version is easily derived from the minor id.
One consequence is, that without a working C compiler, linkshrlib.com may not work.
All this may be frowned upon, but is very practical when distributing the procedure to other systems.
If (global) symbols listlib and vectorcompatible
already exist and point to a working executable, these are used, and no new
version is being compiled.
So, if you're really annoyed or worried about this behaviour, have global symbols
point to precompiled and linked executables listlib.exe and
vectorcompatible.exe, not forgetting the dollar preceding the executable
file specification, like this:
$ listlib :== $exe:listlib.exe
$ vectorcompatible :== $exe:vectorcompatible.exe
Docs, linkshrlib help
Ok, that most explained. If linkshrlib.com
is started without any arguments, it will display a comprehensive
help text:
$ @linkshrlib
Create a shareable image from an objectlibrary
Uses 2 executables, that will be compiled and linked if
not available in foreign symbols listlib and
vectorcompatible.
Usage: @Linkshrlib help
shows this screen.
Usage: @Linkshrlib