Subject: Re: cygwin compiled DLLs
From: [email-masked] (Mark Levedahl)

19 Dec 1998 15:39:56 -0800
Message-ID: <[email-masked]>
References: <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
To: Charles Wilson <[email-masked]>
Cc: [email-masked]

Charles Wilson wrote:

> I had no idea this was possible. This is great! Please either post it to the
> list, or check into uploading it to the ftp.franken.de repository.
>
> Chuck Wilson
>
> 

Ok, here it is. A couple of caveats:

1) I have only ever used this script to assemble multiple .c files together: c++
source might be useable, but I've never tried (and see note 2). Also, the script
expects only source files, no precompiled objects or other libraries. You could
easily modify for that.

2) MATLAB controls all memory allocation for its session, including any MEX
files. Hence, all memory allocation must go through mxMalloc/mxCalloc/MxFree.
Directly accessing malloc/free is not allowed. Thus, any library functions that
allocate memory must be recompiled using these memory allocation routines. (This
explains why opendir fails). I suspect c++ new/delete would need overloads as
well.

3) That said, I have had success linking to both the cygwin and mscrt libraries
(the latter through -mno-cygwin).

Mark Levedahl

#! /bin/bash
# compile and link a MATLAB MEX file (relocatable DLL)
#

# required import libraries
IMPDEFS="matlab.exe libmx.dll"

# ***Fill in your path to libcygwin.a here (with no trailing slash)***
LIBPATH=${CYGFS}/H-i586-cygwin32/i586-cygwin32/lib

# ***Fill in your path to the matlab 5 root here (with no trailing slash)***
MATLAB=/app/matlab

# ***Fill in your path to place to store .def files generated by this script
LIBMEX=$MATLAB/bin/implibs

# check for arguments
if [ $# -lt 1 ]; then
 echo "usage: cmex [-cig5] source"
 exit
fi

debug=0
inline=0
type=-mno-cygwin
arch=i686
while getopts cig5? v; do
 if [ "$v" == "?" ]; then
  echo "usage: cmex [-cig5] source"
  echo "   c : link to cygwin1.dll (default:mingw)"
  echo "   i : inline array access"
  echo "   g : include debug info"
  echo "   5 : optimize for pentium (default:686)"
  exit

 else
  case $v in
   (g) debug=1;;
   (i) inline=1;;
   (5) arch=i586;;
   (c) type= ;;
  esac
 fi
done

while [ $OPTIND -gt 1 ]; do
 shift
 OPTIND=$(($OPTIND - 1))
done

# debug or what?
if [ $debug -eq 1 ]; then
 gccopts="-Wall -g $type"
else
 gccopts="-Wall -O6 $type -march=$arch -ffast-math -fstrict-aliasing
-malign-double"
fi

# inline array access?
if [ $inline -eq 0 ]; then
 rcopts=
else
 rcopts="--define ARRAY_ACCESS_INLINING"
 gccopts="$gccopts -DARRAY_ACCESS_INLINING"
fi

# source file name(s)
source=$*
base=${1%.*}
objs=${*//%.*/.o}

# Compile source file(s):
echo "windres $rcopts -i $MATLAB/extern/include/mexversion.rc -o mexversion.o"
windres $rcopts -i $MATLAB/extern/include/mexversion.rc -o mexversion.o || exit
echo "gcc -c $gccopts -DMATLAB_MEX_FILE -I$MATLAB/extern/include ${source}"
gcc -c $gccopts -DMATLAB_MEX_FILE -I$MATLAB/extern/include ${source} || exit

# Create fixup.o which is needed to terminate the
# import list and the relocation section in the dll.
cat > fixup.c << EOF
/* Copied from winsup/dcrt0.cc in the cygwin32 source distribution. */
asm(".section .idata\$3\n" ".long 0,0,0,0, 0,0,0,0");
/* Next one is needed to properly terminate the .reloc section in the dll
*/
asm(".section .reloc\n" ".long 0,8");
EOF
gcc -c $gccopts fixup.c

# Create a very minimalist startup routine for the dll.
# C copy of winsup/init.cc in the cygwin32 source distribution.
cat > init.c << EOF
#include <windows.h>
int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return 1;
}
EOF
gcc -c $gccopts init.c

# create import libraries if needed...
# Note:
#    Dlltool release does not like .def files to start with a line 'LIBRARY
#    <libname>'.  Therefore this workaround: extract library name from line 1
#    into variable libname and feed dlltool with a .def file with the 1st
#    line stripped so the .def file starts with the line 'EXPORTS'

IMPLIBS=
if [ ! -d $LIBMEX ];then
 mkdir -p $LIBMEX
fi
for libname in ${IMPDEFS}; do
 if [ ! -f $LIBMEX/${libname%.*}.a ];then
  cd $MATLAB/bin
  echo "Creating $libname import library..."
  tail +2l $MATLAB/extern/include/matlab.def > temp.def
  echo dlltool --def temp.def --dllname $libname --output-lib
$LIBMEX/${libname%.*}.a
  dlltool --def temp.def --dllname $libname --output-lib $LIBMEX/${libname%.*}.a
|| exit
  rm temp.def
  cd -
 else
  echo "Will use existing import library $LIBMEX/${libname%.*}.a"
 fi
 IMPLIBS="${IMPLIBS} $LIBMEX/${libname%.*}.a"
done

# Make .def file:
echo EXPORTS > ${base}.def
echo mexFunction >> ${base}.def

# Link DLL.
echo 'Linking DLL...'
dllwrap -o ${base}.dll --def ${base}.def --entry _dll_entry@12 \
 ${objs} init.o fixup.o mexversion.o ${IMPLIBS} $LIBPATH/libcygwin.a

# Clean up
rm ${base}.o init.c init.o fixup.c fixup.o mexversion.o ${base}.def

-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".