# cmakeBuild does not set environment variables in Windows when run in Pipeline

XMLWordPrintable

#### Details

• Bug
• Status: Closed
• Blocker
• Resolution: Not A Defect
• None
• Jenkins ver. 2.164.3
Cmake plugin version 2.6.1
Jenkins slave running on windows machine as a service.

#### Description

Jenkins pipeline snippet:

def cmake_tasks() {
def steps = [[withCmake: true]]
def os = "windows"
def config = "Debug"
def generator = "Ninja"

// ==== addidional env vars ====
def vars="""
LIB=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\ATLMFC\\LIB\\amd64;C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.17763.0\\ucrt\\x64;C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\lib\\um\\x64;C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.17763.0um\\x64;
PATH=C:\\Program Files (x86)\\MSBuild\\14.0\\binamd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64;C:\\Program Files (x86)\\Windows Kits\\10\\binx64;C:\\Program Files (x86)\\Windows Kits\\10\\binx86;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.6.1 Tools\\x64;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\CMake\\bin;c:\\windows\\system32;C:\\
Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v7.0bin;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v7.0libnvvp;g:\\Bin;
"""

// another variant, also does not affect CMake
//   vars = bat returnStdout: true, script: """
//@call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
//set
//"""

// third variant, also doesn't work
//    bat """call c:\Path\to\Visual\Studio\vcvarsall.bat
//           set > build.props"""

def cmakeArgs = "-DARG=VALUE"
def cmake_inst = 'InSearchPath'
cmakeArgs = cmakeArgs + " -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_MAKE_PROGRAM=g:\\Bin\\ninja"
tasks["${os}"] = { node("${os}"){
stage("${os}/${config}") {
withEnv([vars]){
if (os == "windows"){
bat "set | sort"
println vars
println steps
}

cmakeBuild(buildDir: "build_${config}", buildType: config, cleanBuild: true, cmakeArgs: cmakeArgs, generator: generator, installation: cmake_inst, sourceDir: ".", steps: steps) } } } } return tasks } pipeline { agent none stages{ stage('Configurte') { steps{ script { parallel cmake_tasks() } } } } }  Snippet of CMakeLists.txt cmake_minimum_required(VERSION 3.12) message(STATUS "LIB value =$ENV{LIB}")
message(STATUS "PATH value = $ENV{PATH}")  Result: I see LIB and PATH in output of "set | sort " and both println's inside if(os == "windows") block. But output of cmake shows only default environment variables. LIB is unset, PATH is default LIB value = PATH value = C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\CMake\\bin;c:\\windows\\system32;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v7.0bin;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v7.0\\libnvvp;g:\\Bin;  #### Attachments #### Attachments #### Activity After careful studying of this discussion, as well as a web-page of snippet generator, it became clear for me that envVars, passed to cmakeBuild, has nothing to do with my issue. And the issue itself is invalid, since I've incorrectly passed arguments to withEnv. Thanks for the help. Vladimir Eremeev added a comment - After careful studying of this discussion, as well as a web-page of snippet generator, it became clear for me that envVars, passed to cmakeBuild, has nothing to do with my issue. And the issue itself is invalid, since I've incorrectly passed arguments to withEnv. Thanks for the help. Vladimir Eremeev added a comment - - Anyway, you do not need to pass envvars to BuildToolStep to configure cmake. These varaibles are passed to the build tool (make or nija). Now I see why my attempts failed. It seems, the only way to pass environment variables to cmake is using withEnv. The online help for Build tool | Env. Variableshas an example that shows how to set multiple variables. Sorry, I cannot figure out where it is, and how I should use it in a pipeline script. Here is what I've entered in pipeline snippet generator: And here is the generated code: cmakeBuild buildDir: '${build_dir}', buildType: '${config}', cleanBuild: true, generator: 'Ninja', installation: 'InSearchPath', sourceDir: '${env.WORKSPACE}', steps: [[envVars: '''A=B
C=D''', withCmake: true]]


Code sample in the issue description does exactly this. It generates a string in the form "NAME=VALUE<newline>NAME=VALUE"), and CMake does not see these variables.

They don't contain examples either.

I've also studied sources on GitHub but failed to find how BuildToolStep processes this.vars, set in setEnvVars.

Vladimir Eremeev added a comment - - Anyway, you do not need to pass envvars to BuildToolStep to configure  cmake . These varaibles are passed to the  build tool  (make or nija). Now I see why my attempts failed. It seems, the only way to pass environment variables to cmake is using withEnv. The online help for  Build tool | Env. Variables has  an example that shows how to set multiple variables. Sorry, I cannot figure out where it is, and how I should use it in a pipeline script. Here is what I've entered in pipeline snippet generator:  And here is the generated code: cmakeBuild buildDir: '${build_dir}' , buildType: '${config}' , cleanBuild: true , generator: 'Ninja' , installation: 'InSearchPath' , sourceDir: '\${env.WORKSPACE}' , steps: [[envVars: '''A=B C=D''', withCmake: true ]] Code sample in the issue description does exactly this. It generates a string in the form "NAME=VALUE<newline>NAME=VALUE"), and CMake does not see these variables.   I've found two links: https://javadoc.jenkins.io/plugin/cmakebuilder/index.html?hudson/plugins/cmake/BuildToolStep.html  and https://javadoc.jenkins.io/plugin/cmakebuilder/hudson/plugins/cmake/BuildToolStep.html They don't contain examples either. I've also studied sources on GitHub but failed to find how BuildToolStep processes this.vars, set in setEnvVars.
Martin Weber added a comment -
"java.lang.ClassCastException: class hudson.plugins.cmake.BuildToolStep.setEnvVars() expects class java.lang.String but received class java.util.ArrayList"


You get this, because BuildToolStep.setEnvVars() takes a String, not an array. You may specify more than one envvar, if you separate them by newlines (as stated in the online help). This is the same behavior as in the freestyle project version of the plugin.
Anyway, you do not need to pass envvars to BuildToolStep to configure cmake. These varaibles are passed to the build tool (make or nija). The main purpose is to run

make install

with the DESTDIR variable set to a directory below workspace root in order to ease archiving of artifacts.

4. Both documentation pieces, for withEnv and for envVars, miss examples on how to set multiple variables, they only show how to set a single variable, a very rare case, IMHO.

The online help for Build tool | Env. Variables has an example that shows how to set multiple variables.

Martin Weber added a comment - "java.lang.ClassCastException: class hudson.plugins.cmake.BuildToolStep.setEnvVars() expects class java.lang.String but received class java.util.ArrayList" You get this, because BuildToolStep.setEnvVars() takes a String, not an array. You may specify more than one envvar, if you separate them by newlines (as stated in the online help). This is the same behavior as in the freestyle project version of the plugin. Anyway, you do not need to pass envvars to BuildToolStep to configure cmake . These varaibles are passed to the build tool (make or nija). The main purpose is to run make install with the DESTDIR variable set to a directory below workspace root in order to ease archiving of artifacts. 4. Both documentation pieces, for withEnv and for envVars, miss examples on how to set multiple variables, they only show how to set a single variable, a very rare case, IMHO. The online help for Build tool | Env. Variables has an example that shows how to set multiple variables.

Yes, indeed. Changing argument of withEnv to

vars = ["INCLUDE=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE; ..... ",
"LIB=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64; ...",
"LIBPATH=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;....",
"PATH=C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;...",
// etc
]

does the trick.

Tried adding the same to the "steps" argument of cmakeBuild:

def steps = [[
withCmake: true,
envVars: ["INCLUDE=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE; ..... ",
"LIB=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64; ...",
"LIBPATH=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;....",
"PATH=C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;...",
// etc
] ]]


got error:

"java.lang.ClassCastException: class hudson.plugins.cmake.BuildToolStep.setEnvVars() expects class java.lang.String but received class java.util.ArrayList"


I see following issues.

1. Manual of withEnv is not clear (I understand that this is not related to current issue)

2. Processing of envVars by cmakeBuild is not consistent with one, done by "withEnv" (Though, I understand that different authors could have different ideas about user interface. But consistency is good).

3. Description of envVars is misleading. I've come from Python, and sentence "key-value pairs" suggests that this argument should be a dictionary (or a map), not a string. It is not said, how these pairs must be separated, if they are wrapped in a string.

4. Both documentation pieces, for withEnv and for envVars, miss examples on how to set multiple variables, they only show how to set a single variable, a very rare case, IMHO.

Vladimir Eremeev added a comment - - Yes, indeed. Changing argument of withEnv to    vars = [ "INCLUDE=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE; ..... " , "LIB=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64; ..." , "LIBPATH=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;...." , "PATH=C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;..." , // etc ] does the trick. Tried adding the same to the "steps" argument of cmakeBuild: def steps = [[ withCmake: true , envVars: [ "INCLUDE=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE; ..... " , "LIB=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64; ..." , "LIBPATH=C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;...." , "PATH=C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;..." , // etc ] ]] got error: "java.lang.ClassCastException: class hudson.plugins.cmake.BuildToolStep.setEnvVars() expects class java.lang. String but received class java.util.ArrayList"   I see following issues. 1. Manual of withEnv is not clear (I understand that this is not related to current issue) 2. Processing of envVars by cmakeBuild is not consistent with one, done by "withEnv" (Though, I understand that different authors could have different ideas about user interface. But consistency is good). 3. Description of envVars is misleading. I've come from Python, and sentence "key-value pairs" suggests that this argument should be a dictionary (or a map), not a string. It is not said, how these pairs must be separated, if they are wrapped in a string. 4. Both documentation pieces, for withEnv and for envVars, miss examples on how to set multiple variables, they only show how to set a single variable, a very rare case, IMHO.
Martin Weber added a comment -

withEnv takes an array of multiple key-value pairs, one for each variable. Your script passes an array of a single string containing multiple key-value pairs, if I understand your script correctly. Please try with a minimal example.

Martin Weber added a comment - withEnv takes an array of multiple key-value pairs, one for each variable. Your script passes an array of a single string containing multiple key-value pairs, if I understand your script correctly. Please try with a minimal example.

#### People

Martin Weber