Linking a prebuilt static library

I am trying to link a static library to my main executable but I keep receiving the following error:

main.obj : error LNK2019: unresolved external symbol “void __cdecl HelloWorld(void)” (?HelloWorld@@
YAXXZ) referenced in function main [C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-librar
ies\build\Main.vcxproj]
C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-libraries\build\Debug\Main.exe : fatal err
or LNK1120: 1 unresolved externals [C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-librar
ies\build\Main.vcxproj]

Here is the configuration details:

– Building for: Visual Studio 16 2019
– Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19045.
– The CXX compiler identification is MSVC 19.29.30147.0
– Detecting CXX compiler ABI info
– Detecting CXX compiler ABI info - done
– Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/
Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
– Detecting CXX compile features
– Detecting CXX compile features - done
– Configuring done
– Generating done
– Build files have been written to: C:/Users/Shack/Desktop/Git/Projects/C_C++/Linking-static-librar
ies/build

I am building on windows 10 with a cmake version of 3.25.0. The project has cmake build the main project and make build the static library.
My code is as follows:

--------->Cmake project:

CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)
project (“Linking-static-libraries” LANGUAGES CXX)
add_executable (Main main.cpp)
target_link_libraries (Main C:/Users/Shack/Desktop/Git/Projects/C_C++/Linking-static-libraries-StaticHello.lib)
target_include_directories (Main PUBLIC C:/Users/Shack/Desktop/Git/Projects/C_C++/Linking-static-libraries)

main.cpp:

#include <iostream>
#include “Hello.h”

using namespace std;

int main()
{
HelloWorld();
return 0;
}

--------->Makefile Project:

Makefile:

rebuild: clean all

all: Hello

Hello: Hello.cpp Hello.h
g++ -c Hello.cpp
ar rcs StaticHello.lib Hello.o

clean:
rm StaticHello.lib
rm Hello.o

Hello.h:

void HelloWorld();

Hello.cpp:

#include <iostream>
#include “Hello.h”

using namespace std;

void HelloWorld()
{
cout << “Hello World!!!” << endl;
}

All files are in the same directory. With “make all”, and then “cmake -S . -B build” and then of course “cmake --build build”, The errors mentioned above are produced. Any ideas on the cause? and perhaps a solution? Thanks.

It may be because you’re using two different compilers, and they may have different rules for name mangling.

You either should use the same compiler for both parts, or export a C interface, which does not suffer from C++ mangling issues.

Thank you for taking the time to have a look at this!

Based on what you have said, I thought to perhaps add an extern “C” to the declaration in the header. I tried that and now get the following:

StaticHello.lib(Hello.o) : error LNK2019: unresolved external symbol ZStlsISt11char_traitsIcEERSt1
3basic_ostreamIcT_ES5_PKc referenced in function HelloWorld [C:\Users\Shack\Desktop\Git\Projects\C

C++\Linking-static-libraries\build\Main.vcxproj]
StaticHello.lib(Hello.o) : error LNK2019: unresolved external symbol _ZNSolsEPFRSoS_E referenced in
function HelloWorld [C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-libraries\build\Main
.vcxproj]
StaticHello.lib(Hello.o) : error LNK2001: unresolved external symbol ZSt4endlIcSt11char_traitsIcEE
RSt13basic_ostreamIT_T0_ES6
[C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-libraries\bu
ild\Main.vcxproj]
StaticHello.lib(Hello.o) : error LNK2001: unresolved external symbol _ZSt4cout [C:\Users\Shack\Desk
top\Git\Projects\C_C++\Linking-static-libraries\build\Main.vcxproj]
C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-libraries\build\Debug\Main.exe : fatal err
or LNK1120: 4 unresolved externals [C:\Users\Shack\Desktop\Git\Projects\C_C++\Linking-static-librar
ies\build\Main.vcxproj]

Hello.h: edited

extern “C” {
void HelloWorld();
}

This is the same problem, but more convoluted.
Your static library make calls into the the C++ standard library. When building the library, the toolchain finds the appropriate symbols in the standard library provided by the compiler (libstdc++ for GCC).
However, when your main executable, the msvc toolchain brings its own standard library implementation, with differently named and differently mangled symbols.

It seems basically impossible (at least not without a lot of hacks) to use static libraries between different toolchains. Especially, when msvc is involved.

1 Like

I have a compiler installed through msys that I use. Is there a simple way to switch from msvc to it and have cmake use it? Or perhaps just a resource to start.

Cmake detected MSVC 19 as your default C++ compiler. You can tell cmake to use a different C++ compiler by setting the CMAKE_CXX_COMPILER value to a different compiler, see CMAKE_CXX_COMPILER
There are three common ways to achieve this, either set the CXX environment variable before calling cmake, create a toolchain file containing CMAKE_CXX_COMPILER and pass it with -DCMAKE_TOOLCHAIN_FILE=path/to/file or simply pass -DCMAKE_CXX_COMPILER=path/to/compiler to your initial cmake call.

Take note that each of these approaches requires you to delete your current cmake cache beforehand