1

I've run into a problem that I cannot seem to find anywhere else.

I am compiling a program that Visual Studio complains about not finding the corresponding .pdb file:

foo.lib(func.obj) : Warning LNK4099: PDB 'foo.pdb' was not found with 'foo.lib(func.obj)' or at '<Source_DIR>\build\Debug\foo.pdb'; linking object as if no debug info.

So I found a helpful link here describing that installing the .pdb files is as simple as:

install(FILES $<TARGET_PDB_FILE:foo> DESTINATION ${CMAKE_INSTALL_BINDIR}/$<CONFIG> OPTIONAL)

So in my foo lib I have my CMakeLists.txt file set up as such:

cmake_minimum_required(VERSION 3.18)
project(foo)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

set(version 1)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_library(foo SHARED foo.hpp foo.cpp)

set_target_properties(foo PROPERTIES DEBUG_POSTFIX "d")

target_include_directories(foo
  PUBLIC 
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
  "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)

add_library(foo::foo ALIAS foo)

install(TARGETS foo
    EXPORT fooTargets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/$<CONFIG> 
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/$<CONFIG>
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/$<CONFIG> 
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(FILES foo.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(FILES $<TARGET_PDB_FILE:foo> DESTINATION ${CMAKE_INSTALL_BINDIR}/$<CONFIG> 
OPTIONAL)


install(EXPORT fooTargets
    FILE footargets.cmake
    NAMESPACE foo::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake
)

# generate the version file for the config file
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/fooConfigVersion.cmake"
  VERSION "${version}"
  COMPATIBILITY AnyNewerVersion
)

# create config file
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
  "${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmake"
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake
)

# install config files
install(FILES
      "${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmake"
      "${CMAKE_CURRENT_BINARY_DIR}/fooConfigVersion.cmake"
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake
)

# generate the export targets for the build tree
export(EXPORT fooTargets
   FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/footargets.cmake"
   NAMESPACE foo::
)

Which installs everything nicely into something like this:

InstallDir
-- include
-- bin
-- lib

However, when I link against foo in my CMakeLists.txt I get the warning that is provided above on how it cannot find the .pdb file. However, the .pdb file is living in the InstallDir -> bin -> food.pdb.

Is there a way to link to this using CMake? Or do I have to manually copy over the .pdb file into the Debug directory even before it exists? This is where I'm stuck and I'm not sure how to proceed. This is the current CMake file:

cmake_minimum_required(VERSION 3.18)

project(Test_foo)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(foo_DIR ${CMAKE_CURRENT_LIST_DIR}/foo/lib/cmake)

find_package(foo 1 EXACT REQUIRED)

add_executable(Test_foo main.cpp)
target_link_libraries(Test_foo PUBLIC foo::foo)
set_property(TARGET Test_foo PROPERTY NO_SYSTEM_FROM_IMPORTED 1)

This will link happily. However, when I build I get the warning as described from above. I want to be able to point it to the .pdb file that is installed. However I am not sure how to do that. Any tips?

halfer
  • 19,824
  • 17
  • 99
  • 186
Sailanarmo
  • 1,139
  • 15
  • 41
  • I think the linker expects the pdb file to be next to the `.lib`. But since foo is a shared library, the linker shouldn't care for the pdb file. What are the contents of the generated config file? – Chronial Jan 26 '23 at 23:00
  • @Chronial you are correct. Moving them to the lib folder instead of the bin folder did the trick. Thank you. If you would like credit, please create an answer and I'll mark it as correct. – Sailanarmo Jan 26 '23 at 23:05

1 Answers1

3

The linker expects the .pdb to be next to the .lib.

When you link in a static library, its debug info is merged into the thing you're building. So you should put the .pdb next to the lib so the linker can find it.

When you link in a shared library, its debug info is not touched by the linker and should be next to the .dll, where the debugger will find it when debugging. So in this case it is better to have the .pdb in your bin folder – next to the dll.

Chronial
  • 66,706
  • 14
  • 93
  • 99
  • To be honest I wasn't really sure how to replicate this. I had created three libraries. Each were created in the same way and it was only this particular library that was complaining about not having the .pdb. And I wasn't sure if that was from the shared version or the static version (Which I am linking with /MDd). The other two libraries didn't care about having their .pdb's in the source code. – Sailanarmo Jan 26 '23 at 23:11
  • Also, when I was compiling this code as static through Jenkins it threw an error when it tried to run `install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}/$ OPTIONAL)` So I assumed it was a shared library issue and not a static library issue. – Sailanarmo Jan 26 '23 at 23:14
  • 1
    I clarified the difference between shared and static libraries in my answer. – Chronial Jan 26 '23 at 23:16