How does VS2015 link static libraries to other libraries and executables? - c++

I'm trying to create a project, that will create an executable MyExec.exe, which will depends on another library Niftilib, which itself depends on zlib.
What I did is that I used cmake and created a superbuild, using ExternalProject_Add to download and compile zlib:
ExternalProject_Add(Zlib
SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/zlib"
BINARY_DIR "${PROJECT_BINARY_DIR}/deps/zlib-build"
INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/zlib-install"
GIT_REPOSITORY "${git_protocol}://github.com/madler/zlib.git"
GIT_TAG "50893291621658f355bc5b4d450a8d06a563053d"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DINSTALL_BIN_DIR=<INSTALL_DIR>/bin
-DINSTALL_INC_DIR=<INSTALL_DIR>/include
-DINSTALL_LIB_DIR=<INSTALL_DIR>/lib
-DINSTALL_MAN_DIR=<INSTALL_DIR>/share/man
-DINSTALL_PKGCONFIG_DIR=<INSTALL_DIR>/share/pkgconfig)
I did the same for Nifticlib:
ExternalProject_Add(Nifticlib
SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib"
BINARY_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-build"
INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-install"
GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/nifticlib.git"
GIT_TAG "9f427b39eb6a16822c6ed34454f87eb751b23220"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DZLIB_INCLUDE_DIR=${ZLIB_INC_DIR}
-DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib
DEPENDS Zlib)
Then I did the same for MyExec:
ExternalProject_Add(MyExec
SOURCE_DIR "${PROJECT_BINARY_DIR}/MyExec"
BINARY_DIR "${PROJECT_BINARY_DIR}/MyExec-build"
INSTALL_DIR "${PROJECT_BINARY_DIR}/MyExec-install"
GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/MyExec.git"
GIT_TAG "8514aacf5422f1111602e24ea73b229556293b8c"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DBOOST_INC_DIR=${Boost_INCLUDE_DIRS}
-DBOOST_LIB_DIR=${Boost_LIBRARY_DIRS}
-DZLIB_INC_DIR=${ZLIB_INC_DIR}
-DZLIB_LIB_DIR=${ZLIB_LIB_DIR}
-DNIFTI_INC_DIR=${NIFTI_INC_DIR}
-DNIFTI_LIB_DIR=${NIFTI_LIB_DIR}
DEPENDS Nifticlib)
And in my CMakeLists of MyExec project, I have this:
cmake_minimum_required(VERSION 3.6)
project(MyExec)
include_directories(${BOOST_INC_DIR} ${ZLIB_INC_DIR} ${NIFTI_INC_DIR})
link_directories(${BOOST_LIB_DIR} ${ZLIB_LIB_DIR} ${NIFTI_LIB_DIR})
add_subdirectory(DataStructure)
add_subdirectory(FileHandler)
add_subdirectory(Parser)
add_executable(${PROJECT_NAME} MyExec.cc)
target_link_libraries(${PROJECT_NAME} zlibd znz nifticdf niftiio DataStructure FileHandler Parser)
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
My goal is to be able to distribute MyExec.exe without having all the required libraries (except boost). I want nifticlib library to be embedded in my exec.
If I compile this way, it doesn't work, because it says that zlibd.dll is missing. I find out that I had to link my executable to zlibstaticd instead of zlibd.
But my question is, should I also change -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib to -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibstaticd.lib in Nifticlib project ?
Or does it only matter in the executable project ? Why does nifticlib require me to provide the path to the zlib library, if it's build as a static library and doesn't do any linking ?
Thank you.
Edit: If I dont link the zlib to my executable, I get these errors:
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzdopen referenced in function znzdopen
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzread referenced in function znzread
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzwrite referenced in function znzwrite
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputs referenced in function znzputs
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgets referenced in function znzgets
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputc referenced in function znzputc
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgetc referenced in function znzgetc
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzflush referenced in function znzflush
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzeof referenced in function znzeof
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzclose referenced in function Xznzclose
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzopen referenced in function znzopen
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzseek referenced in function znzseek
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gztell referenced in function znztell
znz is part of nifticlib. It is the part using the zlib library.
Edit 2: To make it simpler, my question is does the linking happen like Linking 1 or Linking 2 (knowing that nifticlib depends on zlib, both compiled as static libraries):
Linking 1 Linking 2
-------------- -------------- ---------------
| zlib | | zlib | | nifticlib |
-------------- -------------- ---------------
| \ /
-------------- \ /
| nifticlib | \ /
-------------- \ /
| -------------------
-------------- | MyExec.exe |
| MyExec.exe | -------------------
--------------

