In the previous post we did some installation and configuration of software to support us in the automation of doing static code analysis of TwinCAT software. We have reached a state where a Jenkins job is launched as soon as our TwinCAT library project is pushed to the Git-repository. Even though we have a Jenkins job defined for static code analysis of TwinCAT software, it’s not doing anything yet. This will be our next step.
The last thing we did in the last post was to verify that Jenkins cloned the repository defined in the job in the workspace directory C:\Jenkins\workspace<jobname>. What we need to do next is to create a build step for the job, which will orchestrate the build steps. The build step that we are going to add is going to launch a script that will provide all the necessary data for our program that will do the static code analysis.
First we have our TwinCAT-project that resides in the workspace directory of the Jenkins build machine. Next we need to launch a BAT-script that will collect some basic data about the Visual Studio/TwinCAT project (that just has been cloned from the GIT-repository) that it will analyze and provide this data to a C# program. The BAT-script will also launch the C#-program. It’s this C#-program that will open our TwinCAT-project and do the static code analysis. The result of the static code analysis is fed back to Jenkins, and we can use this result to for instance simply print it to any interested party or send an e-mail notification.
“A BAT-script? Isn’t that something you wrote in the ’90s?” some of you may think. Personally I’ve probably not written a windows batch file since I got my first IBM-compatible PC in the early/mid-’90s (a blazingly fast 66MHz 486 with 4MB of RAM). However, as we are running on a Windows machine I find this suitable. You can do quite a lot with windows batch files and surely more than enough for our purposes. It’s been really fun to dwelve into details and goodies of windows batch file development. If you find it more suitable you can write a bash script instead and run it in git bash (or the now included bash shell in Windows 10).
Go to the job-page in Jenkins and click Configure. There you will have the possibility to add a build step.
Select Execute Windows batch command and enter LaunchPLCStaticAnalysis.bat in the Command window and click Save. Now we want to add this file to our PLC library project, so create a new file with this name in the root-folder of your TwinCAT library project. Open it with your favourite editor. Now what exactly do we want our script to do? It’s actually quite simple. We want the script to launch our C#-program (which we’ve not yet written), and provide it with the arguments that it needs to initiate the static code analysis. The arguments are:
- The file-location of the Visual Studio project file
- The file-location of the TwinCAT solution file
Why do we need those two files? First of all, we need to be able to open the correct project to do the static code analysis at. Second, those two files provide all the information that makes it possible for us to select the correct version of Visual Studio and TwinCAT (by using the remote manager which I’ll come back to). The visual studio solution file has the extension .sln and the TwinCAT project solution file .tsproj. Note that the .tsproj is not the same PLC project files (which have the extension .plcproj). The tsproj-file is the container for everything in a TwinCAT project (including Motion, I/O, System, PLC and much more), and holds information on what version of TwinCAT the solution was created with and is thus what is interesting for us. Let’s start by writing the code for finding the visual studio solution file.
rem Find the visual studio solution file. for /r %%i in (*.sln) do ( SET VISUAL_STUDIO_SOLUTION_PATH="%%i" )
for /r iterates through all the files recursively in the current directory, which is what we want as this batch file will reside in the root directory of our visual studio solution which will also include the TwinCAT solution.
%%i is a loop variable and where our selection (*.sln) is stored if anything should be found.
If a file is found ending with .sln we store this in the variable
VISUAL_STUDIO_SOLUTION_PATH using the
Remember that you can at anytime write
help <command> (for example,
for help) in the Windows command prompt (cmd.exe) to get more information.
While we’re at it, let’s do the same for the TwinCAT solution file.
rem Find the TwinCAT solution file. FOR /r %%i IN (*.tsproj) DO ( SET TWINCAT_PROJECT_PATH="%%i" )
It would be nice to do some error checking on this to see whether the script found both of these files.
This is done using
IF NOT DEFINED <variable>.
If this is the case, we want to return the script with an error code.
We’ll want to check the existance of both files (*.sln and .tsproj), and if any of these is not found we’ll return.
If the file path is found, we’ll print the complete path to the console.
rem Error handling of finding the files. IF NOT DEFINED VISUAL_STUDIO_SOLUTION_PATH ( echo Visual studio solution file path does not exist! GOTO Exit ) ELSE ( echo VISUAL_STUDIO_SOLUTION_PATH found! echo The filepath to the visual studio solution file is: %VISUAL_STUDIO_SOLUTION_PATH% ) IF NOT DEFINED TWINCAT_PROJECT_PATH ( echo TwinCAT project file does not exist! GOTO Exit ) ELSE ( echo TWINCAT_PROJECT_PATH found! echo The filepath to the TwinCAT project file is: %TWINCAT_PROJECT_PATH% )
If any of these files are not found, the script will GOTO Exit, which we’ll define as:
:Exit echo Failed! EXIT /B 1
What we’re doing here is that we’re exiting the program and setting a system wide environment variable called
%errorlevel% to one.
By convention a return value of anything other than zero is considered a failure.
This return value is used by Jenkins to mark the build as a success or failure.
The final thing this batch file needs to do is to execute the C# program that will execute the static code analysis and provide it with the parameters that we’ve just collected. We also need to configure our batch file with where our C# program is, which I’ve called TcStaticAnalysisLoader.
rem Set the below variable TC_STATIC_ANALYSIS_LOADER_PATH to the complete path of rem where the executable TcStaticAnalysisLoader.exe resides. SET TC_STATIC_ANALYSIS_LOADER_PATH=C:\Program Files (x86)\TcSAL\TcStaticAnalysisLoader.exe rem Run the TwinCAT automation interface application IF EXIST "%TC_STATIC_ANALYSIS_LOADER_PATH%" ( "%TC_STATIC_ANALYSIS_LOADER_PATH%" -v %VisualStudioSolutionFilePath% -t %TwinCATProjectFilePath% ) ELSE ( echo The configured search path for TcStaticAnalysisLoader does not exist! GOTO Exit )
If the user has provided this script with a file path to the TcStaticAnalysisLoader executable that does not exist, we’ll do a error print and exit. With the above code we will have our C# program launched and provided with two arguments (-v and -t), for the Visual studio file path and TwinCAT project file path, both of which are needed for our next step.
Make sure to add the file to source control of your TwinCAT library project and push it to the repository. All sourcecode in this post is available on my GitHub.
That’s it for this post! Up to this point we have:
- An understanding of why we want to do continous integration/continous delivery
- A machine with Jenkins installed and configured
- A Jenkins job for the TwinCAT static code analysis
- A TwinCAT library project to do the static code analysis upon
- A windows batch file that is executed when a Git push is done, and which in turn starts execution of a program
Now there is only one thing missing – the program that will execute the static code analysis of our TwinCAT PLC project, and this is our goal and mission in the next and final post, so stay tuned!