276 lines
17 KiB
Plaintext
276 lines
17 KiB
Plaintext
plugin-test
|
|
Bryce Denney
|
|
|
|
This is a series of simple programs that test your platform for shared
|
|
library support. The tests start from something trivial that should
|
|
work everywhere, and gradually add one feature at a time, until at
|
|
the end (not done yet) it should test all of the shared library
|
|
features that Bochs needs to support plugins.
|
|
|
|
test1-static: build a static library and link against it
|
|
test2-dynamic: with same code, build a shared library and link against it
|
|
test3-twomodules: build 2 shared libs and link against them
|
|
test4-interdep: build 2 shared libs, one depends on the other, and link
|
|
test5-execsymbols: can a shared lib can access a symbol from the executable?
|
|
test6-ltdlopen: use ltdl library to dlopen modules, should work on many
|
|
platforms, but doesn't seem to work on win32.
|
|
test7-win32dll: same as test6-ltdlopen but specific to win32 DLLs
|
|
test8-execlass: define a C++ class in main, use it from the modules
|
|
test9-modclass: define a C++ class in a module, use it from main
|
|
test10-modvirtual: define an abstract interface with instantiations in modules
|
|
test11-modglobalconstr: test if global constructors in shared libs are called
|
|
test12-modglobalconstr2: work around lack of global constructors, if needed
|
|
|
|
-----------------------------------------------------------------------
|
|
Results of platform testing:
|
|
|
|
x86 Linux:
|
|
passing: 1,2,3,4,5,6,8,9,10,11,12.
|
|
This platform will support plugins.
|
|
|
|
Cygwin with these environment variables (Mingw):
|
|
export CPPFLAGS=-mno-cygwin;
|
|
export CFLAGS=-mno-cygwin
|
|
export CXXFLAGS=-mno-cygwin;
|
|
export LDFLAGS=-mno-cygwin
|
|
passing 1,6,7,8,9,10,11,12.
|
|
When compiling in Cygwin, Bochs always compiles with -mno-cygwin, so
|
|
this is the normal build environment. This platform will support plugins.
|
|
|
|
Cygwin without -mno-cygwin:
|
|
passing: 1,2,3,4. failing 5-12.
|
|
This platform will NOT support plugins yet.
|
|
|
|
Solaris:
|
|
passing: 1,2,3,4,5,6,8,9,10,12.
|
|
This platform will support plugins.
|
|
NOTE: Global constructors in shared modules are not executed when
|
|
the module is loaded. That is why test 11 fails. As long as we don't depend
|
|
on global constructors, Solaris plugins should work fine.
|
|
|
|
MacOS X:
|
|
passing: 1,2,3,4,5,6,8,9,10,11,12.
|
|
This platform will support plugins.
|
|
NOTE: You must have the dlcompat library installed where configure can
|
|
find it. On the SF compile farm, I use these commands before configure:
|
|
export LIBS='-L/sw/lib'
|
|
export CFLAGS='-I/sw/include'
|
|
export CPPFLAGS='-I/sw/include'
|
|
export CXXFLAGS='-I/sw/include'
|
|
NOTE: On MacOS X we cannot have the same symbol name in two different
|
|
modules; we must name the symbols so that the symbol names are unique. In
|
|
tests 6,7-12, the modules.h file uses #defines to rename each global symbol
|
|
to something unique.
|
|
|
|
No other platform data is available.
|
|
To check for plugin support on other platforms, run "do_tests.sh" and
|
|
send the results to Bryce.
|
|
-----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Notes for win32 DLLs:
|
|
|
|
*.dll.a is an import library
|
|
|
|
libtool makes an import library when you link against a DLL
|
|
|
|
dlltool --as=as --dllname cygmodule2-0.dll --def .libs/cygmodule2-0.dll-def --output-lib .libs/libimp-cygmodule2-0.a
|
|
|
|
the dll-def file is created at the time that the DLL is created.
|
|
|
|
Exporting a class from a DLL...
|
|
http://www.codeguru.com/win32/dyndllclass.shtml
|
|
|
|
|
|
|
|
|
|
Win32 DLL Topics
|
|
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_dll_topics.asp
|
|
|
|
------
|
|
Mutual DLL imports
|
|
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_mutual_imports.asp
|
|
|
|
Exporting or importing to another executable file presents complications when
|
|
the imports are mutual (or "circular"). For example, two DLLs import symbols
|
|
from each other, similar to mutually-recursive functions.
|
|
|
|
The problem with mutually-importing executable files (usually DLLs) is that
|
|
neither can be built without building the other first. Each build process
|
|
requires, as input, an import library produced by the other build process.
|
|
|
|
The solution is to use the LIB utility with the /DEF option, which produces an
|
|
import library without building the executable file. Using this utility, you
|
|
can build all the import libraries you need, no matter how many DLLs are
|
|
involved or how complicated the dependencies are.
|
|
|
|
The general solution for handling mutual imports is:
|
|
|
|
1.Take each DLL in turn. (Any order is feasible, although some orders are more
|
|
optimal.) If all the needed import libraries exist and are current, run LINK to
|
|
build the executable file (DLL). This produces an import library. Otherwise,
|
|
run LIB to produce an import library.
|
|
|
|
Running LIB with the /DEF option produces an additional file with an .EXP
|
|
extension. The .EXP file must be used later to build the executable file.
|
|
|
|
2.After using either LINK or LIB to build all the import libraries, go back and
|
|
run LINK to build any executable files that were not built in the previous
|
|
step. Note that the corresponding .EXP file must be specified on the LINK line.
|
|
|
|
If you had run the LIB utility earlier to produce an import library for DLL1,
|
|
LIB would have produced the file DLL1.EXP as well. You must use DLL1.EXP as
|
|
input to LINK when building DLL1.DLL.
|
|
-----------
|
|
|
|
this makes a symbol table for a file
|
|
|
|
dlltool.exe --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def def.txt uselib.exe
|
|
|
|
These lines from test4 show that libtool does know how to make
|
|
import libraries:
|
|
> generating import library for `cygmodule1-0.dll'
|
|
> dlltool --as=as --dllname cygmodule1-0.dll --def .libs/cygmodule1-0.dll-def --output-lib .libs/libimp-cygmodule1-0.a
|
|
|
|
Now what I want to see is generation of an import library corresponding to
|
|
a BINARY.
|
|
|
|
|
|
/bin/sh.exe ../libtool g++ -g -O2 -c module1.cc
|
|
mkdir .libs
|
|
g++ -g -O2 -c module1.cc -DDLL_EXPORT -DPIC -o .libs/module1.lo
|
|
In file included from module1.cc:2:
|
|
module1.h:4: warning: #warning I will export DLL symbols for MODULE1
|
|
In file included from module1.cc:3:
|
|
module2.h:8: warning: #warning I will import DLL symbols for MODULE2
|
|
g++ -g -O2 -c module1.cc -o module1.o >/dev/null 2>&1
|
|
mv -f .libs/module1.lo module1.lo
|
|
/bin/sh.exe ../libtool g++ -g -O2 -c module2.cc
|
|
rm -f .libs/module2.lo
|
|
g++ -g -O2 -c module2.cc -DDLL_EXPORT -DPIC -o .libs/module2.lo
|
|
In file included from module2.cc:3:
|
|
module2.h:4: warning: #warning I will export DLL symbols for MODULE2
|
|
g++ -g -O2 -c module2.cc -o module2.o >/dev/null 2>&1
|
|
mv -f .libs/module2.lo module2.lo
|
|
/bin/sh.exe ../libtool g++ -no-undefined -o libmodule2.la module2.lo -rpath `pwd`/lib
|
|
rm -fr .libs/libmodule2.la .libs/libmodule2.* .libs/libmodule2.*
|
|
generating symbol list for `libmodule2.la'
|
|
dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule2-0.dll-def module2.lo
|
|
sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule2-0.dll-def > .libs/libmodule2.exp
|
|
if test "x`head -1 .libs/libmodule2.exp`" = xEXPORTS; then cp .libs/libmodule2.exp .libs/cygmodule2-0.dll-def; else echo EXPORTS > .libs/cygmodule2-0.dll-def; _lt_hint=1; cat .libs/libmodule2.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule2-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule2-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi
|
|
gcc -Wl,--base-file,.libs/cygmodule2-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo
|
|
dlltool --as=as --dllname cygmodule2-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule2-0.dll-def --base-file .libs/cygmodule2-0.dll-base --output-exp .libs/cygmodule2-0.dll-exp
|
|
gcc -Wl,--base-file,.libs/cygmodule2-0.dll-base .libs/cygmodule2-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo
|
|
dlltool --as=as --dllname cygmodule2-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule2-0.dll-def --base-file .libs/cygmodule2-0.dll-base --output-exp .libs/cygmodule2-0.dll-exp --output-lib .libs/libmodule2.dll.a
|
|
gcc .libs/cygmodule2-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo
|
|
ar cru .libs/libmodule2.a module2.o
|
|
ranlib .libs/libmodule2.a
|
|
creating libmodule2.la
|
|
(cd .libs && rm -f libmodule2.la && ln -s ../libmodule2.la libmodule2.la)
|
|
mkdir -p lib bin
|
|
/bin/sh.exe ../libtool cp libmodule2.la `pwd`/lib
|
|
cp .libs/libmodule2.dll.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.dll.a
|
|
dlpath=`bash 2>&1 -c '. .libs/libmodule2.lai;echo $dlname'`
|
|
dldir=/home/bryce/bochs-testing/plugin-test/test4-interdep/lib/`dirname $dlpath`
|
|
test -d $dldir || mkdir -p $dldir
|
|
cp .libs/cygmodule2-0.dll $dldir/cygmodule2-0.dll
|
|
cp .libs/libmodule2.lai /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.la
|
|
cp .libs/libmodule2.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a
|
|
ranlib /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a
|
|
chmod 644 /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a
|
|
----------------------------------------------------------------------
|
|
Libraries have been installed in:
|
|
/home/bryce/bochs-testing/plugin-test/test4-interdep/lib
|
|
|
|
If you ever happen to want to link against installed libraries
|
|
in a given directory, LIBDIR, you must either use libtool, and
|
|
specify the full pathname of the library, or use the `-LLIBDIR'
|
|
flag during linking and do at least one of the following:
|
|
- add LIBDIR to the `PATH' environment variable
|
|
during execution
|
|
- add LIBDIR to the `LD_RUN_PATH' environment variable
|
|
during linking
|
|
- use the `-Wl,--rpath -Wl,LIBDIR' linker flag
|
|
|
|
See any operating system documentation about shared libraries for
|
|
more information, such as the ld(1) and ld.so(8) manual pages.
|
|
----------------------------------------------------------------------
|
|
/bin/sh.exe ../libtool g++ -no-undefined -o libmodule1.la module1.lo -rpath `pwd`/lib libmodule2.la
|
|
generating import library for `cygmodule2-0.dll'
|
|
dlltool --as=as --dllname cygmodule2-0.dll --def .libs/cygmodule2-0.dll-def --output-lib .libs/libimp-cygmodule2-0.a
|
|
rm -fr .libs/libmodule1.la .libs/libmodule1.* .libs/libmodule1.*
|
|
generating symbol list for `libmodule1.la'
|
|
dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule1-0.dll-def module1.lo
|
|
sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule1-0.dll-def > .libs/libmodule1.exp
|
|
if test "x`head -1 .libs/libmodule1.exp`" = xEXPORTS; then cp .libs/libmodule1.exp .libs/cygmodule1-0.dll-def; else echo EXPORTS > .libs/cygmodule1-0.dll-def; _lt_hint=1; cat .libs/libmodule1.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule1-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule1-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi
|
|
gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a
|
|
dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp
|
|
gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a
|
|
dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp --output-lib .libs/libmodule1.dll.a
|
|
gcc .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a
|
|
ar cru .libs/libmodule1.a module1.o
|
|
ranlib .libs/libmodule1.a
|
|
creating libmodule1.la
|
|
(cd .libs && rm -f libmodule1.la && ln -s ../libmodule1.la libmodule1.la)
|
|
mkdir -p lib bin
|
|
/bin/sh.exe ../libtool cp libmodule1.la `pwd`/lib
|
|
libtool: install: warning: relinking `libmodule1.la'
|
|
cd /home/bryce/bochs-testing/plugin-test/test4-interdep; /bin/sh ../libtool --mode=relink g++ -no-undefined -o libmodule1.la module1.lo -rpath /home/bryce/bochs-testing/plugin-test/test4-interdep/lib libmodule2.la
|
|
generating symbol list for `libmodule1.la'
|
|
dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule1-0.dll-def module1.lo
|
|
sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule1-0.dll-def > .libs/libmodule1.exp
|
|
if test "x`head -1 .libs/libmodule1.exp`" = xEXPORTS; then cp .libs/libmodule1.exp .libs/cygmodule1-0.dll-def; else echo EXPORTS > .libs/cygmodule1-0.dll-def; _lt_hint=1; cat .libs/libmodule1.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule1-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule1-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi
|
|
gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2
|
|
dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp
|
|
gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2
|
|
dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp --output-lib .libs/libmodule1.dll.a
|
|
gcc .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2
|
|
cp .libs/libmodule1.dll.aT /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.dll.a
|
|
dlpath=`bash 2>&1 -c '. .libs/libmodule1.lai;echo $dlname'`
|
|
dldir=/home/bryce/bochs-testing/plugin-test/test4-interdep/lib/`dirname $dlpath`
|
|
test -d $dldir || mkdir -p $dldir
|
|
cp .libs/cygmodule1-0.dll $dldir/cygmodule1-0.dll
|
|
cp .libs/libmodule1.lai /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.la
|
|
cp .libs/libmodule1.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a
|
|
ranlib /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a
|
|
chmod 644 /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a
|
|
----------------------------------------------------------------------
|
|
Libraries have been installed in:
|
|
/home/bryce/bochs-testing/plugin-test/test4-interdep/lib
|
|
|
|
If you ever happen to want to link against installed libraries
|
|
in a given directory, LIBDIR, you must either use libtool, and
|
|
specify the full pathname of the library, or use the `-LLIBDIR'
|
|
flag during linking and do at least one of the following:
|
|
- add LIBDIR to the `PATH' environment variable
|
|
during execution
|
|
- add LIBDIR to the `LD_RUN_PATH' environment variable
|
|
during linking
|
|
- use the `-Wl,--rpath -Wl,LIBDIR' linker flag
|
|
|
|
See any operating system documentation about shared libraries for
|
|
more information, such as the ld(1) and ld.so(8) manual pages.
|
|
----------------------------------------------------------------------
|
|
/bin/sh.exe ../libtool g++ -no-undefined -o uselib ./uselib.cc libmodule1.la libmodule2.la
|
|
generating import library for `cygmodule1-0.dll'
|
|
dlltool --as=as --dllname cygmodule1-0.dll --def .libs/cygmodule1-0.dll-def --output-lib .libs/libimp-cygmodule1-0.a
|
|
g++ -o .libs/uselib ./uselib.cc .libs/libimp-cygmodule1-0.a .libs/libimp-cygmodule2-0.a -Wl,--rpath -Wl,/home/bryce/bochs-testing/plugin-test/test4-interdep/lib
|
|
In file included from ./uselib.cc:2:
|
|
module1.h:8: warning: #warning I will import DLL symbols for MODULE1
|
|
In file included from ./uselib.cc:3:
|
|
module2.h:8: warning: #warning I will import DLL symbols for MODULE2
|
|
creating uselib.exe
|
|
|
|
|
|
|
|
Try making a dll with everything in it, and then a nearly empty object that
|
|
|
|
build libmain.la with main.lo
|
|
build module1.la with libmain.la
|
|
build module2.la with libmain.la
|
|
build .exe from libmain.la
|
|
|
|
Then main.cc can dlopen module1.la
|