* Why does linking a.so with b.so require execs to be linked both -la and -lb? @ 2003-08-11 21:02 David Wuertele 2003-08-11 23:50 ` Mike Castle 2003-08-12 13:16 ` Glynn Clements 0 siblings, 2 replies; 9+ messages in thread From: David Wuertele @ 2003-08-11 21:02 UTC (permalink / raw) To: linux-c-programming # I'm creating a shared library like this: libDaveA.so: $(LIB_OBJECTS) $(CXX) -shared -ldl -rdynamic -o $@ $^ -lDaveB -lDaveC -lDaveD -lDaveE # And I have some executables that use the shared lib: daveprog: daveprog.cpp $(CXX) -o $@ $^ -lDaveA The executable doesn't use any of the functions from libDaveB.so, libDaveC.so, libDaveD.so, or libDaveE.so. It only uses functions from libDaveA.so. But when I compile with the above makefile, gcc complains: /usr/tools/lib/gcc-lib/mipsel-linux/2.96/../../../../mipsel-linux/bin/ld: warning: libDaveB.so.0, needed by /usr/local/lib/libDaveA.so, not found (try using -rpath or -rpath-link) Why is that? Why should daveprog, which never uses any functionality AT ALL from libDaveB.so, have to link to it? Dave ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-11 21:02 Why does linking a.so with b.so require execs to be linked both -la and -lb? David Wuertele @ 2003-08-11 23:50 ` Mike Castle 2003-08-12 0:10 ` David Wuertele 2003-08-12 0:11 ` David Wuertele 2003-08-12 13:16 ` Glynn Clements 1 sibling, 2 replies; 9+ messages in thread From: Mike Castle @ 2003-08-11 23:50 UTC (permalink / raw) To: linux-c-programming In article <m3k79jj4av.fsf@bfnet.com>, David Wuertele <dave-gnus@bfnet.com> wrote: >Why is that? Why should daveprog, which never uses any functionality >AT ALL from libDaveB.so, have to link to it? Consider what would happen if everything was using static libraries instead. In my opinion, it should be a consistent command line between static and dynamic linking, with adding -static the only difference. mrc -- Mike Castle dalgoda@ix.netcom.com www.netcom.com/~dalgoda/ We are all of us living in the shadow of Manhattan. -- Watchmen fatal ("You are in a maze of twisty compiler features, all different"); -- gcc ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-11 23:50 ` Mike Castle @ 2003-08-12 0:10 ` David Wuertele 2003-08-12 13:49 ` Glynn Clements 2003-08-12 0:11 ` David Wuertele 1 sibling, 1 reply; 9+ messages in thread From: David Wuertele @ 2003-08-12 0:10 UTC (permalink / raw) To: linux-c-programming I asked my friend, who is a windows programmer, whether windows had the same behavior. He said absolutely not, and generated this test. His test is even more interesting than mine. It does the following: 1. build two libraries libA and libB. libA has one function that calls a function in libB. 2. link libA and libB 3. Erase libB 4. link a program that uses A's function with libA --- WITHOUT HAVING ACCESS TO libB! Why can't we do this on Linux? Here's the windows demonstration: 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 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-12 0:10 ` David Wuertele @ 2003-08-12 13:49 ` Glynn Clements 2003-08-12 16:42 ` David Wuertele 0 siblings, 1 reply; 9+ messages in thread From: Glynn Clements @ 2003-08-12 13:49 UTC (permalink / raw) To: David Wuertele; +Cc: linux-c-programming David Wuertele wrote: > I asked my friend, who is a windows programmer, whether windows had > the same behavior. He said absolutely not, and generated this test. > His test is even more interesting than mine. It does the following: > > 1. build two libraries libA and libB. libA has one function that > calls a function in libB. > 2. link libA and libB > 3. Erase libB > 4. link a program that uses A's function with libA --- WITHOUT HAVING > ACCESS TO libB! > > Why can't we do this on Linux? > > Here's the windows demonstration: > 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(); > } So libA_func() calls libB_func(). So any program which calls libA_func() will only work if libB.dll is available. > 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; > } So this program requires libB.dll. > 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 -- 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 So, what you are asking is why Linux requires the indirect dependencies to be present at link time, right? One fundamental difference between the way in which Linux and Windows handle shared libraries is that Windows associates external references (either from a program or from a DLL) with a specific library. E.g. the program will have a dependency upon "libA_func in libA.dll", while libA.dll will have a dependency upon "libB_func in libB.dll". OTOH, on Linux, the dependency isn't associated with a specific library. E.g. libA.so just needs libB_func; it doesn't matter where it comes from. If the program exported that function, you could link against libA.so without libB.so (unless libA.so listed it as an explicit dependency). One consequence of this difference is that Linux allows an executable to export symbols to a library. Thus you can create a library with unresolved references (i.e. symbols not provided by either the library or any of it's explicit dependencies). So long as that symbol actually gets provided at run-time (e.g. by the executable itself), everything works. The fact that Windows disallows this (every import has to be provided by a specific library, not some yet-to-be-built executable) allows it to perform the check for a specific library when that library is built. OTOH, Linux can't perform the check until the final link. BTW, In most cases, it doesn't actually *need* to do it until run-time; the run-time linker just loads everything and, so long as there are no unresolved symbols at that point, everything works. The one exception is that, unless you use the -E switch, the executable will only export those symbols which are required by any of the libraries; consequently, this complete set of libraries must be available to the linker. In any case: if you need libB.so to actually run the executable, why does it matter if you need it in order to link the program? -- Glynn Clements <glynn.clements@virgin.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-12 13:49 ` Glynn Clements @ 2003-08-12 16:42 ` David Wuertele 2003-08-12 17:54 ` Glynn Clements 2003-08-12 19:12 ` Steven 0 siblings, 2 replies; 9+ messages in thread From: David Wuertele @ 2003-08-12 16:42 UTC (permalink / raw) To: linux-c-programming Thanks Glynn, for the excellent explanation! Glynn> So, what you are asking is why Linux requires the indirect Glynn> dependencies to be present at link time, right? Exactly. Glynn> One consequence of this difference is that Linux allows an Glynn> executable to export symbols to a library. Thus you can create Glynn> a library with unresolved references (i.e. symbols not provided Glynn> by either the library or any of it's explicit dependencies). So Glynn> long as that symbol actually gets provided at run-time (e.g. by Glynn> the executable itself), everything works. Does this "flexibility" have practical applications? Glynn> In any case: if you need libB.so to actually run the Glynn> executable, why does it matter if you need it in order to link Glynn> the program? Encapsulation and portability. We're writing a toolkit that isolates the programmer from the underlying implementation. Requiring the programmer to explicitly link to the underlying library requires that the programmer know what that underlying library is. Also, it prevents us from changing the underlying library. These goals don't seem that unreasonable to us, and they are very important for our application. Dave ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-12 16:42 ` David Wuertele @ 2003-08-12 17:54 ` Glynn Clements 2003-08-12 19:12 ` Steven 1 sibling, 0 replies; 9+ messages in thread From: Glynn Clements @ 2003-08-12 17:54 UTC (permalink / raw) To: David Wuertele; +Cc: linux-c-programming David Wuertele wrote: > Glynn> One consequence of this difference is that Linux allows an > Glynn> executable to export symbols to a library. Thus you can create > Glynn> a library with unresolved references (i.e. symbols not provided > Glynn> by either the library or any of it's explicit dependencies). So > Glynn> long as that symbol actually gets provided at run-time (e.g. by > Glynn> the executable itself), everything works. > > Does this "flexibility" have practical applications? I have encountered uses of this in the past, but I can't recall any specifics. Ultimately, you can always achieve the same effect by having the application register callbacks with the library. > Glynn> In any case: if you need libB.so to actually run the > Glynn> executable, why does it matter if you need it in order to link > Glynn> the program? > > Encapsulation and portability. We're writing a toolkit that isolates > the programmer from the underlying implementation. Requiring the > programmer to explicitly link to the underlying library requires that > the programmer know what that underlying library is. Also, it > prevents us from changing the underlying library. These goals don't > seem that unreasonable to us, and they are very important for our > application. The programmer doesn't *explicitly* link to the library; an application will typically only link against the "topmost" library (libA in your example), and the resulting executable will only have a direct dependency (one which is actually stored in the executable) upon that library. In order for the link step to succeed, the library which is explicitly referenced has to exist. If that library has any dependencies, they must also exist at link time, but the information won't be encoded into the executable (ldd will show the transitive dependencies, but they aren't stored in the executable; if you hide the direct dependencies, the transitive dependencies will disappear from the ldd output). E.g. if an application links with -lgtk, libgtk must exist; if the implementation uses libX11, that must also exist, and so on. However, the executable will only contain a dependency upon libgtk, not upon libX11. You could transfer the executable to a system where the libgtk implementation uses the framebuffer API instead of X11, and it should still work. Sometimes shared libraries are built without dependency information. In that case, the executable has to explicitly link against the dependencies, otherwise you would end up with unresolved symbols at run-time. However, omitting dependency information could be considered a bug (for your purposes, it would definitely be a bug). Finally, if you want to be able to build executables which use libA, but are unable or unwilling to supply a specific libB, you could supply a "stub" library (one which provides functions which do nothing). Obviously, such a library would have no dependencies. -- Glynn Clements <glynn.clements@virgin.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-12 16:42 ` David Wuertele 2003-08-12 17:54 ` Glynn Clements @ 2003-08-12 19:12 ` Steven 1 sibling, 0 replies; 9+ messages in thread From: Steven @ 2003-08-12 19:12 UTC (permalink / raw) To: David Wuertele; +Cc: linux-c-programming [-- Attachment #1: Type: text/plain, Size: 1219 bytes --] > Glynn> One consequence of this difference is that Linux allows an > Glynn> executable to export symbols to a library. Thus you can create > Glynn> a library with unresolved references (i.e. symbols not provided > Glynn> by either the library or any of it's explicit dependencies). So > Glynn> long as that symbol actually gets provided at run-time (e.g. by > Glynn> the executable itself), everything works. > Does this "flexibility" have practical applications? If it's combined with weak symbols it's often handy. Suppose library A arranges to libA_error whenever it suffers an error, which prints an error message and terminates the program. If the libA_error is weak, then an application can define its own libA_error as a strong symbol, which will then override the weak variant and be called in preference to the library's own version. Systems with multiple, incompatible, threading libraries, such as FreeBSD, often do something similar with symbols be provided by the application's chosen threading library. This means that libA should be able to work reasonably well whether the application uses libkse or libthr, without the author of libA having to do anything special. Steven Smith, sos22@cam.ac.uk. [-- Attachment #2: Type: application/pgp-signature, Size: 187 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-11 23:50 ` Mike Castle 2003-08-12 0:10 ` David Wuertele @ 2003-08-12 0:11 ` David Wuertele 1 sibling, 0 replies; 9+ messages in thread From: David Wuertele @ 2003-08-12 0:11 UTC (permalink / raw) To: linux-c-programming Mike> Consider what would happen if everything was using static Mike> libraries instead. But they aren't. One feature of shared libraries is runtime binding. Mike> In my opinion, it should be a consistent command line between Mike> static and dynamic linking, with adding -static the only Mike> difference. That seems like an unnecessarily strict requirement to me. I don't see the benefit. Dave ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Why does linking a.so with b.so require execs to be linked both -la and -lb? 2003-08-11 21:02 Why does linking a.so with b.so require execs to be linked both -la and -lb? David Wuertele 2003-08-11 23:50 ` Mike Castle @ 2003-08-12 13:16 ` Glynn Clements 1 sibling, 0 replies; 9+ messages in thread From: Glynn Clements @ 2003-08-12 13:16 UTC (permalink / raw) To: David Wuertele; +Cc: linux-c-programming David Wuertele wrote: > # I'm creating a shared library like this: > libDaveA.so: $(LIB_OBJECTS) > $(CXX) -shared -ldl -rdynamic -o $@ $^ -lDaveB -lDaveC -lDaveD -lDaveE > > # And I have some executables that use the shared lib: > daveprog: daveprog.cpp > $(CXX) -o $@ $^ -lDaveA > > The executable doesn't use any of the functions from libDaveB.so, > libDaveC.so, libDaveD.so, or libDaveE.so. It only uses functions from > libDaveA.so. But when I compile with the above makefile, gcc > complains: > > /usr/tools/lib/gcc-lib/mipsel-linux/2.96/../../../../mipsel-linux/bin/ld: warning: libDaveB.so.0, needed by /usr/local/lib/libDaveA.so, not found (try using -rpath or -rpath-link) > > Why is that? Why should daveprog, which never uses any functionality > AT ALL from libDaveB.so, have to link to it? Because libDaveB is listed as a dependency of libDaveA. Does libDaveA really require all of those other libraries? If not, don't list them as dependencies. OTOH, if something in libDaveA requires libDaveB, anything which requires libDaveA will also require libDaveB. Dependencies apply to the library as a whole, not to individual functions. Even if the program only used functions which don't themselves require libDaveB, the linker has no way of knowing that. -- Glynn Clements <glynn.clements@virgin.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2003-08-12 19:12 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2003-08-11 21:02 Why does linking a.so with b.so require execs to be linked both -la and -lb? David Wuertele 2003-08-11 23:50 ` Mike Castle 2003-08-12 0:10 ` David Wuertele 2003-08-12 13:49 ` Glynn Clements 2003-08-12 16:42 ` David Wuertele 2003-08-12 17:54 ` Glynn Clements 2003-08-12 19:12 ` Steven 2003-08-12 0:11 ` David Wuertele 2003-08-12 13:16 ` Glynn Clements
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).