PDB files with CMake install - c++

I am using a CMake command to install PDB files to enable debugging in a developer distribution of my C++ application. The command is as below:
INSTALL(DIRECTORY ${PROJECT_BINARY_DIR}/Debug
DESTINATION bin
FILES_MATCHING
PATTERN *.pdb
)
Also, I've managed to install the relevant source used to build that developer distribution, in a 'src' folder at the same level, so that my top level distribution folder looks as:
include\
src\
lib\
bin\
share\
doc\
3rdparty\
etc\
How can I let the PDB files 'know' where the source is (I am assuming this is required)? Is there a CMake command that can achieve this? What would be a small example?

I just answered my own similar question, How to get CMake to install PDB files for targets.
Use this install rule to copy the target's PDB file, if it exists, to the target's install location bin directory.
install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}> DESTINATION bin OPTIONAL)

PDB files store absolute path names to the source files. When not using a symbol server, the only way to ensure some degree of source code relocatability is to use the subst command.
The idea is to use subst to create a drive-letter name (e.g. N:\) for the root of the source tree. Then do your builds from this drive, so that absolute paths starting with N:\ get embedded into the PDB files. When you later need to debug the executable on a different machine, use subst on that machine to get the same absolute paths to the sources. This will enable the PDB files to find the source files.
For example, if you have a file C:\MySources\main.cpp, do the following:
subst N: C:\MySources
N:
run your build
Later, let's say you need to debug on a machine where the same file is stored in D:\Devel\Other\main.cpp. Simply do subst N: D:\Devel\Other and then work from the N: drive there as well.
This answer is largely based on information from this question and the links therein.

You just need to inform Visual Studio where the source is... It will pop up a file browser dialog; just point to the source on your local machine if the paths differ from when it was built.

The PDB file stores the path to the files as they were when the program was compiled. There is nothing you must do to let them know where the source was.

Related

correspondence between muti cmakelists.txt file and vs project structure that created by cmake vs geneator?

I'm trying to build a visual studio c++ project under windows by cmake, there are two cmakelists.txt file in my source, and they are't parent-child relationship, main cmakelists.txt link library and add executable, the other one is only responsible for collating the dependent path to the global variable and passing to main cmakelists.txt file use.
At the beginning of executing cmake script, i pass the build dir path by command line parameter "-B".
Final i got the output file, but the structure of result direcotry puzzled me.Main-cmakelists.txt generate configuration file to build folder that was specified by earlier. But the other one cmakelists.txt, which generate configuration file outside, and one level heigher than specified build folder, and the folder with same name as the folder where sub-cmakelists.txt located.
I tried to find answer in offical documents and book like cmakecookbook, currently, no relevant entry found.
How can i specify the path for the generator ouput of sub-cmakelists.txt? I want to unify same build root folder for all cmakelists.
Is there have some professional tutorial introduction about correspondence between cmake file and vs project file?
Thanks.
enter image description here
The second parameter of add_subdirectory() command, can specify the binary_dir path to place the output file for sub-cmakelist.

how to use pb.cc to make libraries in subdirectories, i got "Cannot find source file"

