Hi all!

This is w.r.t the thread How to make my C++ program executable on other computers

I didn't want to continue the discussion there, so i created the new thread. I had faced the same problems in the past. I needed some clarification on the following:

1)The option shown in the video [http://www.youtube.com/watch?v=AvrjQtFBJvk] creates a statically linked executable. Am i right about that?

2) I had tried this approach when i had used certain external libraries.[i don't remember which one though]. I had linked my exe with the library. Everything worked fine with the default[/MDd] but i would have to ship all the necessary DLLs with it. So, i thought of creating a stand-alone exe.

However, when i had tried the approach mentioned in the video, i used to get linker errors. I never actually looked further into it. I was reminded of the problem when i saw this thread.

Now, my question is, when this option is chosen, the linker actually puts all your library code into your executable right?[thus statically linking it]

Please let me know if anyone else has actually tried shipping executables this way[as opposed to the common way of actually shipping DLLs with the program].

Thanks a lot!

PS: Sorry for such a big post :)

Recommended Answers

All 4 Replies

Statically linking the libraries into the executable is not a problem at all. However, you have to be careful about a few things.

First of all, if you have an external library that provides a DLL and an import library (.lib on Microsoft compilers, and .a on others) then you cannot use that library for statically linking to it. The "import library" is essentially a static library which acts as a thin layer of functions that perform the dynamic linking of the DLL file (when the executable starts), it basically loads / unloads the DLL and attaches the function pointers of the DLL to the functions in the executable. You cannot use that library to statically link the entire code of the DLL into your executable.

So, you first need to make sure that you have the static library that contains all the code of the DLL, i.e., a static version of the dynamic library. This static library must have been compiled from the source code of that external library, it cannot be obtained from the DLL. So, if that is not what you have, you must get it, if you can't get it, then tough luck, you have to use the DLL (and distribute it with your application).

Second, if the external library in question also has external dependencies of its own (could be system DLLs or other external library DLLs), then to perform the static linking to that external library, you also need to link to all its external dependencies. And if you want those external dependencies to be statically linked as well, then you have to do the same work on those libraries too, and so on so forth. Depending on the library in question, this process can become quite time consuming and also very difficult to maintain since it becomes your responsibility to be able to compile and link the external library correctly (as opposed to being the responsibility of the library author(s) to provide a working DLL).

Third, you must be aware that you are also paying a price for statically linking in all the external libraries. You pay a price in the size of your executable, and if you distribute multiple related applications, you'll pay a price in the overall size of the application folder.

Fourth, if the external library in question is fairly standard and stable, and that it is easily distributable (the DLLs), it would probably be better to have it installed as part of your application's installation.

As for your question:

when this option is chosen, the linker actually puts all your library code into your executable right?

Yes and no. The executable will contain all the functions from the library that are actually being called at one point or another by your executable (your code). Functions that are included in the library but that you never call will not be included in the executable. This can be an advantage if you use only a small portion of the library, since you get rid of one run-time dependency and reduce the overall size of the file(s).

commented: Thanks for the nice explanation :) +5

So, you first need to make sure that you have the static library that contains all the code of the DLL, i.e., a static version of the dynamic library. This static library must have been compiled from the source code of that external library, it cannot be obtained from the DLL. So, if that is not what you have, you must get it, if you can't get it, then tough luck, you have to use the DLL (and distribute it with your application)

Hi mike_2000_17,

Thanks a lot for your answer! Now, say my static library[say myLib] has 2 dependecies A and B. I have built the static version of myLib.

So, myLib <- A, B [as dependencies]. Compiling all these, i get a huge static library. Using this, i would be able to create a stand-alone.

So, i am clear about that part. Thanks!

First of all, if you have an external library that provides a DLL and an import library (.lib on Microsoft compilers, and .a on others) then you cannot use that library for statically linking to it

yes, that was exactly my case. I had a DLL and a small .lib[the import library]. So, why this wouldn't work is because there could be some dependecies of this DLL that's present in probably another DLL? Could you please explain a little more on this part?

Thanks!

So, why this wouldn't work is because there could be some dependecies of this DLL that's present in probably another DLL?

