0

I asked an online LLM and it said:

Yes, absolutely. You need to link to the dependency library even when building a static library that calls functions within it.

But I tried building a static library that calls another function, and all I did was include the header, and then call the function. It built on Linux with GCC, without any complaints about undefined reference or anything.

Let's say:

MyStaticLibrary:

#include "MyExternalFunction.h"

void my_static_library_function()
{
     MyExternalFunction();
}

The above compiled fine with no complaints from compiler.

Then I create an executable, main:

void my_static_library_function();

int main()
{
    my_static_library_function();
    return 0;
}

I linked main executable to my static library (obviously, because I call it's function) and THEN it complains that MyExternalFunction isn't defined, and so the EXECUTABLE has to link that function. But not the static library. And so therefore the static library doesn't have to link functions it calls. What about other symbols like variables? It's same? A static library never NEEDS to link anything, it only needs declarations?

What brought me to ask this is that I'm building a static library (libcurl) and I'm wondering whether that library only needs the include directory to MBedTLS (the ssl library backend) in order to compile.

15
  • 2
    A static library does not pass the link stage (it's more or less a package of compiled object files). But the "missing" function's body/implementation should be linked later on for creating e.g. an executable. Commented Apr 11 at 9:15
  • @wohlstad So in other words libcurl should compile as a static library with only the include directory defined, it doesn't need to have MBedTLS linked. Right? If there's really no distinction between a static library and an obj file, I mean, I think I know that when a translation unit is compiled to an obj file it's ok to have externally defined symbols. Commented Apr 11 at 9:22
  • AFAIK Yes, this is correct (I'm sure at least in Windows env, I am less familiar with e.g. Linux but I assume it is similar). But anyway MBedTLS must be available for the client that will use your library eventually (to link an executable etc.). However - If you are using Linux you might wait for a more confident response from a Linux person. Commented Apr 11 at 9:24
  • 1
    "I asked an online LLM and it said:" And that was your first mistake. Did you even ATTEMPT at solving the problem? Cause all you have shown is that you want others to solve the problem for you. That is not what stackoverflow is for. Commented Apr 11 at 10:44
  • 1
    @Zebrafish What do you mean? It has nothing to do with the compiler, but everything to do with the linker. You are not making any sense. Commented Apr 11 at 16:50

1 Answer 1

4

The answer you got is broadly correct, but "building" is a vague term that doesn't capture that there are different steps to it.

A static library is just an indexed collection of object files. An object file is produced in the compilation step (I use it in the more strict sense here, not as a synonym to whole build though it's sometimes used this way). It's a dependency for further development, a limited collection of some definitions to link with.

You don't link a static library, it's produced just by making an archive. The linking step takes shared libraries, static libraries, object files, and sometimes specific stuff like linker scripts that you don't need to worry about here. It then produces an executable or shared library, which is a "final product" that'll be installed and used by the OS.

When the OS loads a shared library, it'll find references to some symbols inside and it needs to associate them with actual addresses in memory. A symbol can be either in that shared library itself, or already loaded from somewhere beforehand. That somewhere is usually one of its shared library dependencies (you can see them with readelf -d on Linux) but you can also preload some shared libraries, which your shared library won't know anything about - this requires additional effort on your side as a user of that final product.

There's also dynamic linking where you put in your code that at some point during run time, you're going to load a library and pick out some symbols from it to use. The whole procedure described above is still performed, but you can delay it, even perform it lazily only for the symbols you actually use.

The point is that everything needs to be defined when it's going to be used, but you have a lot of flexibility in "promising you'll make sure to provide the required definitions".

For the object file (and therefore static library), you only need to specify what will come in from outside. Those are extern declarations. Function declarations are extern by default, that's why all you need is to include a header file with int f(int x); and it'll compile, but the symbol for this function will be undefined.

In order to link successfully, it's recommended to provide the definition of f in one of the shared/static libraries given to the linker. However, if you know what you're doing, you can tell the linker to ignore undefined symbols and everything will be fine... until you need to run it.

Only at that point, when loading your library (let's ignore dynamic linking), you need to make sure that the symbol for f was defined somewhere - either among the shared library dependencies that get found by the loader functionality of your OS (note: not simply the ones used during the linking step!) or in a library you explicitly provided to your process.

TL;DR for basic, nice software development: you need the declaration to compile and the definition to link.

Sign up to request clarification or add additional context in comments.

2 Comments

Umm OK. I think it's simplest to just think of a static library as an object file. Someone mentioned they're basically the same thing. And so the answer is no, I don't need to link anything when building a static library. I'm wondering why you were cautious enough to say "The answer you got is broadly correct,". Isn't is the case when building a static library you don't need to link AT ALL, because it's treated like an obj file, and compiling to obj files never needs linking.
Yes, building a static library has no link step. It's just used during it. I can add that there's stuff like CMake's target_link_libraries where you can specify static ones too, but "link static to static" will just create a dependency within the build system - it's so that you can specify abstract library dependencies without worrying about what kind of libraries they are. In that case, "link to" has a different meaning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.