From: Stefan Neis Date: Mon, 8 Mar 2004 09:50:27 +0000 (+0000) Subject: Shell version of dllar, needed for building DLLs while generating X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/2d35020a8dd1a0908f4e76af323cc0d413d6b8c3 Shell version of dllar, needed for building DLLs while generating .def file on the fly. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@26135 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/os2/dllar.sh b/src/os2/dllar.sh new file mode 100644 index 0000000000..8ed5b4fb6b --- /dev/null +++ b/src/os2/dllar.sh @@ -0,0 +1,408 @@ +#!/bin/sh +# +# 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 +# Ported to Unix like shell by Stefan Neis, Stefan.Neis@t-online.de +# +# This script 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 +# - GNU file utilities (mv, rm) +# - GNU sed +# - lxlite (optional, see flag below) +# (used for general .dll cleanup) +# + +flag_USE_LXLITE=1; + +# +# helper functions +# basnam, variant of basename, which does _not_ remove the path, _iff_ +# second argument (suffix to remove) is given +basnam(){ + case $# in + 1) + echo $1 | sed 's/.*\///' | sed 's/.*\\//' + ;; + 2) + echo $1 | sed 's/'$2'$//' + ;; + *) + echo "error in basnam $*" + exit 8 + ;; + esac +} + +# Cleanup temporary files and output +CleanUp() { + cd $curDir + for i in $inputFiles ; do + case $i in + *!) + rm -rf `basnam $i !` + ;; + *) + ;; + esac + done + + # Kill result in case of failure as there is just to many stupid make/nmake + # things out there which doesn't do this. + if [ $# -eq 0 ]; then + rm -f "${outFile}.a" "${outFile}.def" "${outFile}.dll" + fi +} + +# Print usage and exit script with rc=1. +PrintHelp() { + echo 'Usage: dllar [-o[utput] output_file] [-d[escription] "dll descrption"]' + echo ' [-cc "CC"] [-f[lags] "CFLAGS"] [-ord[inals]] -ex[clude] "symbol(s)"' + echo ' [-libf[lags] "{INIT|TERM}{GLOBAL|INSTANCE}"] [-nocrt[dll]] [-nolxl[ite]]' + echo ' [*.o] [*.a]' + echo '*> "output_file" should have no extension.' + echo ' If it has the .o, .a or .dll extension, it is automatically removed.' + echo ' The import library name is derived from this and is set to "name".a.' + echo '*> "cc" is used to use another GCC executable. (default: gcc.exe)' + echo '*> "flags" should be any set of valid GCC flags. (default: -s -Zcrtdll)' + echo ' These flags will be put at the start of GCC command line.' + echo '*> -ord[inals] tells dllar to export entries by ordinals. Be careful.' + echo '*> -ex[clude] defines symbols which will not be exported. You can define' + echo ' multiple symbols, for example -ex "myfunc yourfunc _GLOBAL*".' + echo ' If the last character of a symbol is "*", all symbols beginning' + echo ' with the prefix before "*" will be exclude, (see _GLOBAL* above).' + echo '*> -libf[lags] can be used to add INITGLOBAL/INITINSTANCE and/or' + echo ' TERMGLOBAL/TERMINSTANCE flags to the dynamically-linked library.' + echo '*> -nocrt[dll] switch will disable linking the library against emx''s' + echo ' C runtime DLLs.' + echo '*> -nolxl[ite] switch will disable running lxlite on the resulting DLL.' + echo '*> All other switches (for example -L./ or -lmylib) will be passed' + echo ' unchanged to GCC at the end of command line.' + echo '*> If you create a DLL from a library and you do not specify -o,' + echo ' the basename for DLL and import library will be set to library name,' + echo ' the initial library will be renamed to 'name'_s.a (_s for static)' + echo ' i.e. "dllar gcc.a" will create gcc.dll and gcc.a, and the initial' + echo ' library will be renamed into gcc_s.a.' + echo '--------' + echo 'Example:' + echo ' dllar -o gcc290.dll libgcc.a -d "GNU C runtime library" -ord' + echo ' -ex "__main __ctordtor*" -libf "INITINSTANCE TERMINSTANCE"' + CleanUp + exit 1 +} + +# Execute a command. +# If exit code of the commnad <> 0 CleanUp() is called and we'll exit the script. +# @Uses Whatever CleanUp() uses. +doCommand() { + echo "$*" + eval $* + rcCmd=$? + + if [ $rcCmd -ne 0 ]; then + echo "command failed, exit code="$rcCmd + CleanUp + exit $rcCmd + fi +} + +# main routine +# setup globals +cmdLine=$* +outFile="" +inputFiles="" +description="" +CC=gcc.exe +CFLAGS="-s -Zcrtdll" +EXTRA_CFLAGS="" +EXPORT_BY_ORDINALS=0 +exclude_symbols="" +library_flags="" +curDir=`pwd` +curDirS=curDir +case $curDirS in +*/) + ;; +*) + curDirS=${curDirS}"/" + ;; +esac +# Parse commandline +libsToLink=0 +while [ $1 ]; do + case $1 in + -ord*) + EXPORT_BY_ORDINALS=1; + ;; + -o*) + shift + outFile=$1 + ;; + -d*) + shift + description=$1 + ;; + -f*) + shift + CFLAGS=$1 + ;; + -c*) + shift + CC=$1 + ;; + -h*) + PrintHelp + ;; + -ex*) + shift + exclude_symbols=${exclude_symbols}$1" " + ;; + -libf*) + shift + library_flags=${library_flags}$1" " + ;; + -nocrt*) + CFLAGS="-s" + ;; + -nolxl*) + flag_USE_LXLITE=0 + ;; + -* | /* | *.dll) + case $1 in + -L* | -l*) + libsToLink=1 + ;; + *) + ;; + esac + EXTRA_CFLAGS=${EXTRA_CFLAGS}" "$1 + ;; + *) + found=0; + if [ $libsToLink -ne 0 ]; then + EXTRA_CFLAGS=${EXTRA_CFLAGS}" "$1 + else + for file in $1 ; do + if [ -f $file ]; then + inputFiles="${inputFiles} $file" + found=1 + fi + done + if [ $found -eq 0 ]; then + echo "ERROR: No file(s) found: "$1 + exit 8 + fi + fi + ;; + esac + shift +done # iterate cmdline words + +# +if [ -z "$inputFiles" ]; then + echo "dllar: no input files" + PrintHelp +fi + +# Now extract all .o files from .a files +newInputFiles="" +for file in $inputFiles ; do + case $file in + *.a | *.lib) + case $file in + *.a) + suffix=".a" + AR="ar" + ;; + *.lib) + suffix=".lib" + AR="emxomfar" + ;; + *) + ;; + esac + dirname=`basnam $file $suffix`"_%" + mkdir $dirname + if [ $? -ne 0 ]; then + echo "Failed to create subdirectory ./$dirname" + CleanUp + exit 8; + fi + # Append '!' to indicate archive + newInputFiles="$newInputFiles ${dirname}!" + doCommand "cd $dirname; $AR x ../$file" + cd $curDir + found=0; + for subfile in $dirname/*.o ; do + if [ -f $subfile ]; then + found=1 + if [ -s $subfile ]; then + # FIXME: This should be: is file size > 32 byte, _not_ > 0! + newInputFiles="$newInputFiles $subname" + fi + fi + done + if [ $found -eq 0 ]; then + echo "WARNING: there are no files in archive \'$file\'" + fi + ;; + *) + newInputFiles="${newInputFiles} $file" + ;; + esac +done +inputFiles="$newInputFiles" + +# Output filename(s). +do_backup=0; +if [ -z $outFile ]; then + do_backup=1; + set outFile $inputFiles; outFile=$2 +fi + +# If it is an archive, remove the '!' and the '_%' suffixes +case $outFile in +*_%!) + outFile=`basnam $outFile _%!` + ;; +*) + ;; +esac +case $outFile in +*.dll) + outFile=`basnam $outFile .dll` + ;; +*.DLL) + outFile=`basnam $outFile .DLL` + ;; +*.o) + outFile=`basnam $outFile .o` + ;; +*.obj) + outFile=`basnam $outFile .obj` + ;; +*.a) + outFile=`basnam $outFile .a` + ;; +*.lib) + outFile=`basnam $outFile .lib` + ;; +*) + ;; +esac +defFile="${outFile}.def" +dllFile="${outFile}.dll" +arcFile="${outFile}.a" + +if [ $do_backup -ne 0 -a -f $arcFile ] ; then + doCommand "mv $arcFile ${outFile}_s.a" +fi + +# Extract public symbols from all the object files. +tmpdefFile=${defFile}_% +rm -f $tmpdefFile +for file in $inputFiles ; do + case $file in + *!) + ;; + *) + doCommand "emxexp -u $file >> $tmpdefFile" + ;; + esac +done + +# Create the def file. +rm -f $defFile +libName=`basnam $outFile` +echo "LIBRARY `echo $libName | sed 's/\./_/'` $library_flags" >> $defFile +if [ -n $description ]; then + echo "DESCRIPTION \"${description}\"" >> $defFile +fi +echo "EXPORTS" >> $defFile + +doCommand "cat $tmpdefFile | sort.exe | uniq.exe > ${tmpdefFile}%" +grep -v "^ *;" < ${tmpdefFile}% | grep -v "^ *$" >$tmpdefFile + +# Checks if the export is ok or not. +for word in $exclude_symbols; do + grep -v $word < $tmpdefFile >${tmpdefFile}% + mv ${tmpdefFile}% $tmpdefFile +done + + +if [ $EXPORT_BY_ORDINALS -ne 0 ]; then + sed "=" < $tmpdefFile | \ + sed ' + N + : loop + s/^\([0-9]\+\)\([^;]*\)\(;.*\)\?/\2 @\1 NONAME/ + t loop + ' > ${tmpdefFile}% + grep -v "^ *$" < ${tmpdefFile}% > $tmpdefFile +else + rm -f ${tmpdefFile}% +fi +cat $tmpdefFile >> $defFile +rm -f $tmpdefFile + +# Do linking, create implib, and apply lxlite. +gccCmdl=""; +for file in $inputFiles ; do + case $file in + *!) + ;; + *) + gccCmdl="$gccCmdl $file" + ;; + esac +done +doCommand "$CC $CFLAGS -Zdll -o $dllFile $defFile $gccCmdl $EXTRA_CFLAGS" + +doCommand "emximp -o $arcFile $defFile" +if [ $flag_USE_LXLITE -ne 0 ]; then + add_flags=""; + if [ $EXPORT_BY_ORDINALS -ne 0 ]; then + add_flags="-ynd" + fi + doCommand "lxlite -cs -t: -mrn -mln $add_flags $dllFile" +fi + +# Successful exit. +CleanUp 1 +exit 0