Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-46596

Broken multi-line bat when calling vcvarsall.bat

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • durable-task-plugin
    • None
    • Durable Task Plugin 1.14

       

      Hello, I've ran into a weird parsing bug when using multi-line bat commands under Windows.

       

      We use the VisualStudio compiler, which requires running `vcvarsall.bat` from the command line in order to setup our environment prior to build.

      node('windows-vs2013') {
          bat """
              vcvarsall.bat x86
              echo "Made it!"
              nmake /?
          """
      }
      

      Unfortunately, it doesn't appear we actually execute the command successfully. We see:

      [Pipeline] node
      Running on dynamic-windows-vs2013-2934 in C:\jenkins\workspace\multiline-bat
      [Pipeline] {
      [Pipeline] bat
      [multiline-bat] Running batch script

      C:\jenkins\workspace\multiline-bat>vcvarsall.bat x86;
      [Pipeline] }
      [Pipeline] // node
      [Pipeline] End of Pipeline
      Finished: SUCCESS

      Note, the command appears to be executed, but we never see the expected "Made it" text or the help content from nmake.

      To be clear, you cannot do this in two steps:

      bat "vcvarsall x86"
      bat "nmake"

      Because the second command will be executed in a different shell that does not contain the correct environment configuration.

      Curiously, we can work around the issue by doing:

      node('windows-vs2013') {
          bat """
              call vcvarsall.bat x86
              echo "Made it!"
              nmake /?
          """
      }

      Which produces the correct output:
      Edit 9/5/17:
      Which only sometimes produces the correct result:

      Running on dynamic-windows-vs2013-6962 in C:\jenkins\workspace\multiline-bat
      [Pipeline] {
      [Pipeline] bat
      [multiline-bat] Running batch script

      C:\jenkins\workspace\multiline-bat>call vcvarsall.bat x86
      "Made it!"

      Microsoft (R) Program Maintenance Utility Version 12.00.21005.1
      Copyright (C) Microsoft Corporation. All rights reserved.

      Usage: NMAKE @commandfile
      NMAKE [options] [/f makefile] [/x stderrfile] [macrodefs] [targets]

      Options:

      /A Build all evaluated targets
      /B Build if time stamps are equal
      /C Suppress output messages
      /D Display build information
      /E Override env-var macros
      /ERRORREPORT:{NONE|PROMPT|QUEUE|SEND} Report errors to Microsoft
      /G Display !include filenames
      /HELP Display brief usage message
      /I Ignore exit codes from commands
      /K Build unrelated targets on error
      /N Display commands but do not execute
      /NOLOGO Suppress copyright message
      /P Display NMAKE information
      /Q Check time stamps but do not build
      /R Ignore predefined rules/macros
      /S Suppress executed-commands display
      /T Change time stamps but do not build
      /U Dump inline files
      /Y Disable batch-mode
      /? Display brief usage message
      [Pipeline] }
      [Pipeline] // node
      [Pipeline] End of Pipeline
      Finished: SUCCESS

      I was a little surprised the first form didn't work and figured I'd create the ticket to raise awareness and share our workaround. Consider it a low priority.

      Thanks for all your hard work.
      Regards,

      Ryan

       

      Note, I actually discovered this very usable workaround while drafting the issue. This new workaround solves my original complaint about our previous workaround, which required chaining together multiple commands using 

      bat "vcvarsall x86 && cmake ... && nmake ..."
      

      The "&&" chaining becomes pretty unusable if the arguments/command chain gets large. The "call" solution is much more succinct and allows us to still leverage a multi-line string to improve readability. Cheers!

      Edit 9/5/17
      The "call" workaround previously mentioned only partially works. It works in the simple case, like in the original sample, but extending it failed:

      bat """
      		call vcvarsall.bat amd64
      		cmake -G Ninja  -D SOME_VARIABLE=Something ^
      			-D CMAKE_INSTALL_PREFIX=${WORKSPACE}/install ^
      			-D CMAKE_BUILD_TYPE=RelWithDebInfo ^
      			-D VERSION_PRIVATEBUILD=true ^
      			-D VERSION_NUMBER=4.0.0.0 ^
      			-D VERSION_SPECIALBUILD=${BUILD_TAG} ^
      			-D SOME_CUSTOM_PARAM=http://someURL ^
      			-D SOME_CUSTOM_PARAM=${WORKSPACE}/build/folder ^
      """
      

      We're still back to the original solution, which works but seems a little tacky:

      void multiline(List<String> commands) {
      	command = commands.join(" && ")
      	return command
      }
      bat multiline([
          "vcvarsall.bat amd64",
          "cmake -G ..."
      ])
      

       

       

       

       

       

       

       

       

       

            Unassigned Unassigned
            thorntonryan Ryan Thornton
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: