erb nobbles
erb nobbles

Reputation: 11

Unresolved external symbol when linking shared library CMake and C++

I'm trying to link a new C++ project to a C library using CMake. The library is located here and when cloning and compiling the library in standalone, I can run the tests, etc. However, when I add it as a git submodule to my C++ project, and try to link it to my main.cpp file I get many linker errors for each called function:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2019 unresolved external symbol "__declspec(dllimport) void __cdecl wimp_instr_queue_high_prio_lock(struct _WimpInstrQueue *)" (__imp_?wimp_instr_queue_high_prio_lock@@YAXPEAU_WimpInstrQueue@@@Z) referenced in function main  magnum-wimp main.obj

The .dll is being generated and placed in the binary directory, and the .lib to link the symbols is being generated and placed in the lib directory. The C++ project is structured with a dependencies folder and a src folder, with two main CMakeLists.txt files:

CMakeLists.txt in the root directory

cmake_minimum_required(VERSION 3.5)
project(magnum-wimp CXX)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE})

add_subdirectory(dependencies)
add_subdirectory(magnum-wimp)

set_target_properties(wimp PROPERTIES FOLDER Dependencies)
set_target_properties(wimp
    PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}"
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}"
)

CMakeLists.txt in the magnum-wimp/src directory:

cmake_minimum_required(VERSION 3.5)
project(magnum-wimp)

add_executable(${PROJECT_NAME} main.cpp)

# Include the directory containing the wimp library headers
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/dependencies/wimp/wimp/src)

# Add the directory containing the wimp library
target_link_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})

# Link against the wimp shared library
target_link_libraries(${PROJECT_NAME} PRIVATE wimp)

I used a similar CMakeLists.txt file for the src folder as the library has in the tests folders, so I'm unsure why the library appears to be unable to link to the program - when loading the visual studio solution it seems to be pointing to the .lib file at least. When running the tests in the library repo, it compiles and links to the .lib files and uses the .dll file without any problems which is what I would have expected.

Upvotes: 0

Views: 181

Answers (1)

erb nobbles
erb nobbles

Reputation: 11

The issue was that the C header files were't wrapped in an extern "C" block. This is why the code linked correctly for tests, or for other C projects but failed in C++ as it uses a different linkage system.

An example of how to fix it would be as follows:

extern "C"
{
    #include <header1.h>
    #include <header2.h>
    ...
}

One way of making this cleaner could be to place the headers in a combined header file to avoid having to include the block each time for each include. A preprocessor check could also be used to only wrap the block if the code is compiled as C++:

#ifdef __cplusplus
extern "C" {
#endif

#include <header1.h>
#include <header2.h>
...

#ifdef __cplusplus
}
#endif

Upvotes: 0

Related Questions