No. It has nothing to do with the dependencies of the DLL, it has to do with the way the DLL code is packaged and what the import library contains (or doesn't contain). Let's do a quick review of the way these things are created and packaged:

To start, you have a bunch of cpp files (source files). Each cpp file is compiled separately (called the separate compilation model) as what is called a "translation unit" to create an object file (.o or .obj depending on compiler). An object file is a piece of compiled code, separated by functions (the code for each function). Each function is given a "symbol" (the name of the function, usually with some decoration or mangling) identifying the section of code that it corresponds to. In the compiled code in the object files, every function call that appears (except those that the compiler inlined) appears not as an actual function call instruction, but rather as a reference to the symbol of the function being called. So, each object file has a list of symbols that it defines (its functions) and a list of symbols (for each function) that it needs (you can obtain that list of defined and used symbols for a given object file by asking the linker for it).

A static library, or sometimes called an "archive" (in Unix lingo), is nothing more than a collection of object files (i.e., kind of like a zip-file full of object files, but not compressed, as far as I know).

When you create an executable file, you invoke the linker and ask it to assemble a number of object files and/or static library together into a self-contained executable. At this point, the linker has to go through all the object files to create a global list of all available symbols (defined by one object file or another) along with markers to be able to find them in the object files. Then, it goes through all the references to symbols that appear in the compiled code, finds those symbols in its global symbol table, and then makes the link (replaces the symbol references by actual function calls). Usually, the linker will proceed recursively from the main() function, as to avoid resolving symbols that never get called. At the end, the linker takes all the compiled code of functions corresponding to used symbols and assembles them into one file, and makes an entry-point to call the main() function. At the end of the process, you have an executable file without any references to any of the original symbols (they have all been resolved by the linker), and which might or might not export a certain number of symbols as well (e.g., if marked __attribute(__dllexport) or similar).

When you create a DLL file, the process is almost exactly the same, in every way, as when creating an executable file. The only differences is in the entry-point and exit-point, which can be both defined for a DLL, and are both optional (they are initialization / finalization functions). Other than that and a few more things that are too complicated to explain here, a DLL is essentially the same as an executable, but without a main() function. This means that all symbols were resolved (internally) by the linker, and only some exported functions remain as exposed symbols published by the DLL. Usually, we refer to executables and DLLs by one general term which is "module" or executable module.

The moral of the story is that a DLL is completely different from a static library. A DLL is at a much later stage, it is packaged like an executable (so, think of DLLs as executables without a main() function). The linker cannot take a DLL and use it as if it was a static library. It would be a little bit like trying to edit a PDF file using Microsoft Word, you can't, even if the PDF was created from a MS word document, because it has been packaged into a PDF already.

As for the import library, it is just a static library which defines all the symbols (functions) found in the DLL, except that instead of having those symbols associated to the actual compiled code, they are associated to very small functions which simply forward the call to the DLL (and to find those DLL functions, this import library has a few bits of additional initialization code to load the DLL and fetch the function pointers for all the different functions in the DLL). In other words, there is no way for the linker to figure out that there is this connection between the DLL and the import library, because the linker only understands symbol tables and such. In some sense, the import library acts as a firewall between your code and the DLL.

So, it doesn't matter if the DLL has other dependencies or not. If the DLL and import-lib is all you have, you cannot statically link to the code within the DLL. There might be some tools or tricks to unpackage a DLL or to lump the DLL into the executable resource section, but that's a different ball-game.

Note also that in the Unix world (Unix / Linux / MacOSX / etc.), what corresponds to DLLs are "shared objects" (.so files), and they are much closer to static libraries because the packaging into .so files actually preserves enough information for the linker to be able to link directly to it, without the need for an import library, and the dynamic binding of the executable and the .so file is much stronger (shared memory, address space, exported global variables, and so on). So, most of the explanations above do not apply to the Unix world.

Now, say my static library[say myLib] has 2 dependecies A and B. I have built the static version of myLib.
So, myLib <- A, B [as dependencies]. Compiling all these, i get a huge static library. Using this, i would be able to create a stand-alone.
So, i am clear about that part. Thanks!

I think you got it right... Just to be sure: Look at it this way, every static library that was required to compile the DLL is a static library that you will need to compile your stand-alone executable. And, if any of those static libraries are import libraries linking to some other DLL, then you will need to find or compile the "real" static library with the same code as that other DLL. And then, you'll need every single static library that was needed to compile that other DLL in order to compile your stand-alone executable. And so it goes until you have no more dependencies to resolve (or, the only dependencies left are system libraries or DLLs). Most open-source libraries will have a list of external dependencies somewhere in one of the instruction files in the source-code directory (usually in README or INSTALL or BUILD or HOW_TO_BUILD, these are the conventional names).

This is also one of the advantages of DLLs, they act as insulators for external dependencies. You can have a very complicated library with lots of external dependencies, but if you compile that library into a DLL, all your executable needs to link to is that DLL (via its import library). This simplifies to coding and linking, but of course, you still need to deploy your application along with all its external dependencies (DLLs). Choosing between dynamic and static linking is not a clear-cut issue, there are advantages to both, and that is why many popular libraries offer both options (e.g., GCC standard libraries, Microsoft's C run-time libraries, Boost libraries, etc.).

commented: Thanks! +0

Thanks a lot mike_2000_17. Excellent explanation :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.