This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

How do I link to a shared lib without having that lib'sdependencies (the way MS link does)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]