Search code examples
c++visual-studiocmakecompilation

Debugging CMake Visual Studio project with PATH environment set by VS_DEBUGGER_ENVIRONMENT


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!


Solution

  • This is just to share what I finally ended up with after some painful hours of digging through the web.

    1. 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")
    
    1. 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.

    1. 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 Debugging environment for C/C++ and here for FORTRAN targets Debugging environment for FORTRAN