Debugging CMake Visual Studio project with PATH environment set by VS_DEBUGGER_ENVIRONMENT - c++

I've created a CMake project using visual studio 2019. It has one executable target, which links to some shared libraries (DLL). I cannot directly set the system environment variable PATH because the DLL path is determined by find_package. Therefore, set VS_DEBUGGER_ENVIRONMENT target property is my choice to debug that executable target.
However, the VS_DEBUGGER_ENVIRONMENT property is not working when I directly open the CMake project and debug that target. I've checked the .vsproj it has the correct LocalDebuggerEnvironment tag generated.
But if I run cmake -G "Visual Studio 16 2019" ../ and open the generated visual studio solution and then debug the subproject from there, everything turns out to be ok.
I think maybe the visual studio doesn't support LocalDebuggerEnvironment when opening project as a CMake project. Or perhaps I didn't debug it the right way. Is there anything else I can do to change the visual studio debug runtime PATH environment using CMake?
Any suggestion would be greatly appreciated!

This is just to share what I finally ended up with after some painful hours of digging through the web.
First, a variable to store the required debugging paths is needed (example):
list(APPEND VS_DEBUGGING_PATH "%PATH%")
list(APPEND VS_DEBUGGING_PATH "${PostgreSQL_ROOT}/bin")
The next step is to create a ${CMAKE_PROJECT_NAME}.vcxproj.user template file for C/C++ and in my case also a ${CMAKE_PROJECT_NAME}.vfproj.user template for FORTRAN (just for the record):
file(
WRITE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'\$(Configuration)'=='Release'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='MinSizeRel'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='RelWithDebInfo'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='Debug'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>"
)
file(
WRITE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vfproj.user"
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<VisualStudioUserFile>
<Configurations>
<Configuration Name=\"Release|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"MinSizeRel|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"RelWithDebInfo|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"Debug|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
</Configurations>
</VisualStudioUserFile>"
)
As you might see, both template files are just dumped into the root of ${CMAKE_BINARY_DIR} in this case. The base name ${CMAKE_PROJECT_NAME} is also arbitrary.
Those templates can then finally be "configured" (copied) into each target folder of your setup. Either for C/C++
configure_file(
"${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vcxproj.user"
"${CMAKE_CURRENT_BINARY_DIR}/${target_name}.vcxproj.user"
#ONLY
)
or FORTRAN
configure_file(
"${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vfproj.user"
"${CMAKE_CURRENT_BINARY_DIR}/${target_name}.vfproj.$ENV{USERNAME}.user"
#ONLY
)
or even both if necessary. The variable ${target_name} needs to replaced with your target name of course. :-)
This should suffice. It is however important to close VS 2019 before (re-)configuring/(re-)generating with CMake. Otherwise VS 2019 might simply overwrite those files for each target.
I strongly hope this is helpful.
Please let me know if you need more details.
Here is the result for C/C++ targets and here for FORTRAN targets

Related

Reading file in a c++ file in VS project [duplicate]