The usual way is that linking is only done when an executable binary is generated. This includes for example normal executables, but also dynamic libraries (.dll, .so). Linking is not done for static libraries (.lib, .a).
That means if you build a static library of "nifticlib" it does not need to be linked to "zlib".
You should definitly change the dependency from the dynamic one to the static one, because CMake carries dependencies from static libraries over to the final binary. In this case it should not matter though, because you don't specify a real CMake dependency, just some variable for the library.
Note: In Visual Studio you can pretty easily "link" static libraries into each other. What it does is just concatenation of all functions into one .lib file. CMake does not use this feature though and instead carries dependencies over like mentioned above when doing "TARGET_LINK_LIBRARIES" on a static library target.

Related

Getting error LNK2019 when adding library with cmake

I am trying to add two libraries to my project through cmake: libgit2 and git2cpp (a c++ wrapper for libgit2).
Here is my project file structure:
I am trying to add them as libraries in cmake by doing the following:
cmake_minimum_required(VERSION 3.24)
project(create_clib_plugin)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
include_directories("build/include")
add_library(libgit2 SHARED IMPORTED)
set_target_properties(libgit2 PROPERTIES
IMPORTED_LOCATION "C:/Users/minha/CLionProjects/create-clib-plugin/build/lib/libs/libgit2/git2.DLL"
IMPORTED_IMPLIB "C:/Users/minha/CLionProjects/create-clib-plugin/build/lib/libs/libgit2/git2.lib"
INTERFACE_INCLUDE_DIRECTORIES "C:/Users/minha/CLionProjects/create-clib-plugin/build/include"
)
find_library(CPPGIT2_LIBRARY git2cpp HINTS "C:/Users/minha/CLionProjects/create-clib-plugin/build/lib/git2cpp.lib" REQUIRED)
add_executable(create_clib_plugin main.cpp)
TARGET_LINK_LIBRARIES(create_clib_plugin "C:/Users/minha/CLionProjects/create-clib-plugin/build/lib/libs/libgit2/git2.lib")
TARGET_LINK_LIBRARIES(create_clib_plugin "C:/Users/minha/CLionProjects/create-clib-plugin/build/lib/git2cpp.lib")
And finally, my main.cpp
#include "git2cpp/initializer.h"
int main(int argc, char *argv[]) {
auto_git_initializer;
return 0;
}
I'm getting the following errors:
main.obj : error LNK2019: unresolved external symbol "public: __cdecl git::Initializer::Initializer(void)" (??0Initializer#git##QEAA#XZ) referenced in function main [C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\create_clib_plugin.vcxproj]
main.obj : error LNK2019: unresolved external symbol "public: __cdecl git::Initializer::~Initializer(void)" (??1Initializer#git##QEAA#XZ) referenced in function main [C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\create_clib_plugin.vcxproj]
C:\Users\minha\CLionProjects\create-clib-plugin\build\lib\libs\libgit2\git2.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64' [C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\create_clib_plugin.vcxproj]
C:\Users\minha\CLionProjects\create-clib-plugin\build\lib\git2cpp.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64' [C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\create_clib_plugin.vcxproj]
C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\Release\create_clib_plugin.exe : fatal error LNK1120: 2 unresolved externals [C:\Users\minha\CLionProjects\create-clib-plugin\cmake-build-release\create_clib_plugin.vcxproj]
Does anyone have any insight on what could be causing this?

Using CMake with CPP and ASM on Windows template doesn't work

https://github.com/Ybalrid/cmake-cpp-nasm this project doesn't compile with errors:
[build] cpp.obj : error LNK2019: unresolved external symbol _asm_foo referenced in function _main [C:\Users\[username]\Downloads\cmake-cpp-nasm-master\build\cmake-cpp-nasm.vcxproj] [build] Hint on symbols that are defined and could potentially match: [build] asm_foo
How do I get rid of these errors?
Ok, I managed to fix this by adding a space:
Old:
if(WIN32)
string(APPEND CMAKE_ASM_NASM_FLAGS "-dWIN32=1")
endif(WIN32)
New:
if(WIN32)
string(APPEND CMAKE_ASM_NASM_FLAGS " -dWIN32=1")
endif(WIN32)

wxWidgets not linking using Cmake from VSCode (MSVC)

Problem
I am getting linker errors when building my project. The project has no trouble finding wxWidgets headers. I have looked at the wxWidgets minimal example and recreated it in order to verify that my build from source worked properly. I used cmake in VSCode to do the build using the cmake extension.
The wxWidgets cmake generated fine and the build of wxwidgets appears to have gone fine. I am using the Visual Studio 2022 amd64 toolset to do the compile. (I installed VS2022 Community Edition for the compiler only).
It looks like it is building DLL for the libraries. I would prefer static libraries but for an initial run I didnt think it mattered. I link my application to wx::net wx::core wx::base as recommended. I thought that this would take care of linking when I go to build.
When I go to build my overall application utilizing the wxWidgets library, I get these linker errors.
What am I doing wrong here? Im obviously not configuring something correctly for it to find the library, but I am kind of stumped here.
Linker Errors
[build] ProjectName.obj : error LNK2001: unresolved external symbol "protected: static class wxAppConsole * (__cdecl* wxAppConsoleBase::ms_appInitFn)(void)" -snipped-
[build] ProjectName.obj : error LNK2001: unresolved external symbol "protected: static class wxAppConsole * wxAppConsoleBase::ms_appInstance" -snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "void (__cdecl* wxTheAssertHandler)(class wxString const &,int,class wxString const &,class wxString const &,class wxString const &)"-snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "bool wxTrapInAssert" (?wxTrapInAssert##3_NA) -snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "class wxMBConv * wxConvLibcPtr" (?wxConvLibcPtr##3PEAVwxMBConv##EA) -snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "public: static unsigned __int64 const wxString::npos" (?npos#wxString##2_KB)-snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "class wxSize const wxDefaultSize" (?wxDefaultSize##3VwxSize##B)-snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "class wxPoint const wxDefaultPosition" (?wxDefaultPosition##3VwxPoint##B)-snipped-
[build] MainWindow.obj : error LNK2001: unresolved external symbol "char const * const wxFrameNameStr" (?wxFrameNameStr##3QBDB)-snipped-
[build] C:\path\to\executable\ProjectName.exe : fatal error LNK1120: 9 unresolved externals -snipped-
[build] Build finished with exit code 1
Project Layout
Pretty basic project layout. I am building a GUI application and I am logically separating out the ui source code.
This is basically a recreation of the minimal wxWidgets example where you have an entry point (Projectname.hpp and ProjectName.cpp provide this) and a main window/frame (MainWindow.hpp and MainWindow.cpp provide this). The ProjectName application will do the wxIMPLEMENT_APP(ProjectName) and will hold a pointer to a MainWindow. The MainWindow is shown using the OnInit Function.
ProjectName/
build/
external/
wxWidgets-3.1.6/
-CMakeLists.txt
source/
ui/
-MainWindow.hpp
-MainWindow.cpp
-ProjectName.hpp
-ProjectName.cpp
-CMakeLists.txt
I have compiled the wxWidgets library using their cmake instructions for using a subdirectory in cmake so I could add it to my project. Here are the contents of the CMakeLists.txt's
ProjectName CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
set(MAJOR 0)
set(MINOR 0)
set(PATCH 1)
#Setup Project
project(ProjectNameProject VERSION ${MAJOR}.${MINOR}.${PATCH}
DESCRIPTION "ProjectName Descrip"
LANGUAGES CXX)
add_executable(ProjectName WIN32 ${PROJECT_SOURCE_DIR}/source/ProjectName.cpp
${PROJECT_SOURCE_DIR}/source/ui/MainWindow.cpp)
target_include_directories(ProjectName PRIVATE ${PROJECT_SOURCE_DIR}/source)
target_include_directories(ProjectName PRIVATE ${PROJECT_SOURCE_DIR}/source/ui)
target_link_libraries(ProjectName PRIVATE wx::net wx::core wx::base)
add_subdirectory(${CMAKE_SOURCE_DIR}/external)
ProjectName/externals CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
add_subdirectory(${CMAKE_SOURCE_DIR}/external/wxWidgets-3.1.6)
Update
I changed the Cmake option for building a shared library (DLL) and set it to OFF. When this is done, it builds a static library (LIB). This seemed to fix my linking issues.
Per Igor's suggestion, I took another look at the minimal sample CMakeLists.txt and noticed they used the following line for linking
target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES})
Perhaps my line (below) is the way to link statically and does not work with DLLs?
target_link_libraries(ProjectName PRIVATE wx::net wx::core wx::base)
If someone could help me understand why having it build statically fixed it, I would 100% accept that answer.
I changed the Cmake option for building a shared library (DLL) and set it to OFF. When this is done, it builds a static library (LIB). This seemed to fix my linking issues.
Unfortunately I do no see anyone able to chime in to help understand why this is the solution, but I am going to select this as an answer for others coming to this in the future.
If I see any updates that answer the question of "why" I will accept their answer.

Building GStreamer with CMake causes SDP & WebRTC unresolved external symbol errors

I'm building a C++ GStreamer project with CMake which depends on GStreamer, GLIB, Libsoup and json-glib. I'm new to CMake and having trouble setting up my project. I've managed to include many of the dependencies but some seem to remain unresolved even though they are part of GStreamer. All GStreamer methods and types are resolved with the exception of SDP and WebRTC. They are, to my understanding, part of GStreamer and are also located inside of the directory which GMake correctly "finds".
These are the errors that are occurring when trying to build the project.
[build] error LNK2019: unresolved external symbol __imp_gst_sdp_message_new referenced in function "void __cdecl soup_websocket_message_cb(struct _SoupWebsocketConnection *,enum SoupWebsocketDataType,struct _GBytes *,void *)" (?soup_websocket_message_cb##YAXPEAU_SoupWebsocketConnection##W4SoupWebsocketDataType##PEAU_GBytes##PEAX#Z)
[build] error LNK2019: unresolved external symbol __imp_gst_sdp_message_parse_buffer referenced in function "void __cdecl soup_websocket_message_cb(struct _SoupWebsocketConnection *,enum SoupWebsocketDataType,struct _GBytes *,void *)" (?soup_websocket_message_cb##YAXPEAU_SoupWebsocketConnection##W4SoupWebsocketDataType##PEAU_GBytes##PEAX#Z)
[build] error LNK2019: unresolved external symbol __imp_gst_sdp_message_as_text referenced in function "void __cdecl on_offer_created_cb(struct _GstPromise *,void *)" (?on_offer_created_cb##YAXPEAU_GstPromise##PEAX#Z)
[build] error LNK2019: unresolved external symbol __imp_gst_webrtc_session_description_get_type referenced in function "void __cdecl on_offer_created_cb(struct _GstPromise *,void *)" (?on_offer_created_cb##YAXPEAU_GstPromise##PEAX#Z)
[build] error LNK2019: unresolved external symbol __imp_gst_webrtc_session_description_new referenced in function "void __cdecl soup_websocket_message_cb(struct _SoupWebsocketConnection *,enum SoupWebsocketDataType,struct _GBytes *,void *)" (?soup_websocket_message_cb##YAXPEAU_SoupWebsocketConnection##W4SoupWebsocketDataType##PEAU_GBytes##PEAX#Z)
[build] error LNK2019: unresolved external symbol __imp_gst_webrtc_session_description_free referenced in function "void __cdecl on_offer_created_cb(struct _GstPromise *,void *)" (?on_offer_created_cb##YAXPEAU_GstPromise##PEAX#Z)
This is my CMakeLists.txt
# CMakeList.txt : CMake project for stream-project, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
project (stream-project LANGUAGES CXX)
# Packages
find_package(PkgConfig REQUIRED)
# Add source to this project's executable.
add_executable (${PROJECT_NAME} "main.cpp" "main.h")
# Search all modules that we so desire to use and "include_directories"
pkg_search_module(GST REQUIRED gstreamer-1.0 gstreamer-sdp-1.0 gstreamer-video-1.0 gstreamer-app-1.0 gstreamer-webrtc-1.0)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_search_module(LIBSOUP REQUIRED libsoup-2.4)
pkg_search_module(JSONGLIB REQUIRED json-glib-1.0)
include_directories(
${GST_INCLUDE_DIRS}
${GLIB_INCLUDE_DIRS}
${LIBSOUP_INCLUDE_DIRS}
${JSONGLIB_INCLUDE_DIRS}
)
# Link target directories and libraries
target_link_directories(${PROJECT_NAME} PRIVATE
${GST_LIBRARY_DIRS}
${GLIB_LIBRARY_DIRS}
${LIBSOUP_LIBRARY_DIRS}
${JSONGLIB_LIBRARY_DIRS}
)
target_link_libraries(${PROJECT_NAME} PRIVATE
${GST_LIBRARIES}
${GLIB_LIBRARIES}
${LIBSOUP_LIBRARIES}
${JSONGLIB_LIBRARIES}
)
message(STATUS ${GST_INCLUDE_DIRS})
I've managed to solve it by using a premade find script I found online.
https://chromium.googlesource.com/external/Webkit/+/master/Source/cmake/FindGStreamer.cmake
It creates all necessary defines which I then include and link.
These are the defaults as specified in the FindGStreamer.cmake file
FIND_GSTREAMER_COMPONENT(GSTREAMER_APP gstreamer-app-1.0 gst/app/gstappsink.h gstapp-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_AUDIO gstreamer-audio-1.0 gst/audio/audio.h gstaudio-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_FFT gstreamer-fft-1.0 gst/fft/gstfft.h gstfft-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_PBUTILS gstreamer-pbutils-1.0 gst/pbutils/pbutils.h gstpbutils-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_VIDEO gstreamer-video-1.0 gst/video/video.h gstvideo-1.0)
I extended those above with:
FIND_GSTREAMER_COMPONENT(GSTREAMER_SDP gstreamer-sdp-1.0 gst/sdp/sdp.h gstsdp-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_WEBRTC gstreamer-webrtc-1.0 gst/webrtc/webrtc.h gstwebrtc-1.0)

Use win32 libs in cmake project [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Error LNK2019 unresolved external symbol _WinMain#16 referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ)
(4 answers)
Linker error: unresolved external symbol _WinMain#16 when building console application [duplicate]
(1 answer)
Closed 1 year ago.
I'm trying to build a cmake project that uses WinHTTP. Below is my cmakelists.txt file
cmake_minimum_required(VERSION 3.19)
project(Mandarin_EXE_Updator)
set(SOURCE_FILES main.cpp)
set(WIN32 True)
OPTION(WINHTTP ON)
add_executable(Mandarin_Updator WIN32 ${SOURCE_FILES})
target_link_libraries(winhttp)
I've tried doing link_libraries and target_link_libraries but with no luck. I think i need to use link_libraries, but with the full path to the lib file.
below is the output of cmake --build .
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)
" (?invoke_main##YAHXZ) [C:\Users\srika\OneDrive\Desktop\Mandarin.EXE\Mandarin Updater\build\Mandarin_Updator.vcxproj]
C:\Users\srika\OneDrive\Desktop\Mandarin.EXE\Mandarin Updater\build\Debug\Mandarin_Updator.exe : fatal error LNK1120: 1 unresolved ext
ernals [C:\Users\srika\OneDrive\Desktop\Mandarin.EXE\Mandarin Updater\build\Mandarin_Updator.vcxproj]