0
votes

Our compilation system copies binary dependencies using robocopy. For example, an hypotetical copy_dependencies.bat file can be something like:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll

Since such binaries do not affect the success of the compilation but the execution of final executables, we'd like to add error-checking to them (check path or filenames changes, for example). The idea is to catch them ASAP instead of on a deeper level when the tests run.

As if the batch returns a non-zero errorlevel then our compilation system automatically stops, our first approach would be to check the error level at the end of each batch:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll

if errorlevel 8 exit /b
exit /b 0

Note: We check for an errorlevel of at least 8 since smaller values are just warnings for us (extra files and so on). That's why we also reset the errorlevel to 0 at the end.

The problem is that robocopy resets the errorlevel, so if the first command fails it is not reported. Then, the next solution would be to check every single call:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
if errorlevel 8 exit /b
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll
if errorlevel 8 exit /b

exit /b 0

The problem here is that we'd have to change hundreds of files.

In addition to a replace-all-like script to do so, is there any cleaner way to do it? Something like a flag to robocopy that we can add to PARAMETERS to avoid the reset?

A different approach may involve an execution flag for batches that automatically exits the script if the errorlevel is 8 or higher (so we can set it at the beginning of the compilation).


PS

I'm publishing our best solution so far but it still will require modifying all the files. Changing the batch files (especially because of the easy pattern) is not very time consuming now but I would like to know if there is a solution that does not involve such change. Thanks!

1
I am afraid there is no flag for robocopy to keep previous ErrorLevel values. Anyway, you should first clarify what you want to happen in case the first robocopy line fails, so whether the second one should still be executed or not...aschipfl
@aschipfl thanks! actually in our case it would be the same if following robocopies are executed or not as long as the copy_dependendies.bat fails (errorlevel > 0), since it is the one that is checked by the compilationcbuchart
Why do you use a batch file after all? why not just calling robocopy.exe directly?aschipfl
@aschipfl our makefile is structure something like: 1) checkout/update 2) dependencies 3) compile 4) post-build operations. Step 2 can imply many operations (dozens of dependencies) so they are contained in a separate per-project-scriptcbuchart
It's not just robocopy. Every Windows executable resets the errorlevel. Unless you specifically write an application that saves the errorlevel before it starts, but even then you'll have to pass the errorlevel to the application on the command line because there's no automatic way for any application to get the previously-run application's exit code.DodgyCodeException

1 Answers

0
votes

UPDATE

As suggested by @DodgyCodeException in the comments, the solution that best solves this problems seems to be to prefix every robocopy statement with a single-line condition so that the robocopy is executed only if the error level has not been raised before. The copy_dependencies.bat shown in the example is now:

@echo off
if not errorlevel 8 robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
if not errorlevel 8 robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll

if errorlevel 8 exit /b
exit /b 0

Previous solution included using an intermediate batch (called here my_robocopy.bat) that propagates the error level:

@echo off
if errorlevel 8 exit /b
robocopy %PARAMETERS% %*
exit /b

The copy_dependencies.bat shown in the example is now:

@echo off
call %COMMON_PATH%\my_robocopy.bat src_path\Debug   dst_path\Debug   dep_name.dll
call %COMMON_PATH%\my_robocopy.bat src_path\Release dst_path\Release dep_name.dll

if errorlevel 8 exit /b
exit /b 0