1

I'm trying to build a CMake project with Visual Studio 2022 17.2.6 but linking fails.

The directory structure is:

root
  |- CMake_Test
  |  |- subdir
  |  |  |- test.cpp
  |  |  |- test.h
  |  |
  |  |- CMakeLists.txt
  |  |- main.cpp
  |
  |- CMakeLists.txt

root/CmakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project ("CMake_Test")

add_subdirectory ("CMake_Test")

root/CMake_Test/CMakeLists.txt:

cmake_minimum_required (VERSION 3.12)

add_executable (cmake_test)

target_compile_features(cmake_test PRIVATE cxx_std_20)

target_sources(cmake_test PRIVATE "main.cpp" "subdir/test.cpp")

main.cpp:

#include <iostream>

#include "subdir\test.h"

int main()
{
    std::cout << sub::test() << std::endl;
}

test.h:

#pragma once

namespace sub {
    constexpr int test();
}

test.cpp:

#include "test.h"

namespace sub {
    constexpr int test() {
        return 42;
    }
}

Build output:

>------ Rebuild All started: Project: CMake_Test, Configuration: x64-debug ------
  [1/1] Cleaning all built files...
  Cleaning... 0 files.
  [1/3] Building CXX object CMake_Test\CMakeFiles\cmake_test.dir\subdir\test.cpp.obj
  [2/3] Building CXX object CMake_Test\CMakeFiles\cmake_test.dir\main.cpp.obj
  [3/3] Linking CXX executable CMake_Test\cmake_test.exe
  FAILED: CMake_Test/cmake_test.exe 
  cmd.exe /C "cd . && "E:\Programme\Microsoft Visual Studio\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMake_Test\CMakeFiles\cmake_test.dir --rc="E:\Windows Kits\10\bin\10.0.19041.0\x64\rc.exe" --mt="E:\Windows Kits\10\bin\10.0.19041.0\x64\mt.exe" --manifests  -- "E:\Programme\Microsoft Visual Studio\VC\Tools\MSVC\14.32.31326\bin\Hostx64\x64\link.exe" /nologo CMake_Test\CMakeFiles\cmake_test.dir\main.cpp.obj CMake_Test\CMakeFiles\cmake_test.dir\subdir\test.cpp.obj  /out:CMake_Test\cmake_test.exe /implib:CMake_Test\cmake_test.lib /pdb:CMake_Test\cmake_test.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
  LINK Pass 1: command "E:\Programme\Microsoft Visual Studio\VC\Tools\MSVC\14.32.31326\bin\Hostx64\x64\link.exe /nologo CMake_Test\CMakeFiles\cmake_test.dir\main.cpp.obj CMake_Test\CMakeFiles\cmake_test.dir\subdir\test.cpp.obj /out:CMake_Test\cmake_test.exe /implib:CMake_Test\cmake_test.lib /pdb:CMake_Test\cmake_test.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMake_Test\CMakeFiles\cmake_test.dir/intermediate.manifest CMake_Test\CMakeFiles\cmake_test.dir/manifest.res" failed (exit code 1120) with the following output:
E:\Code\CMake_Test\out\build\x64-debug\CMake_Test\main.cpp.obj : error LNK2019: unresolved external symbol "int __cdecl sub::test(void)" (?test@sub@@YAHXZ) referenced in function main
E:\Code\CMake_Test\out\build\x64-debug\CMake_Test\CMake_Test\cmake_test.exe : fatal error LNK1120: 1 unresolved externals
  ninja: build stopped: subcommand failed.

Rebuild All failed.
mmaag
  • 1,534
  • 2
  • 18
  • 24
  • Get rid of `constexpr`. See *both* duplicate questions, in the listed order, for more information. `constexpr` implies `inline`. `inline` functions don't work this way. They won't get compiled until they're actually used. Nothing uses this `constexpr` function, and even if something did, it may still not get compiled, but inlined. – Sam Varshavchik Aug 03 '22 at 11:47
  • Getting rid of `constexpr` isn't really an option if the whole point of the function is to be usable at compile time. Also it is not true that the function isn't used, the `main` function calls it. The actual problem seems to be that `inline` (and therefore `constexpr` function definitions need to be visible by the file that is using it. Putting the definition into the header solves the problem. – mmaag Aug 03 '22 at 12:36

0 Answers0