I have a project with the following structure:
project_name/CMakeLists.txt
project_name/src
project_name/resources
...
project_name-build/configuration_name/project_name.exe
I want my application to be run in the root project directory project_name so it can directly access resources.
Does CMake provide a method to specify this property, or will I have to manually set it in each build environment I use?
I've looked around in the documentation and haven't found anything other than the possibility of setting up a post-build event to run my project from the desired directory which is less than desirable. I also found that the working directory setting for Visual Studio is saved in a per-user file (.vcxproj.user) which I don't believe CMake generates (which points to the answer being probably no).
Since CMake 3.8, there is the VS_DEBUGGER_WORKING_DIRECTORY target property, which allows you to set the debugger working directory for a target in Visual Studio.
Usage example:
set_property(TARGET MyTarget PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
As drescherjm pointed out (in his comment on the question) CMake doesn't provide a method to directly set a working directory. However, CMake does provide indirect methods of doing so.
The path I think I'll take is to use the configure_file command to fill in a template .user file.
Here is an easier solution.
Paste this at the end of your cmake:
file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?> \
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>")
It overwrites the default vcxproj.user file for the current project and specifies $(OutDir) for the Working Directory as desired for debugging. Make sure that $PROJECT_NAME is your project name.

Dependent project cannot see headers from a library in refferences in Visual Studio

I am learning how to make a static library. I started with windows and Visual Studio.
The directory structure looks like this:
- MyLibraryProject
- include
- MyLibraryProject
- MyLibraryHeader.h
- src
- MyLibrarySource.cpp
- build
- MyLibraryProject.vcxproj
- MyDependentProject
- main.cpp
- MyDependentProject.vcxproj
MyLibraryProject.vcxproj has the following settings:
Setting
Value
Configuration type
Static library (.lib)
Additional Include Directories
$(MSBuildThisFileDirectory)../include/MyLibraryProject
MyDependentProject.vcxproj has no special settings, except I added MyLibraryProject onto refferences, the image features actual names I used:
If I use relative paths in main.cpp, I can build the project - the static linking works just fine and it runs:
#include "../MyLibraryProject/include/MyLibraryProject/MyLibraryHeader.h"
However, I want to include the headers like this:
// fatal error C1083: Cannot open include file: 'MyLibraryProject/MyLibraryHeader.h': No such file or directory
#include <MyLibraryProject/MyLibraryHeader.h>
And that just does not work. I also tried to use property sheet but couldn't get that to work either. I've been searching the internet, but generally found claims that if you add a reference, both headers and static libs will work.
Here's the full repository, if you're willing to take a look. Or ask in the comments if there's information missing.
Project references do not provide the dependent project with any information about headers. The most flexible way to do this instead (in Visual Studio) are property sheets. I created a file MyLibraryProject/build/MyLibraryProjectDependency.props:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
And I added it to MyDependentProject.vcxproj in Property explorer in Visual Studio. This solved the issues and headers are now seen on the path I want them.

How to ensure that the relative paths are the same in Linux and Windows using CMake [duplicate]

I have a project with the following structure:
project_name/CMakeLists.txt
project_name/src
project_name/resources
...
project_name-build/configuration_name/project_name.exe
I want my application to be run in the root project directory project_name so it can directly access resources.
Does CMake provide a method to specify this property, or will I have to manually set it in each build environment I use?
I've looked around in the documentation and haven't found anything other than the possibility of setting up a post-build event to run my project from the desired directory which is less than desirable. I also found that the working directory setting for Visual Studio is saved in a per-user file (.vcxproj.user) which I don't believe CMake generates (which points to the answer being probably no).
Since CMake 3.8, there is the VS_DEBUGGER_WORKING_DIRECTORY target property, which allows you to set the debugger working directory for a target in Visual Studio.
Usage example:
set_property(TARGET MyTarget PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
As drescherjm pointed out (in his comment on the question) CMake doesn't provide a method to directly set a working directory. However, CMake does provide indirect methods of doing so.
The path I think I'll take is to use the configure_file command to fill in a template .user file.
Here is an easier solution.
Paste this at the end of your cmake:
file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?> \
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>")
It overwrites the default vcxproj.user file for the current project and specifies $(OutDir) for the Working Directory as desired for debugging. Make sure that $PROJECT_NAME is your project name.

What is the $(PackageConfiguration) variable in a Visual Studio project?

I ran into a linker error (Couldn't open sqlite3.lib) when making a WinRT application. The funny thing is, it only happens in a new configuration that I made (Master, as opposed to Debug or Release). I cloned the new configuration from Release, so it should be identical except for a few preprocessor defines. I found the following entry as a default in my "Library Directories" section under "VC++ Directories"
$(FrameworkSDKRoot)..\v8.1\ExtensionSDKs\SQLite.WinRT81\3.8.0.2\DesignTime\$(PackageConfiguration)\$(PlatformTarget)
However, I can't find any information on what the PackageConfiguration variable actually expands to. I guessed it might be Debug / Release but the folders at that location on the file system are Debug and Retail. If I add another entry with "Retail" instead of $PackageConfiguration then I can build the program properly, but it seems strange. Does anyone know how this variable is defined?
This value comes from the SQLite.WinRT81.props file located in the SQLite extension SDK which is usually installed here:
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1\ExtensionSDKs\SQLite.WinRT81\3.8.2\DesignTime\CommonConfiguration\neutral
On my machine the contents look like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PackageConfiguration Condition="'$(Configuration)' == ''">Debug</PackageConfiguration>
<PackageConfiguration Condition="'$(Configuration)' == 'Debug'">Debug</PackageConfiguration>
<PackageConfiguration Condition="'$(Configuration)' == 'Release'">Retail</PackageConfiguration>
</PropertyGroup>
<PropertyGroup>
<IncludePath>$(FrameworkSDKRoot)\..\v8.1\ExtensionSDKs\SQLite.WinRT81\3.8.2\DesignTime\CommonConfiguration\Neutral;$(IncludePath)</IncludePath>
<LibraryPath>$(FrameworkSDKRoot)\..\v8.1\ExtensionSDKs\SQLite.WinRT81\3.8.2\DesignTime\$(PackageConfiguration)\$(PlatformTarget);$(LibraryPath)</LibraryPath>
<PropertySheetDisplayName>SQLite.WinRT81, 3.8.2</PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>sqlite3.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>

CMake command line for C++ #define

I need to compile different versions of a certain project by adding compiler switches. Usually I would do this by using add_definitions or something like
set_property( TARGET mylib PROPERTY COMPILE_DEFINITIONS _MYDEFINE=1 )
in the CMakeLists.txt file.
In this specific project however, I am not allowed to modify any sources, including the CMakeLists.txt file.
I was hoping that something like
cmake -D_MYDEFINE=1 <path to sources>
would generate a project file (Visual Studio 2008 in my case, but shouldn't matter) which includes _MYDEFINE=1 in its preprocessor definitions but in fact it won't.
What are my options here? Is there a different cmake command line option to achieve this? Feel free to suggest solutions not including the command line, as long as changing the project's CMakeLists.txt is not necessary.
I managed to do it this way now:
I was able to convince everybody to add the following lines to the common CMakeLists.txt:
IF (NOT DEFINED _MYDEFINE)
SET(_MYDEFINE <default value>)
ENDIF()
ADD_DEFINITIONS(-D_MYDEFINE=${_MYDEFINE})
(No it is not really called "MYDEFINE", and <default value> is just a placeholder, I just replaced all that for this example)
This does not change the current behaviour of compiling with no additional compiler flags and is thus a valid change.
And it allows you to do
cmake -D_MYDEFINE=<my value> <path to sources>
where this cmake definition will be mapped to a C++ precompiler definition when cmake creates the project file.
Container CMakeLists.txt solution
Tricky solution:
Your read only CMakeList.txt path: ${path}/ReadOnlyProject/CMakeLists.txt
Create a new CMakeList.txt to upper to the read only library (${path}/CMakeLists.txt):
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
PROJECT (FAKE_PROJECT)
ADD_DEFINITIONS(-D_MYDEFINE=1)
ADD_SUBDIRECTORY(ReadOnlyProject)
Now use your new project (FAKE_PROJECT) to compile. If the ReadOnlyProject does not set compilers definitions directly, it could work.
On Visual Studio 2010:
Try to modify c:\Users\${username}\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props to add custom compiler settings.
You should add the followings:
<Project>
...
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__MYDEFINE=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
To pass a C++ or C pre-processor define without modifying any CMake source files, use the environment variables CFLAGS for C or CXXFLAGS for C++ respectively, e.g.:
$ export CXXFLAGS="-D_MY_DEFINE=1 -D_MY_OTHER_DEFINE=1"
$ mkdir build
$ cd build
$ cmake ..