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 >
OS/2 REXX Batch file  |  1998-04-27  |  10KB  |  283 lines

  1. /* dllar - a tool to build both a .dll and an .a file
  2.  * from a set of object (.o) files for EMX/OS2.
  3.  *
  4.  * Written by Andrew Zabolotny, bit@freya.etu.ru
  5.  *
  6.  * This program will accept a set of files on the command line.
  7.  * All the public symbols from the .o files will be exported into
  8.  * a .DEF file, then linker will be run (through gcc) against them to
  9.  * build a shared library consisting of all given .o files. All libraries
  10.  * (.a) will be first decompressed into component .o files then act as
  11.  * described above. You can optionally give a description (-d "description")
  12.  * which will be put into .DLL. To see the list of accepted options (as well
  13.  * as command-line format) simply run this program without options. The .DLL
  14.  * is built to be imported by name (there is no guarantee that new versions
  15.  * of the library you build will have same ordinals for same symbols).
  16.  *
  17.  * dllar is free software; you can redistribute it and/or modify
  18.  * it under the terms of the GNU General Public License as published by
  19.  * the Free Software Foundation; either version 2, or (at your option)
  20.  * any later version.
  21.  *
  22.  * dllar is distributed in the hope that it will be useful,
  23.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25.  * GNU General Public License for more details.
  26.  *
  27.  * You should have received a copy of the GNU General Public License
  28.  * along with dllar; see the file COPYING.  If not, write to the Free
  29.  * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  30.  * 02111-1307, USA.
  31.  */
  32.  
  33. /* To successfuly run this program you will need:
  34.  * - Current drive should have LFN support (HPFS, ext2, network, etc)
  35.  *   (Sometimes dllar generates filenames which won't fit 8.3 scheme)
  36.  * - gcc
  37.  *   (used to build the .dll)
  38.  * - emxexp
  39.  *   (used to create .def file from .o files)
  40.  * - emximp
  41.  *   (used to create .a file from .def file)
  42.  * - GNU text utilites (cat, sort, uniq)
  43.  *   used to process emxexp output
  44.  * - lxlite (optional, see flag below)
  45.  *   (used for general .dll cleanup)
  46.  */
  47.  
  48.  flag_USE_LXLITE = 1;
  49.  
  50.  call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  51.  call SysLoadFuncs
  52.  
  53.  parse arg cmdLine;
  54.  outFile = '';
  55.  inputFiles.0 = 0;
  56.  description = '';
  57.  CCFLAGS = '-s -Zcrtdll';
  58.  EXTRA_CCFLAGS = '';
  59.  EXPORT_BY_ORDINALS = 0;
  60.  exclude_symbols = '';
  61.  library_flags = '';
  62.  curDir = directory();
  63.  curDirS = curDir;
  64.  if (right(curDirS, 1) \= '\')
  65.   then curDirS = curDirS||'\';
  66.  
  67.  do I = 1 to words(cmdLine)
  68.   tmp = word(cmdLine, I);
  69.   if left(tmp, 1) = '-'
  70.    then select
  71.          when abbrev('output', substr(tmp, 2), 1)
  72.           then do
  73.                 i = i + 1;
  74.                 outFile = word(cmdLine, i);
  75.                end;
  76.          when abbrev('description', substr(tmp, 2), 1)
  77.           then description = GetLongArg();
  78.          when abbrev('flags', substr(tmp, 2), 1)
  79.           then CCFLAGS = GetLongArg();
  80.          when abbrev('help', substr(tmp, 2), 1)
  81.           then call PrintHelp;
  82.      when abbrev('ordinals', substr(tmp, 2), 3)
  83.       then EXPORT_BY_ORDINALS = 1;
  84.          when abbrev('exclude', substr(tmp, 2), 2)
  85.       then exclude_symbols = exclude_symbols||GetLongArg()' ';
  86.          when abbrev('libflags', substr(tmp, 2), 4)
  87.       then library_flags = library_flags||GetLongArg()' ';
  88.          when abbrev('nocrtdll', substr(tmp, 2), 5)
  89.       then CCFLAGS = '-s';
  90.          otherwise
  91.           EXTRA_CCFLAGS = EXTRA_CCFLAGS' 'tmp;
  92.         end
  93.    else do
  94.          rc = SysFileTree(tmp, "files", "FO");
  95.          if (rc = 0)
  96.           then do J = 1 to files.0
  97.                 inputFiles.0 = inputFiles.0 + 1;
  98.                 K = inputFiles.0;
  99.                 inputFiles.K = files.J;
  100.                end;
  101.           else say 'WARNING: there is no file which fits filemask "'tmp'"';
  102.         end;
  103.  end;
  104.  if (inputFiles.0 = 0)
  105.   then do
  106.         say 'dllar: no input files'
  107.         call PrintHelp;
  108.        end;
  109.  
  110. /* Now extract all .o files from .a files */
  111.  do I = 1 to inputFiles.0
  112.   if right(inputFiles.I, 2) = '.a'
  113.    then do
  114.          fullname = inputFiles.I;
  115.          inputFiles.I = '$_'filespec('NAME', inputFiles.I);
  116.      inputFiles.I = left(inputFiles.I, length(inputFiles.I) - 2);
  117.          '@mkdir 'inputFiles.I;
  118.          if (rc \= 0)
  119.           then do
  120.                 say 'Failed to create subdirectory ./'inputFiles.I;
  121.                 call CleanUp;
  122.                 exit 3;
  123.                end;
  124.          inputFiles.I = '!'inputFiles.I;
  125.          call doCommand('cd 'substr(inputFiles.I, 2)' & ar x 'fullname);
  126.          call directory(curDir);
  127.          rc = SysFileTree(substr(inputFiles.I, 2)'\*', 'files', 'FO');
  128.          if (rc = 0)
  129.           then do J = 1 to files.0
  130.                 inputFiles.0 = inputFiles.0 + 1;
  131.                 K = inputFiles.0;
  132.                 inputFiles.K = files.J;
  133.                end;
  134.           else say 'WARNING: there are no files in archive "'substr(inputFiles.I, 2)'"';
  135.         end;
  136.  end;
  137.  
  138. /* Now remove extra directory prefixes */
  139.  do I = 1 to inputFiles.0
  140.   if left(inputFiles.I, length(curDirS)) = curDirS
  141.    then inputFiles.I = substr(inputFiles.I, length(curDirS) + 1);
  142.  end;
  143.  
  144.  if (outFile = '')
  145.   then outFile = inputFiles.1;
  146.  if (left(outFile, 3) = '!$_')
  147.   then outFile = substr(outFile, 4)'_imp';
  148.  dotpos = lastpos('.', outFile);
  149.  if dotpos > 0
  150.   then do
  151.         ext = translate(substr(outFile, dotpos + 1));
  152.         if (ext = 'DLL') | (ext = 'O') | (ext = 'A')
  153.          then outFile = substr(outFile, 1, dotpos - 1);
  154.        end;
  155.  EXTRA_CCFLAGS = substr(EXTRA_CCFLAGS, 2);
  156.  
  157.  defFile = outFile'.def';
  158.  dllFile = outFile'.dll';
  159.  arcFile = outFile'.a';
  160.  call SysFileDelete('$_'defFile);
  161.  gccCmdl = '';
  162.  do I = 1 to inputFiles.0
  163.   if (left(inputFiles.I, 1) \= '!')
  164.    then do
  165.          call doCommand('emxexp -u' inputFiles.I' >>$_'defFile);
  166.          gccCmdl = gccCmdl' 'inputFiles.I;
  167.         end;
  168.  end;
  169.  
  170.  call SysFileDelete(defFile);
  171.  call lineOut defFile, 'LIBRARY 'filespec('NAME', outFile)' 'library_flags;
  172.  if (length(description) > 0)
  173.   then call lineOut defFile, 'DESCRIPTION "'description'"';
  174.  call lineOut defFile, 'EXPORTS';
  175.  call doCommand('cat $_'defFile' | sort | uniq | rxqueue');
  176.  ordinal = 1;
  177.  do while queued() > 0
  178.   parse pull line;
  179.   if (length(line) > 0) & (word(line, 1) \= ';') & (export_ok(line))
  180.    then do
  181.      if EXPORT_BY_ORDINALS
  182.       then do
  183.         line = line||copies('    ',(71-length(line))%8)'@'ordinal' NONAME';
  184.         ordinal = ordinal + 1;
  185.            end;
  186.      call lineOut defFile, line;
  187.     end;
  188.  end;
  189.  call stream defFile, 'C', 'CLOSE';
  190.  call doCommand('rm -f $_'defFile);
  191.  
  192.  call doCommand('gcc 'CCFLAGS' -Zdll -o 'dllFile defFile||gccCmdl' 'EXTRA_CCFLAGS);
  193.  call doCommand('emximp -o 'arcFile defFile);
  194.  if (flag_USE_LXLITE)
  195.   then do
  196.         if (EXPORT_BY_ORDINALS)
  197.          then add_flags = '-ynd';
  198.          else add_flags = '';
  199.         call doCommand('lxlite -cs -t: -mrn -mln 'add_flags' 'dllFile);
  200.        end;
  201.  call CleanUp;
  202. exit;
  203.  
  204. PrintHelp:
  205.  say 'Usage: dllar [-o[utput] output_file] [-d[escription] "dll descrption"]'
  206.  say '       [-f[lags] "CCFLAGS"] [-ord[inals]] -ex[clude] "symbol(s)"'
  207.  say '       [-libf[lags] "{INIT|TERM}{GLOBAL|INSTANCE}"] [-nocrt[dll]]'
  208.  say '       [*.o]'
  209.  say '*> "output_file" should have no extension'
  210.  say '   If it has an .o, .a or .dll extension, it is automatically removed'
  211.  say '*> "flags" should be any set of valid GCC flags (default: -s -Zcrtdll)'
  212.  say '   These flags will be put at the start of GCC command line'
  213.  say '*> -ord[inals] tells dllar to export entries by ordinals. Be careful.'
  214.  say '*> -ex[clude] defines symbols which will not be exported. You can define'
  215.  say '   multiple symbols, for example -ex "myfunc yourfunc _GLOBAL*"'
  216.  say '   If the last character of a symbol is "*", all symbols beginning'
  217.  say '   with the prefix before "*" will be exclude, (see _GLOBAL* above)'
  218.  say '*> -libf[lags] can be used to add INITGLOBAL/INITINSTANCE and/or'
  219.  say '   TERMGLOBAL/TERMINSTANCE flags to the dynamically-linked library'
  220.  say '*> -nocrtdll switch will disable linking the library against emx''s'
  221.  say '   C runtime DLLs'
  222.  say '*> All other switches (for example -L./ or -lmylib) will be passed'
  223.  say '   unchanged to GCC at the end of command line'
  224.  say '*> If you create a DLL from a library and you do not specify -o,'
  225.  say '   the basename for DLL and import library will be set to <library>_imp'
  226.  say '   i.e. "dllar gcc.a" will create gcc_imp.dll and gcc_imp.a'
  227.  say '--------'
  228.  say 'Example:'
  229.  say '   dllar -o gcc290.dll libgcc.a -d "GNU C runtime library" -ord'
  230.  say '    -ex "__main __ctordtor*" -libf "INITINSTANCE TERMINSTANCE"'
  231.  call CleanUp;
  232. exit 1;
  233.  
  234. GetLongArg:
  235.  i = i + 1;
  236.  _tmp_ = word(cmdLine, i);
  237.  if (left(_tmp_, 1) = '"') | (left(_tmp_, 1) = "'")
  238.   then do
  239.         do while (i < words(cmdLine) &,
  240.                   right(_tmp_, 1) \= left(_tmp_, 1))
  241.          i = i + 1;
  242.          if (_tmp_ = '')
  243.            then _tmp_ = word(cmdLine, i);
  244.            else _tmp_ = _tmp_' 'word(cmdLine, i);
  245.         end;
  246.         if (right(_tmp_, 1) = left(_tmp_, 1))
  247.          then _tmp_ = substr(_tmp_, 2, length(_tmp_) - 2);
  248.        end;
  249. return _tmp_;
  250.  
  251. export_ok:
  252.  procedure expose exclude_symbols;
  253.  parse arg line;
  254.  do i = 1 to words(exclude_symbols)
  255.   noexport = '"'word(exclude_symbols, i);
  256.   if right(noexport, 1) = '*'
  257.    then noexport = left(noexport, length(noexport) - 1)
  258.    else noexport = noexport'"';
  259.   if pos(noexport, line) > 0
  260.    then return 0;
  261.  end;
  262. return 1;
  263.  
  264. doCommand:
  265.  parse arg _cmd_;
  266.  say _cmd_;
  267.  '@'_cmd_;
  268.  if (rc \= 0)
  269.  then do
  270.        say 'command failed, exit code='rc;
  271.        call CleanUp;
  272.        exit 2;
  273.       end;
  274. return;
  275.  
  276. CleanUp:
  277.  call directory(curDir);
  278.  do i = inputFiles.0 to 1 by -1
  279.   if left(inputFiles.I, 1) = '!'
  280.    then call doCommand('rm -rf 'substr(inputFiles.I, 2));
  281.  end;
  282. return;
  283.