Skip to content

Instantly share code, notes, and snippets.

@tiwoc
Created June 25, 2015 11:04
Show Gist options
  • Save tiwoc/433cf884fcc3aeccbf37 to your computer and use it in GitHub Desktop.
Save tiwoc/433cf884fcc3aeccbf37 to your computer and use it in GitHub Desktop.

Linker leaving out globals from unused object files in static libs

Starting point (using a lib.cpp symbol from main.cpp)

Look at the following code in two files:

  • main.cpp

      #include <iostream>
    
      extern const char *text;
    
      int main()
      {
      	std::cout << text << std::endl;
      	return 0;
      }
    
  • lib.cpp

      #include <iostream>
    
      namespace {
      class SomeClass
      {
      public:
      	SomeClass(const char *text)
      	{
      		std::cout << text << std::endl;
      	}
      };
    
      }
    
      SomeClass anInstance("Hello, world."); 
      const char *text = "Bye, world.";
    

Direct build

g++ lib.cpp main.cpp && ./a.out

This yields

Hello, world.
Bye, world.

Building via static lib

g++ -c lib.cpp -o lib.o && ar r libfoo.a lib.o && g++ main.cpp -L. -lfoo && ./a.out

This also yields

Hello, world.
Bye, world.

Where it gets interesting (not using any lib.cpp symbols from main.cpp)

Now we modify main.cpp:

#include <iostream>

//extern const char *text;

int main()
{
	//std::cout << text << std::endl;
	return 0;
}

Notice how we removed any reference to symbols from lib.cpp.

Direct build

With an unmodified command line, this now yields

Hello, world.

Notice how the initializer of anInstance is still run.

Building via static lib

Here is where it gets interesting: The binary doesn't print anything.

Conclusion

While usually linking all object files that are given to it, the linker seems to completely discard object files from static libraries if no symbols are referenced from the outside, even if globals are concerned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment