48

I am using CMake to generate Visual Studio project files. I want to run the test executable after setting the PATH environment variable so that it is able to load the required dll. I tried as per the discussion at http://www.mail-archive.com/cmake@cmake.org/msg21493.html but it does not work.

Have you used CMake with Visual Studio for this purpose? Please share your experiences.

Also, I find no easy way to debug my CMake script, for example to see what value it assigns to the PATH variable. Setting CMake verbose with CMAKE_VERBOSE_MAKEFILE does not help. How would I go about debugging it myself?

BIBD
  • 15,107
  • 25
  • 85
  • 137
amit kumar
  • 20,438
  • 23
  • 90
  • 126

6 Answers6

43

For setting custom project setting in Visual Studio from CMake you can use a XML file as a template which can be configured from CMake to work as the .user file.
At my work we use this to set custom debug parameters.

Check the directory containing the generated .vcxproj files for the user settings in the .user files. Here is a snippet of an example UserTemplate.vcxproj.user file we use.

    <?xml version="1.0" encoding="Windows-1252"?>
      <VisualStudioUserFile
        ProjectType="Visual C++"
        Version="9.00"
        ShowAllFiles="false"
        >
        <Configurations>
            <Configuration
                Name="Debug|@USERFILE_PLATFORM@"
                >
                <DebugSettings
                    Command="@USERFILE_COMMAND_DEBUG@"
                    WorkingDirectory="@USERFILE_WORKING_DIRECTORY_DEBUG@"
                    CommandArguments="@USERFILE_COMMAND_ARGUMENTS_DEBUG@"
                    Attach="false"
                    DebuggerType="3"
                    Remote="1"
                    RemoteMachine="@USERFILE_REMOTE_MACHINE_DEBUG@"
                                <!-- More settings removed for snippet -->
                />
            </Configuration>
                <!-- Rest of Configurations -->

Another example of a UserTemplate.vcxproj.user to set the PATH variable, would be:

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
        <LocalDebuggerEnvironment>PATH=..\Your_path;%PATH%".</LocalDebuggerEnvironment>
        <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
      </PropertyGroup>
    </Project>

Setting the UserTemplate.vcxproj.user file next to your CMakeLists.txt file, you can inject any needed variables from CMake into the .vcxproj.user file of your builded project. In CMake you can set the appropiate CMake variables (and add more in the template file if you need them). Next you can do something like this to configure the file.

    # Find user and system name
    SET(SYSTEM_NAME $ENV{USERDOMAIN} CACHE STRING SystemName)
    SET(USER_NAME $ENV{USERNAME} CACHE STRING UserName)

    # Configure the template file
    SET(USER_FILE ${_projectName}.vcxproj.${SYSTEM_NAME}.${USER_NAME}.user)
    SET(OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${USER_FILE})
    CONFIGURE_FILE(UserTemplate.vcxproj.user${USER_FILE} @ONLY)

If you don't care about the system and the user name, the following configuration would be enough.

    # Configure the template file
    SET(USER_FILE ${_projectName}.vcxproj.user)
    SET(OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${USER_FILE})
    CONFIGURE_FILE(UserTemplate.vcxproj.user ${USER_FILE} @ONLY)
MiguelVega
  • 13
  • 3
pkit
  • 7,993
  • 6
  • 36
  • 36
  • This mostly works, but then VStudio overrides my new .user file. How do I instruct VStudio to use a different .user file, or respect my changes? – Terry G Lorber Mar 23 '10 at 17:22
  • @terry-lorber: Today I verified that the above does actually work on VS2008SP1. I created a .vcproj file using CMake, copied in a something.vcproj...user file in the right spot where Visual Studio normally creates it, and my local changes to that file showed up when I viewed the .sln file in the VS IDE. – bgoodr Mar 11 '11 at 19:39
  • 4
    I've extended this, including supporting VS2010 - see CreateLaunchers in https://github.com/rpavlik/cmake-modules/blob/master/CreateLaunchers.cmake The trick is that you can't have visual studio open when generating this - it overwrites this file on exit. – Ryan Pavlik Sep 23 '11 at 13:16
  • Visual Studio (10) can be open, you just have to close the solution. – Andreas Haferburg Apr 18 '13 at 06:24
  • This is a good solution, but I wonder if there is a typo in the last line of the example. Should the `CONFIGURE_FILE` write to `${OUTPUT_PATH}` instead? – Mark Lakata Feb 27 '15 at 22:36
  • Obviously old answer, but just noting that this doesn't work with the Ninja generator of course. :) – Macke Mar 22 '22 at 13:01
