home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
pgccgcc.zip
/
emx
/
bin.new
/
dllar.cmd
< prev
next >
Wrap
OS/2 REXX Batch file
|
1998-04-27
|
10KB
|
283 lines
/* dllar - a tool to build both a .dll and an .a file
* from a set of object (.o) files for EMX/OS2.
*
* Written by Andrew Zabolotny, bit@freya.etu.ru
*
* This program will accept a set of files on the command line.
* All the public symbols from the .o files will be exported into
* a .DEF file, then linker will be run (through gcc) against them to
* build a shared library consisting of all given .o files. All libraries
* (.a) will be first decompressed into component .o files then act as
* described above. You can optionally give a description (-d "description")
* which will be put into .DLL. To see the list of accepted options (as well
* as command-line format) simply run this program without options. The .DLL
* is built to be imported by name (there is no guarantee that new versions
* of the library you build will have same ordinals for same symbols).
*
* dllar is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* dllar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dllar; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* To successfuly run this program you will need:
* - Current drive should have LFN support (HPFS, ext2, network, etc)
* (Sometimes dllar generates filenames which won't fit 8.3 scheme)
* - gcc
* (used to build the .dll)
* - emxexp
* (used to create .def file from .o files)
* - emximp
* (used to create .a file from .def file)
* - GNU text utilites (cat, sort, uniq)
* used to process emxexp output
* - lxlite (optional, see flag below)
* (used for general .dll cleanup)
*/
flag_USE_LXLITE = 1;
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
parse arg cmdLine;
outFile = '';
inputFiles.0 = 0;
description = '';
CCFLAGS = '-s -Zcrtdll';
EXTRA_CCFLAGS = '';
EXPORT_BY_ORDINALS = 0;
exclude_symbols = '';
library_flags = '';
curDir = directory();
curDirS = curDir;
if (right(curDirS, 1) \= '\')
then curDirS = curDirS||'\';
do I = 1 to words(cmdLine)
tmp = word(cmdLine, I);
if left(tmp, 1) = '-'
then select
when abbrev('output', substr(tmp, 2), 1)
then do
i = i + 1;
outFile = word(cmdLine, i);
end;
when abbrev('description', substr(tmp, 2), 1)
then description = GetLongArg();
when abbrev('flags', substr(tmp, 2), 1)
then CCFLAGS = GetLongArg();
when abbrev('help', substr(tmp, 2), 1)
then call PrintHelp;
when abbrev('ordinals', substr(tmp, 2), 3)
then EXPORT_BY_ORDINALS = 1;
when abbrev('exclude', substr(tmp, 2), 2)
then exclude_symbols = exclude_symbols||GetLongArg()' ';
when abbrev('libflags', substr(tmp, 2), 4)
then library_flags = library_flags||GetLongArg()' ';
when abbrev('nocrtdll', substr(tmp, 2), 5)
then CCFLAGS = '-s';
otherwise
EXTRA_CCFLAGS = EXTRA_CCFLAGS' 'tmp;
end
else do
rc = SysFileTree(tmp, "files", "FO");
if (rc = 0)
then do J = 1 to files.0
inputFiles.0 = inputFiles.0 + 1;
K = inputFiles.0;
inputFiles.K = files.J;
end;
else say 'WARNING: there is no file which fits filemask "'tmp'"';
end;
end;
if (inputFiles.0 = 0)
then do
say 'dllar: no input files'
call PrintHelp;
end;
/* Now extract all .o files from .a files */
do I = 1 to inputFiles.0
if right(inputFiles.I, 2) = '.a'
then do
fullname = inputFiles.I;
inputFiles.I = '$_'filespec('NAME', inputFiles.I);
inputFiles.I = left(inputFiles.I, length(inputFiles.I) - 2);
'@mkdir 'inputFiles.I;
if (rc \= 0)
then do
say 'Failed to create subdirectory ./'inputFiles.I;
call CleanUp;
exit 3;
end;
inputFiles.I = '!'inputFiles.I;
call doCommand('cd 'substr(inputFiles.I, 2)' & ar x 'fullname);
call directory(curDir);
rc = SysFileTree(substr(inputFiles.I, 2)'\*', 'files', 'FO');
if (rc = 0)
then do J = 1 to files.0
inputFiles.0 = inputFiles.0 + 1;
K = inputFiles.0;
inputFiles.K = files.J;
end;
else say 'WARNING: there are no files in archive "'substr(inputFiles.I, 2)'"';
end;
end;
/* Now remove extra directory prefixes */
do I = 1 to inputFiles.0
if left(inputFiles.I, length(curDirS)) = curDirS
then inputFiles.I = substr(inputFiles.I, length(curDirS) + 1);
end;
if (outFile = '')
then outFile = inputFiles.1;
if (left(outFile, 3) = '!$_')
then outFile = substr(outFile, 4)'_imp';
dotpos = lastpos('.', outFile);
if dotpos > 0
then do
ext = translate(substr(outFile, dotpos + 1));
if (ext = 'DLL') | (ext = 'O') | (ext = 'A')
then outFile = substr(outFile, 1, dotpos - 1);
end;
EXTRA_CCFLAGS = substr(EXTRA_CCFLAGS, 2);
defFile = outFile'.def';
dllFile = outFile'.dll';
arcFile = outFile'.a';
call SysFileDelete('$_'defFile);
gccCmdl = '';
do I = 1 to inputFiles.0
if (left(inputFiles.I, 1) \= '!')
then do
call doCommand('emxexp -u' inputFiles.I' >>$_'defFile);
gccCmdl = gccCmdl' 'inputFiles.I;
end;
end;
call SysFileDelete(defFile);
call lineOut defFile, 'LIBRARY 'filespec('NAME', outFile)' 'library_flags;
if (length(description) > 0)
then call lineOut defFile, 'DESCRIPTION "'description'"';
call lineOut defFile, 'EXPORTS';
call doCommand('cat $_'defFile' | sort | uniq | rxqueue');
ordinal = 1;
do while queued() > 0
parse pull line;
if (length(line) > 0) & (word(line, 1) \= ';') & (export_ok(line))
then do
if EXPORT_BY_ORDINALS
then do
line = line||copies(' ',(71-length(line))%8)'@'ordinal' NONAME';
ordinal = ordinal + 1;
end;
call lineOut defFile, line;
end;
end;
call stream defFile, 'C', 'CLOSE';
call doCommand('rm -f $_'defFile);
call doCommand('gcc 'CCFLAGS' -Zdll -o 'dllFile defFile||gccCmdl' 'EXTRA_CCFLAGS);
call doCommand('emximp -o 'arcFile defFile);
if (flag_USE_LXLITE)
then do
if (EXPORT_BY_ORDINALS)
then add_flags = '-ynd';
else add_flags = '';
call doCommand('lxlite -cs -t: -mrn -mln 'add_flags' 'dllFile);
end;
call CleanUp;
exit;
PrintHelp:
say 'Usage: dllar [-o[utput] output_file] [-d[escription] "dll descrption"]'
say ' [-f[lags] "CCFLAGS"] [-ord[inals]] -ex[clude] "symbol(s)"'
say ' [-libf[lags] "{INIT|TERM}{GLOBAL|INSTANCE}"] [-nocrt[dll]]'
say ' [*.o]'
say '*> "output_file" should have no extension'
say ' If it has an .o, .a or .dll extension, it is automatically removed'
say '*> "flags" should be any set of valid GCC flags (default: -s -Zcrtdll)'
say ' These flags will be put at the start of GCC command line'
say '*> -ord[inals] tells dllar to export entries by ordinals. Be careful.'
say '*> -ex[clude] defines symbols which will not be exported. You can define'
say ' multiple symbols, for example -ex "myfunc yourfunc _GLOBAL*"'
say ' If the last character of a symbol is "*", all symbols beginning'
say ' with the prefix before "*" will be exclude, (see _GLOBAL* above)'
say '*> -libf[lags] can be used to add INITGLOBAL/INITINSTANCE and/or'
say ' TERMGLOBAL/TERMINSTANCE flags to the dynamically-linked library'
say '*> -nocrtdll switch will disable linking the library against emx''s'
say ' C runtime DLLs'
say '*> All other switches (for example -L./ or -lmylib) will be passed'
say ' unchanged to GCC at the end of command line'
say '*> If you create a DLL from a library and you do not specify -o,'
say ' the basename for DLL and import library will be set to <library>_imp'
say ' i.e. "dllar gcc.a" will create gcc_imp.dll and gcc_imp.a'
say '--------'
say 'Example:'
say ' dllar -o gcc290.dll libgcc.a -d "GNU C runtime library" -ord'
say ' -ex "__main __ctordtor*" -libf "INITINSTANCE TERMINSTANCE"'
call CleanUp;
exit 1;
GetLongArg:
i = i + 1;
_tmp_ = word(cmdLine, i);
if (left(_tmp_, 1) = '"') | (left(_tmp_, 1) = "'")
then do
do while (i < words(cmdLine) &,
right(_tmp_, 1) \= left(_tmp_, 1))
i = i + 1;
if (_tmp_ = '')
then _tmp_ = word(cmdLine, i);
else _tmp_ = _tmp_' 'word(cmdLine, i);
end;
if (right(_tmp_, 1) = left(_tmp_, 1))
then _tmp_ = substr(_tmp_, 2, length(_tmp_) - 2);
end;
return _tmp_;
export_ok:
procedure expose exclude_symbols;
parse arg line;
do i = 1 to words(exclude_symbols)
noexport = '"'word(exclude_symbols, i);
if right(noexport, 1) = '*'
then noexport = left(noexport, length(noexport) - 1)
else noexport = noexport'"';
if pos(noexport, line) > 0
then return 0;
end;
return 1;
doCommand:
parse arg _cmd_;
say _cmd_;
'@'_cmd_;
if (rc \= 0)
then do
say 'command failed, exit code='rc;
call CleanUp;
exit 2;
end;
return;
CleanUp:
call directory(curDir);
do i = inputFiles.0 to 1 by -1
if left(inputFiles.I, 1) = '!'
then call doCommand('rm -rf 'substr(inputFiles.I, 2));
end;
return;