I'm on VS2022. I'm creating a little static library to handle embedded resources (so let's call it er
) in my c++ project.
This library uses zlib
(latest version, 1.3.1) to compress the files before processing it (details don't really matter here). So I built zlib and linked my er
project against zlibstaticd.lib
and zlibstatic.lib
.
The cmake file is something like:
set (EXPORT_HEADER_FILES
export/er/er.hpp
)
set (SOURCE_FILES
cpp/er.cpp
)
source_group("er/cpp" FILES ${SOURCE_FILES})
source_group("er/export" FILES ${EXPORT_HEADER_FILES})
add_library(er STATIC ${EXPORT_HEADER_FILES} ${SOURCE_FILES})
set(ZLIB_LIBS
debug ${ZLIB_LIBRARY}/zlibstaticd.lib optimized ${ZLIB_LIBRARY}/zlibstatic.lib
)
target_link_libraries(er PRIVATE ${ZLIB_LIBS})
target_include_directories(er
PRIVATE hpp ${ZLIB_INCLUDE_DIRS}
PUBLIC export
)
Everything's fine so far.
Now, the point is I want er
to be standalone, that's why zlib
is linked privately. There is no mention of zlib
in the er.hpp
file.
So now I build er
, and want to use it in my other project (lib2
let's call it).
So I add er
and link it as static lib to my project (just like I did with zlib for er
). But when I try to compile I now get linkers errors as follows:
Error LNK2019 unresolved external symbol inflate referenced in function "bool __cdecl er::decompress(...)
Error LNK2019 unresolved external symbol deflate referenced in function "bool __cdecl er::compress(...)
Error LNK2019 unresolved external symbol deflateEnd referenced in function "bool __cdecl er::compress(...)
Error LNK2019 unresolved external symbol inflateEnd referenced in function "bool __cdecl er::decompress(...)
Error LNK2019 unresolved external symbol deflateInit_ referenced in function "bool __cdecl er::compress(...)
Error LNK2019 unresolved external symbol inflateInit_ referenced in function "bool __cdecl er::decompress(...)
Now why would I get that? inflate
, deflate
, deflateEnd
, inflateEnd
,... Those are zlib
functions and as I don't want to link zlib
to lib2
.
I'm really lost here. I tried the
#define ZLIB_WINAPI
#include <zlib/zlib.h>
in the er.cpp
file like some can mentions in some answers I found on SO, but it doesn't do anything.
that's why zlib is linked privately.
As Some programmer dude commented, archive libraries are not linked in any sense of the word.
You can think of them as a shopping bag filled with object files. You want to prepare a baked potato with sour cream; you have potatoes in one shopping bag (er.lib
) and sour cream in another (zlib.lib
). When preparing the meal, you need to use both bags (at link time), i.e. link your final program with both er.lib
and zlib.lib
.
You could put all of your ingredients into a single shopping bag, and then you would only need that one shopping bag (the combined erz.lib
) at link time.
To do that, you can unpack er.lib
and zlib.lib
to extract all the .obj
files from them, and add these object files into the combined erz.lib
library.
Update:
is there an automatic way to do it? I mean like a build rule or a cmake function?
I don't know about cmake
function, but you can trivially construct a Makefile
rule for it. It turns out that (unlike UNIX ar
) LIB.EXE
can directly combine .LIB
files in a single command:
LIB.EXE /OUT:erz.lib er.lib zlib.lib