I tries to use FOREACH to generated several pb files. And make two list names PROTO_SRCS & PROTO_HDRS like below.
I can use it in the main CMakeLists. Like add_executable(a SHARED ${PROTO_SRCS} main.cpp).
But I can not use this param in subdirectories to make a library. when I type "cmake .." in main CMakelists build dir. It shown that "Cannot find source file: a.pb.cc".
main CMakeLists.txt
add_library(xxx SHARED ${PROTO_SRCS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/back back)
in src/back CMakeLists.txt
add_executable(yyy ${PROTO_SRCS})
and I can use message to show ${PROTO_SRCS} in subdir so it pass into successfully.
Please help me to point out the problem. Thx a lot
The issue is that in CMake versions older than 3.20 the GENERATED property of source files is only visible in the directory where it is set. Thus, when you add the protobuf-generated source files to a target defined in a different directory, CMake will no longer know that these are files generated during the build. Consequently, CMake will try to locate these files at configuration time, when they obviously do not exist yet.
Unfortunately, at the time of writing there is only a release candidate for CMake 3.20 and no official release yet. So depending on whether you need to coordinate with other coworkers or whether you're working on this project on your own it might not be feasible to use the release candidate.
If you can't use it, the alternative is to create an object library via add_library(protobuf_objs OBJECT ${PROTO_SRCS}) in the directory where you generate the files and to use target_sources(xxx PRIVATE $<TARGET_OBJECTS:protobuf_objs>) and target_sources(yyy PRIVATE $<TARGET_OBJECTS:protobuf_objs>) instead of adding the ${PROTO_SRCS} as source files to these targets directly.

Why aren't binaries placed in CMAKE_CURRENT_BINARY_DIR?

It is my understanding that CMAKE_CURRENT_BINARY_DIR should point to the directory where binaries for the current CMakeLists.txt file will be placed. However, this doesn't seem to be the case.
Consider this file structure:
CMakeTest
+- CMakeLists.txt
+- main.cpp
CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
add_executable(CMakeTest main.cpp)
message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}")
main.cpp
#include <iostream>
int main() {
std::cout << "Hello, World!";
return 0;
}
On the (Windows) command line, I run the following commands:
md build
cd build
cmake .. -G "Visual Studio 14 2015"
cmake --build .
The first cmake command prints (among other things) the line
CMAKE_CURRENT_BINARY_DIR = X:/dev/projects/CMakeTest/build
So I'd expect the resulting binary file CMakeTest.exe to end up there. Really, however, it is placed in X:/dev/projects/CMakeTest/build/Debug.
Why isn't the binary file placed into CMAKE_CURRENT_BINARY_DIR, but in a sub-directory? And is there any CMake variable that tells me what that subdirectory is?
Edit:
I'm not trying to change the directory where binaries are placed. I'm trying to determine it. The reason is this:
During build, a number of additional resource files are created in the same directory as the executable file. (This part works.) I'd like to use the install(FILES, ...) command to then add these files to the resulting package. So I need to pass the actual path where the binaries are placed to install(FILES, ...).
Variable CMAKE_CURRENT_BINARY_DIR denotes "binary directory currently being processed" by CMake. Usually, this directory and its subdirectories contains build artifacts, like executables, libraries or other generated files.
If you want to control location of executable being built, you need to set variable CMAKE_RUNTIME_OUTPUT_DIRECTORY.
Note, that multiconfiguration build tools, like Visual Studio, for each specific configuration will create subdirectory (named as configuration itself) under CMAKE_RUNTIME_OUTPUT_DIRECTORY. Otherwise, executables created for different configurations would overwrite themselves.
For precise control of per-configuration directory used for built executables, use variable CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>. (Instead of <CONFIG> name of specific configuration should be inserted, so CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG variable will affect Debug builds).
For just determine directory with executable, use $<TARGET_FILE_DIR:tgt> generator expression (instead of tgt a name of the target created the executable should be used).
Note, that generator expressions can be used only in specific places. E.g., list of files for install(FILES) command can use generator expression, but message() command cannot.
Yes, the executables are often stored at a level below the CMAKE_CURRENT_BINARY_DIR, based on the build type. You can navigate to this directory directly by using ${CMAKE_BUILD_TYPE} (which is typically has value of Debug or Release) by building a full path like:
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}

How to remove tokens from a list in cmake?

I want to exclude some source files from building when not in Windows.
What is wrong in the following CMakeLists.txt cmake file?
aux_source_directory(. SRC_LIST)
# Remove Microsoft specific files
message(${SRC_LIST})
list(REMOVE_ITEM SRC_LIST stdafx.h stdafx.cpp)
message("------------------")
message(${SRC_LIST})
The contents of the messages before and after trying to remove the two files are exactly the same.
What is wrong?
You have to specify the exact name of the element you want to remove.
In your case, aux_source_directory prepends each entry with a ./, so the correct command has to be
list(REMOVE_ITEM SRC_LIST ./stdafx.h ./stdafx.cpp)
Also, please make sure you understand the implications of using manual calls to aux_source_directory for maintaining lists of source files:
It is tempting to use this command to avoid writing the list of source
files for a library or executable target. While this seems to work,
there is no way for CMake to generate a build system that knows when a
new source file has been added. Normally the generated build system
knows when it needs to rerun CMake because the CMakeLists.txt file is
modified to add a new source. When the source is just added to the
directory without modifying this file, one would have to manually
rerun CMake to generate a build system incorporating the new file.
Quoting the documentation for aux_source_directory.

Set C++ object file output location with CMake

I would like to use CMake for a project, but I have the following two requirements:
The final output of the project should be a set of object files (*.o).
The location of the object files is important. I want to select which directory the files are outputted.
Does CMake support this type of behavior? If so, how? Can I do it with move commands after the object file is build?
First create an object library.
Now the problem is that:
Object libraries cannot be imported, exported, installed, or linked.
http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:add_library
I would try to use the install(DIRECTORY ...).
Using the options:
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} #Probably you have to check more precisely where the object files are built
DESTINATION #it's something relative to DESTDIR, if set, or CMAKE_INSTALL_PREFIX otherwise
FILES_MATCHING
PATTERN "*.o"
A flaw of this solution will be in the output directory name, that will be basically decided by cmake, I wonder if anything can be done in that respect.