Search code examples
c++cmakestatic-librariesassimp

Why does CMake fail to link my static library?


I am trying to link a static library which I have compiled from the assimp source to my executable CMake project so that it does not have to compile assimp as often since it's such a large library.

I compiled it using CMake with the following commands:

git clone https://github.com/assimp/assimp/
cd assimp
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF ../CMakeLists.txt
cmake --build .

My project structure looks like this:

.
OpenGL
├── OpenGL
│   ├── res
│   ├── src
│   |   └── (my .cpp and .h files)
│   └── CMakeLists.txt
├── libraries
│       └── glfw, glew, imgui...
└── CMakeLists.txt

I now copy assimp/include and assimp/build/bin/Debug/config.h to OpenGL/libraries/assimp/include,

then assimp/build/lib/Debug to OpenGL/libraries/assimp/lib

My CMakeLists.txt(s) look like this:

cmake_minimum_required(VERSION 3.8)

project(OpenGL LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_FIND_DEBUG_MODE)

if (NOT MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
endif()

if (CMAKE_BUILD_TYPE STREQUAL Debug)
    add_definitions(-DDEBUG) # preprocessor macro
else()
    if (MSVC)
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") # if running on release mode remove the cmd prompt on windows
    endif()
endif()

add_subdirectory(OpenGL)
add_subdirectory(libraries/glfw)
add_subdirectory(libraries/glew)
add_subdirectory(libraries/nativefiledialog)

target_include_directories(${PROJECT_NAME} PRIVATE 
    ${CMAKE_CURRENT_SOURCE_DIR}/libraries/glfw/include
    ${CMAKE_CURRENT_SOURCE_DIR}/libraries/glew/include
    OpenGL/src
    libraries
    libraries/stb
    libraries/assimp/include
    libraries/nativefiledialog/src/include
)

and

cmake_minimum_required(VERSION 3.8)

file(GLOB_RECURSE OpenGL_sources *.cpp ../libraries/imgui/*.cpp ../libraries/stb/*.cpp)

add_executable(${PROJECT_NAME} ${OpenGL_sources} "src/engine/input/Key.cpp" "src/engine/input/Buttons.h" "src/engine/input/Button.h" "src/engine/input/Button.cpp" "src/engine/input/MouseButton.h" "src/engine/input/MouseButton.cpp" "src/engine/rendering/objects/Model.h" "src/engine/rendering/objects/Model.cpp")

target_link_libraries(${PROJECT_NAME} PUBLIC
    glfw
    libglew_static
    ${CMAKE_SOURCE_DIR}/libraries/assimp/lib/assimp-vc143-mtd.lib
    nativefiledialog
)

or

cmake_minimum_required(VERSION 3.8)

add_library( assimp STATIC IMPORTED )
set_property( TARGET assimp PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libraries/assimp/lib/assimp-vc143-mtd.lib)

file(GLOB_RECURSE OpenGL_sources *.cpp ../libraries/imgui/*.cpp ../libraries/stb/*.cpp)

add_executable(${PROJECT_NAME} ${OpenGL_sources} "src/engine/input/Key.cpp" "src/engine/input/Buttons.h" "src/engine/input/Button.h" "src/engine/input/Button.cpp" "src/engine/input/MouseButton.h" "src/engine/input/MouseButton.cpp" "src/engine/rendering/objects/Model.h" "src/engine/rendering/objects/Model.cpp")

target_link_libraries(${PROJECT_NAME} PUBLIC
    glfw
    libglew_static
    assimp
    nativefiledialog
)

(Both configurations give the same error)


Running cmake .. from OpenGL/build successfully completes which I think means that CMake was able to find the assimp library.

Now when I run cmake --build . I am greeted with the following error.

assimp-vc143-mtd.lib(AssbinLoader.obj) : error LNK2019: unresolved external symbol uncompress referenced in function "public: virtual void __cdecl Assimp::AssbinImporter::InternReadFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,struct aiScene *,class Assimp::IOSystem *)" (?InternReadFile@AssbinImporter@Assimp@@UEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAUaiScene@@PEAVIOSystem@2@@Z) [F:\dev\cpp\OpenGL\build\OpenGL\OpenGL.vcxproj]
assimp-vc143-mtd.lib(Compression.obj) : error LNK2019: unresolved external symbol inflate referenced in function "public: unsigned __int64 __cdecl Assimp::Compression::decompress(void const *,unsigned __int64,class std::vector<char,class std::allocator<char> > &)" (?decompress@Compression@Assimp@@QEAA_KPEBX_KAEAV?$vector@DV?$allocator@D@std@@@std@@@Z) [F:\dev\cpp\OpenGL\build\OpenGL\OpenGL.vcxproj]
etc...

I believe this means that the function bodies were not found which should be compiled within the .lib.

How do I successfully link the library?


Solution

  • These functions (uncompress and inflate) belong to the ZLIB library. Although assimp CMake links ZLIB in order to use it - which is enough to build assimp by itself, you have to link ZLIB directly to your executable as well in order to use it in your executable context.