My understanding is that all linkers do this since the advent of the compilation+linking programming model. That is the purpose of linking: it looks at missing undefined references to symbols in one object file/library, then satisfies those references by adding in the symbols from another object file/library. If there is some code in the library that the main code did not reference, then there is nothing to bind those functions to, so they naturally don't get bound in to anything as a result and get left out.
Maybe there were some really simple linkers that did add everything in a library to the other library. However this would not be much of a simplification: the linker will still need to walk through all the undefined references to symbols in the main program to perform the call site binding of those undefined symbol references to the actual linked in symbols, so it is not as if the linker could somehow skip needing to look into that. So the linker will always end up forming a knowledge of what were the symbols that ended up being needed in a library.
In most compilers there is a way to perform a full library concatenation (sometimes called a "concatenating link" or an "assembling link"). This is generally not a linking process, but a process where all symbols in a library are appended to another library without resolving any symbol references. Library archiving using ar or ranlib conceptually is a process like that, and so is using clang when assembling LLVM .bc bitcode files together. Those procedures are not to be called proper "linking" though. Sometimes people prefer this kind of "linking" process as a simpler way to resolve circular library references, which would otherwise require linking in a library more than once, or using link groups. (
https://stackoverflow.com/questions...tart-group-and-end-group-command-line-options )
If you are seeing a library concatenation taking place, rather than a link, then maybe it is possible that there exists some linker flags to specify which type of operation it is supposed to perform.
Whole Program Optimization (also Link Time Optimization, LTO, or sometimes Full Interprocedural Optimization) is completely different. It is a process where compiler optimization passes are run again after all code has been brought together by linking. Generally optimizations are run at compiling stage, so they only "see" code individually in each compilation unit (.c/.cpp file) alone. After the linker has been run and all code has been linked together, one can do another invocation of the same compiler for a second run of its optimization passes, which now will be able to operate on all code, and so do optimizations that it would not have had visibility to do otherwise, e.g. constant propagation across function callers and callees across compilation units, more aggressive inlining, or removing function formal arguments that were only ever called with a specific constant literal as input parameter. See
https://en.wikipedia.org/wiki/Interprocedural_optimization or
https://llvm.org/docs/LinkTimeOptimization.html