This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
How do I link to a shared lib without having that lib'sdependencies (the way MS link does)
- From: David Wuertele <dave-gnus at bfnet dot com>
- To: binutils at sources dot redhat dot com
- Date: Mon, 11 Aug 2003 19:28:57 -0700
- Subject: How do I link to a shared lib without having that lib'sdependencies (the way MS link does)
- Cancel-lock: sha1:zJ3x1Gcnr6rh2iX240qLrk1XGoI=
- Organization: Berkeley Fluent Network
I want to create a dynamic library, libA, that links with libB. Then
I want to create an executable that links with libA. But I don't want
to have to have libB around at compile time. But gcc/ld complains if
libB.so is not there! Why is that? My executable only makes calls to
libA. The dynamic loader should take care of libB, not the linker!
In windows, you can do what I want. I've constructed two scripts, one
for Linux using gcc/ld, and one for windows using cl/link, to
demonstrate what I want to do and what is going wrong in Linux. Can
anyone tell me how to achieve this with gcc/ld?
First, the Linux script (which demonstrates the problem). After this,
you can find the windows script (which demonstrates what I want to
do).
#!/bin/sh -v
# build.sh - build dynamic linking test LINUX
# Clean out all output files and ls
rm -f *.o *.so prog
ls -l
total 28
-rwxrwxr-x 1 dave dave 622 Aug 11 19:26 build.sh
-rw-rw-r-- 1 dave dave 148 Aug 11 19:04 libA.c
-rw-rw-r-- 1 dave dave 28 Aug 11 19:03 libA.h
-rw-rw-r-- 1 dave dave 80 Aug 11 19:04 libB.c
-rw-rw-r-- 1 dave dave 28 Aug 11 19:03 libB.h
-rw-rw-r-- 1 dave dave 403 Aug 11 18:46 Makefile
-rw-rw-r-- 1 dave dave 179 Aug 11 19:24 prog.c
# Print out each file
cat libA.h
/* A.h */
void libA_func();
cat libA.c
/* A.c */
#include <stdio.h>
#include "libA.h"
#include "libB.h"
void libA_func ()
{
printf ("libA_func() calling libB_func\n");
libB_func();
}
cat libB.h
/* B.h */
void libB_func();
cat libB.c
/* libB.c */
#include <stdio.h>
void libB_func ()
{
printf ("libB_func\n");
}
cat prog.c
/* prog.cpp */
#include <stdio.h>
#include "libA.h"
int main (int ac, char **av)
{
printf ("prog calling libA_func()\n");
libA_func();
printf ("prog done\n");
return 0;
}
# Compile libB.c into a shared library
gcc -shared -o libB.so libB.c
# Compile and link libA.c to libB.so
gcc -shared -o libA.so libA.c -L. -lB
# Remove libB.so
rm -f libB.so
# Compile and link prog.c to libA.so
gcc -o prog prog.c -L. -lA
/usr/bin/ld: warning: libB.so, needed by ./libA.so, not found (try using -rpath or -rpath-link)
./libA.so: undefined reference to `libB_func'
collect2: ld returned 1 exit status
# AAArgh! OK, Since ld complains, let's give it what it wants
# Why do we have to do this for Linux and not Windows?
gcc -shared -o libB.so libB.c
gcc -o prog prog.c -L. -lA -lB
--------------------------------------------------------------------------------
Now the windows script:
C:\libtest>REM -- build.bat - build dynamic linking test
C:\libtest>REM -- clean all output files and do a dir
C:\libtest>erase libB.obj libB.dll libB.exp libB.lib
C:\libtest>erase libA.obj libA.dll libA.exp libA.lib
C:\libtest>erase prog.obj prog.exe
C:\libtest>dir
Volume in drive C is SilverBox
Volume Serial Number is BCEE-2C23
Directory of C:\libtest
08/11/2003 04:09 PM <DIR> .
08/11/2003 04:09 PM <DIR> ..
08/11/2003 04:07 PM 1,437 build.bat
08/11/2003 03:33 PM 159 libA.c
08/11/2003 03:33 PM 65 libA.h
08/11/2003 03:33 PM 112 libB.c
08/11/2003 03:33 PM 65 libB.h
08/11/2003 03:45 PM 202 prog.c
6 File(s) 2,040 bytes
2 Dir(s) 40,561,799,168 bytes free
C:\libtest>REM -- cat the contents of the files
C:\libtest>type libA.h
// FILE: libA.h
extern __declspec(dllimport) void libA_func();
C:\libtest>type libA.c
// FILE: libA.c
#include "libB.h"
extern __declspec(dllexport) void libA_func()
{
printf("libA_func() calling libB_func()\n");
libB_func();
}
C:\libtest>type libB.h
// FILE: libB.h
extern __declspec(dllimport) void libB_func();
C:\libtest>type libB.c
// FILE: libB.c
extern __declspec(dllexport) void libB_func()
{
printf("libB_func() executing()\n");
}
C:\libtest>type prog.c
#include <stdio.h>
#include "libA.h"
int main(int argc, const char ** argv)
{
printf("prog.exe calling libA_func()\n");
libA_func();
printf("prog.exe exiting\n");
return 0;
}
C:\libtest>REM -- compile and link libB.c to libB.dll
C:\libtest>cl -c libB.c
libB.c
C:\libtest>link libB.obj /dll /out:"libB.dll" /implib:"libB.lib"
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Creating library libB.lib and object libB.exp
C:\libtest>REM -- compile and link libA.c to libA.dll doing
C:\libtest>REM -- the "-lB" equivalent
C:\libtest>cl -c libA.c
libA.c
C:\libtest>link libA.obj libB.lib /dll /out:"libA.dll" /implib:"libA.lib"
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Creating library libA.lib and object libA.exp
C:\libtest>REM -- erase all of the libB output files to prove that linking
C:\libtest>REM -- prog.c doesn't depend on libB.
C:\libtest>erase libB.obj libB.dll libB.exp libB.lib
C:\libtest>REM -- for good measure erase all of libA's output files except
C:\libtest>REM -- the export library and the dll
C:\libtest>erase libA.obj libA.exp
C:\libtest>REM -- do another dir so we can see what's in our directory now
C:\libtest>dir
Volume in drive C is SilverBox
Volume Serial Number is BCEE-2C23
Directory of C:\libtest
08/11/2003 04:09 PM <DIR> .
08/11/2003 04:09 PM <DIR> ..
08/11/2003 04:07 PM 1,437 build.bat
08/11/2003 03:33 PM 159 libA.c
08/11/2003 04:09 PM 45,056 libA.dll
08/11/2003 03:33 PM 65 libA.h
08/11/2003 04:09 PM 1,896 libA.lib
08/11/2003 03:33 PM 112 libB.c
08/11/2003 03:33 PM 65 libB.h
08/11/2003 03:45 PM 202 prog.c
8 File(s) 48,992 bytes
2 Dir(s) 40,561,750,016 bytes free
C:\libtest>REM -- compile prog.c into prog.exe
C:\libtest>cl prog.c libA.lib
prog.c
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:prog.exe
prog.obj
libA.lib
C:\libtest>REM -- now that prog.exe has built, re-compile and link
C:\libtest>REM -- libB so that prog.exe will run
C:\libtest>cl -c libB.c
libB.c
C:\libtest>link libB.obj /dll /out:"libB.dll" /implib:"libB.lib"
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Creating library libB.lib and object libB.exp
C:\libtest>REM -- let's delete all output files again and do a dir
C:\libtest>erase libB.obj libB.exp libB.lib
C:\libtest>erase libA.obj libA.exp libA.lib
C:\libtest>erase prog.obj
C:\libtest>dir
Volume in drive C is SilverBox
Volume Serial Number is BCEE-2C23
Directory of C:\libtest
08/11/2003 04:09 PM <DIR> .
08/11/2003 04:09 PM <DIR> ..
08/11/2003 04:07 PM 1,437 build.bat
08/11/2003 03:33 PM 159 libA.c
08/11/2003 04:09 PM 45,056 libA.dll
08/11/2003 03:33 PM 65 libA.h
08/11/2003 03:33 PM 112 libB.c
08/11/2003 04:09 PM 45,056 libB.dll
08/11/2003 03:33 PM 65 libB.h
08/11/2003 03:45 PM 202 prog.c
08/11/2003 04:09 PM 40,960 prog.exe
9 File(s) 133,112 bytes
2 Dir(s) 40,561,664,000 bytes free
C:\libtest>REM -- NOW FINALLY LET'S RUN THE PROGRAM!
C:\libtest>prog.exe
prog.exe calling libA_func()
libA_func() calling libB_func()
libB_func() executing()
prog.exe exiting
C:\libtest>REM
C:\libtest>REM
C:\libtest>REM
C:\libtest>REM -- and let's type this file
C:\libtest>type build.bat
REM -- build.bat - build dynamic linking test
REM -- clean all output files and do a dir
erase libB.obj libB.dll libB.exp libB.lib
erase libA.obj libA.dll libA.exp libA.lib
erase prog.obj prog.exe
dir
REM -- cat the contents of the files
type libA.h
type libA.c
type libB.h
type libB.c
type prog.c
REM -- compile and link libB.c to libB.dll
cl -c libB.c
link libB.obj /dll /out:"libB.dll" /implib:"libB.lib"
REM -- compile and link libA.c to libA.dll doing
REM -- the "-lB" equivalent
cl -c libA.c
link libA.obj libB.lib /dll /out:"libA.dll" /implib:"libA.lib"
REM -- erase all of the libB output files to prove that linking
REM -- prog.c doesn't depend on libB.
erase libB.obj libB.dll libB.exp libB.lib
REM -- for good measure erase all of libA's output files except
REM -- the export library and the dll
erase libA.obj libA.exp
REM -- do another dir so we can see what's in our directory now
dir
REM -- compile prog.c into prog.exe
cl prog.c libA.lib
REM -- now that prog.exe has built, re-compile and link
REM -- libB so that prog.exe will run
cl -c libB.c
link libB.obj /dll /out:"libB.dll" /implib:"libB.lib"
REM -- let's delete all output files again and do a dir
erase libB.obj libB.exp libB.lib
erase libA.obj libA.exp libA.lib
erase prog.obj
dir
REM -- NOW FINALLY LET'S RUN THE PROGRAM!
prog.exe
REM
REM
REM
REM -- and let's type this file
type build.bat