CMake with clang shows undefined symbol, and with cl links correctly

Viewed 744

TLDR

Im building a static library and linking it to an executable. Im generating makefiles with cmake. When I generate the makefile for cl (The compiler from visual studio) I have no problems, but when I generate the makefile for clang I get an undefined symbol.

Versions:

  • cmake version 3.18.1

  • clang version 11.0.0

    • Target: x86_64-pc-windows-msvc
    • Thread model: posix
  • cl version 19.26.28806 for x64

Minimal Example

I have the following structure for the proyect:

Proyect Root
│   CMakeLists.txt
│   foo.cpp
│   foo.hpp
│   main.cpp
│
└───bin

And this are the contents of the files:

foo.hpp

namespace foo {
    void do_stuff(void);
}

foo.cpp

#include <foo.hpp>

namespace foo {

void do_stuff(void) {}

}

main.cpp

#include <foo.hpp>

int main(void) {
    foo::do_stuff();
    return 0;
}

And CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(CompileAndLinkLib)

include_directories(".")

file(GLOB FOO_SRC "foo.cpp")
add_library(foo STATIC ${FOO_SRC})

add_executable(main "main.cpp")
target_link_libraries(main foo)

Correct linking

First I call vcvarsall.bat. I generate a nmake file with the following command:

cmake .. -G "NMake Makefiles"

And compile with:

nmake

The project compiles and links correctly

The undefined symbol

I generate the make file with the following command:

cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++

And when I compile with make I get the following output:

Scanning dependencies of target foo
[ 25%] Building CXX object CMakeFiles/foo.dir/foo.cpp.obj
[ 50%] Linking CXX static library foo.lib
[ 50%] Built target foo
Scanning dependencies of target main
[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.obj
[100%] Linking CXX executable main.exe
lld-link: error: undefined symbol: void __cdecl foo::do_stuff(void)
>>> referenced by C:\Users\pabsa\temp\main.cpp:4
>>>               CMakeFiles/main.dir/main.cpp.obj:(main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [main.exe] Error 1
make[1]: *** [CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2

Im not sure if im doing something wrong, like if im missing something, or if this is an error with the makefile generated by cmake.

3 Answers

I just had the same problem, but with Clang 13. It could be solved with specifying clang as compiler in the CMakeLists, instead of letting CMake determine it automatically.

set(CMAKE_CXX_COMPILER "clang++")

(And yes, I read your original question correct, using this:

-DCMAKE_CXX_COMPILER=clang++

as an additional argument for cmake did not work for me as well, even if it looks like it should behave the same as setting it in CMakeLists.txt)

I tested again with:

  • clang version 12.0.0
    • Target: x86_64-pc-windows-msvc
    • Thread model: posix

And it worked corretly. Seems like it was a problem with clang 11

You're overcomplicating things imo. What about just "cmake .. -T ClangCL && cmake --build ."? Builds fine for me:

C:\Users\vital\test\_build>cmake .. -T ClangCL
-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.20348.0 to target Windows 10.0.22000.
-- The C compiler identification is Clang 14.0.5 with MSVC-like command-line
-- The CXX compiler identification is Clang 14.0.5 with MSVC-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/vital/test/_build

C:\Users\vital\test\_build>cmake --build .
MSBuild version 17.3.1+2badb37d1 for .NET Framework
  Checking Build System
  Building Custom Rule C:/Users/vital/test/CMakeLists.txt
  foo.vcxproj -> C:\Users\vital\test\_build\Debug\foo.lib
  Building Custom Rule C:/Users/vital/test/CMakeLists.txt
  main.vcxproj -> C:\Users\vital\test\_build\Debug\main.exe
  Building Custom Rule C:/Users/vital/test/CMakeLists.txt

C:\Users\vital\test\_build>
Related