It was thus said that the Great Viacheslav Usov once stated:
>
> We have an elephant in the room here, and let me just name it: Windows.
> Once somebody demonstrates similar techniques on Windows, we could talk
> about real-world portability.
Ivan Krylov ran a similar experiment on Windows, and with static linking,
each function in its own translation unit and turned into a library. Then
Ivan got the following results:
>cl /c main.c
>cl /c func1.c
>cl /c func2.c
>cl /c myfunc2.c
>lib /out:func.lib func1.obj func2.obj
>link /out:main.exe main.obj myfunc2.obj func.lib
>main.exe
main
func1
myfunc2
Which matches what I saw on Linux and Solaris in the same scenario. He
then did it with shared objects (DLLs), each function in its own translation
unit before making it into a shared library, on Windows:
>cl /c main.c
>cl /c func1.c
>cl /c func2.c
>cl /c myfunc2.c
>link /dll /out:mylib.dll func1.obj func2.obj
Creating library mylib.lib and object mylib.exp
>link /out:main.exe main.obj myfunc2.obj mylib.lib
>main
Hello from main
Hello from func1
Hello from func2
Back to func1
Back to main
Hello from myfunc2
Back to main
Which is different from what I saw on Linux and Solaris in the same
scenario:
Hello from main
Hello from func1
Hello from myfunc2
This last is certainly not the same scenario ! My scenario made it clear which version was used by testing not the two calls only from main, but also testing the second function when it is called from the 1st one.
This is exactly where you can see that simple (unlinked) libraries do not behave like prelinked libaries, and that it is the use of simple libaries which is completely inconsistant (independantly of the language you used to create them, it may be C or anothy other).
Simple libraries ARE NOT suitable and NOT compatible with the C standard. They can never be strictly portable. Shared libaries (prelinked) is necessary for portability beause this ensures a strict and stable order for resolving external dependencies. In summary don't use imple libaries at all with C! Instead use the linker and provide the **full list** of the libraries you want to link to, in which you'll specify their expected order or resolution
The basic syntax like "-lm" for invokiner the linker or the C compiler with linker capabilities is inconsistant. You can never predict which unit will be included, unless the ".a" libraries are built to ensure that they will NEVER contain any pair of units defining the same symbol (i.e. each symbol defined in the library belongs to one and only one unit of the library).
The old "ar" tool of Unix (or "tar" or "shar", which give equivalent results) is clearly buggy, it's not different from a simple ".zip" file, or from a filesystem directory containing all compiled .or units listed in an unspecified/unstable order (and not containing any additional metadata file like a "manifest" to specify the order of resolution) ! The old "*ar" tools have never been seriously designed to be suitable for programming, they were made only for backing up and transfering collections of files of any type between systems by packing them ins a single file transferable in a single session (e.g. by FTP) !
There's no such limitation and portability issue when you don't use ANY static library but only use "prelinked" shared libraries (like DLL on windows or ELF libraries on Linux.. note that executable and DLL modules on Windows, as well as on OS/2, are based on directly on the ELF format) !
Let's be serious! Prelinked library formats (or archives containing manifests) are the only suitable formats for developping in any language allowing separate compilations of units (now almost all of them); the alternative is to use unit names with their full pathname (and not just the unit name) so that you can choose between multiple possible implementations in separate modules (with distinct paths) defining the same exported symbol.