11

Just spotted this question now. To debug cmake files I use

MESSAGE( STATUS "static text ${variable}" )

I have never had to set the path get my tests to run. Are you using CTest? It looks like the link you are following is used with ctest.

If I was trying to get this to work I would use set_tests_properties explicitly first.

set_tests_properties(SomeTest PROPERTIES ENVIRONMENT "PATH=c:\somedir;c:\otherdir")

Then make it more general.

plasmacel
  • 8,183
  • 7
  • 53
  • 101
iain
  • 10,798
  • 3
  • 37
  • 41
7

Cmake has a VS_DEBUGGER_ENVIRONMENT property which can be used to set the custom PATH

https://cmake.org/cmake/help/v3.13/prop_tgt/VS_DEBUGGER_ENVIRONMENT.html

set(MY_PATH "PATH=%PATH%" ${MY_CUSTOM_PATH})
set_target_properties(MyTarget PROPERTIES VS_DEBUGGER_ENVIRONMENT "{MY_PATH}")

Some other useful properties are VS_DEBUGGER_COMMAND_ARGUMENTS, VS_DEBUGGER_WORKING_DIRECTORY.

Vishwesh
  • 73
  • 1
  • 5
5

Here is related CMake feature request report:

http://www.kwwidgets.org/Bug/view.php?id=8884

UPDATE: Solved as per Set Visual Studio project "custom environment variables" setting with CMake - thanks to Florian for the comment below.

mloskot
  • 37,086
  • 11
  • 109
  • 136
  • 1
    The issue ["Set Visual Studio project "custom environment variables" setting with CMake"](https://gitlab.kitware.com/cmake/cmake/issues/8884) is now solved. – Florian Nov 25 '17 at 20:25
  • 1
    You're welcome. I have given it a try and added [an answer](https://stackoverflow.com/questions/1005901/how-to-set-path-environment-variable-using-cmake-and-visual-studio-to-run-test/47490441#47490441) with an code example. – Florian Nov 27 '17 at 20:46
5

You can give any options globally with the new VS_USER_PROPS target property (version >= 3.8).

Here is a working example:

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(SetEnvPathTest)

file(WRITE main.cpp [=[
// http://en.cppreference.com/w/cpp/utility/program/getenv
#include <iostream>
#include <cstdlib>

int main()
{
    if(const char* env_p = std::getenv("PATH"))
        std::cout << "Your PATH is: " << env_p << '\n';
}
]=])
add_executable(${PROJECT_NAME} main.cpp)

file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.Cpp.user.props" [=[
<?xml version="1.0" encoding="utf-8"?> 
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LocalDebuggerEnvironment>PATH=C:\Test</LocalDebuggerEnvironment>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LocalDebuggerEnvironment>PATH=C:\Test</LocalDebuggerEnvironment>
  </PropertyGroup>
</Project>
]=])

set_target_properties(
    ${PROJECT_NAME}
    PROPERTIES
        VS_USER_PROPS "${PROJECT_NAME}.Cpp.user.props"
) 

References

Florian
  • 39,996
  • 9
  • 133
  • 149
1

Just wanted to point out that a very useful addition that allows you to set up multiple environment variables as opposed to only one (e.g., only PATH) is given in this link https://stackoverflow.com/a/40531167/9253113

For example, if in addition to setting PATH you wanted to set another variable OTHERVAR one would have to modify the line

<LocalDebuggerEnvironment>PATH=C:\Test</LocalDebuggerEnvironment>

to

<LocalDebuggerEnvironment>PATH=C:\Test &#xA;OTHERVAR="value of OTHERVAR"</LocalDebuggerEnvironment>

Where the symbol "&#xA;" tells the xml parser to introduce the LF character. So multiple variable definitions are possible if separated by the LF character (also the CR character works but NOT the combination CRLF)

Also notice that there CANNOT be any space between &#xA; and the next variable.