Static Analysis is a deprecated feature.
Static Analysis is not supported on OS X* systems.
If it is difficult to modify your build process to create a new build configuration, then you may need to create a build specification instead.
A build specification file is a summary that details how your application is built. In particular, it summarizes the steps needed to perform static analysis and specifies the files to process and the compilation options to use. It also describes the pseudo object modules that must be linked to generate the analysis results and the librarian invocations that are needed to combine those pseudo object modules into static link libraries.
The Intel® C++ Compiler provides utility programs to create and execute build specifications. Invoke any of these utilities with the -help
switch to get a usage message or with the -version
switch to identify the version.
Creating a Build Specification File
There are several ways to create a build specification. They are described here in order of convenience.
- Run your normal (debug) build under the injection utility.
The injection utility launches your build command as a child process, intercepts process creations, and generates a build specification file. Each time it sees an invocation of the compiler, librarian, or linker, it captures the command options and adds a corresponding command to the build specification file. Run the utility, as shown in the following:
inspxe-inject -save-spec <output build spec> -- <build command>
For example:
inspxe-inject -save-spec buildapp_sca.spec -- make debug
The injection utility automatically recognizes the following four compilers: the Intel® C++ Compiler, the Intel® Fortran Compiler, the Microsoft* Visual C++* compiler, and the GNU* C++ compiler. The injection utility will not operate correctly if your build procedure invokes a compiler, librarian, or linker on another computer.
Note
If your build procedure compiles or links files that are not part of your application, the resulting build specification file will also analyze those files. If you cannot avoid compiling unrelated source files during your build, edit the build specification file with a text editor to eliminate the unwanted compilation and link steps.
Modify your build procedure to "wrap" each compilation, librarian, and linker step, then execute the modified build.
The wrapper utility provides direct control over the construction of the build specification. Each time you invoke the wrapper utility, it adds one line to the build specification. When you supply a command line as the argument to the wrapper, the wrapper appends a corresponding line to the build specification. It then optionally executes the command.
In some sense, the wrapper utility is like the injection utility except in the way that build actions are collected. The injection utility observes the actions that are invoked as sub-processes of your build script. The wrapper utility also "observes" the actions you tell it to observe with command line arguments. The actions themselves may or may not actually happen.
The most basic approach is to modify your build script to replace every compiler, library, or linker command with a corresponding command that invokes the wrapper. (You may have to capture additional commands, too, such as directory change commands and file copy commands.) Assuming the
-no-run
option is not supplied, executing the wrapped command will, in turn, execute the command itself in exactly the same way. This means that this transformation cannot break your build script. However, running your build script will, as a side effect, create a build specification. This approach works for any kind of scripting language, such as makefiles, shell scripts, ant scripts and so on.You can modify this basic approach in two ways. First, you can select certain commands to not be wrapped. This allows you to selectively exclude actions from the build specification. Alternatively, you can add additional wrapper invocations (using the
-no-run
option) to selectively add commands to the build specification that would not otherwise be captured. Some examples may make this clearer.Suppose your build uses a utility program called
remote_shell
to invoke a command on a remote machine. Actions performed in this way would be invisible to the injection utility. The utility uses, as its first argument, the remote machine name; the other arguments form the command to be executed remotely. Your build script might contain a line like this:remote_shell host1 gcc <args> file1.c
You could insert an additional line as follows:
inspxe-wrap -no-run -save-spec buildapp_sca.spec -- gcc <args> file1.c remote_shell host1 gcc <args> file1.c
This tells the wrap utility to record the fact that file1.c is being compiled with the indicated arguments. The
-no-run
option tells inspxe-wrap not to actually invoke gcc. The original command remains as it was (unwrapped) and will execute as usual. Note that wrapping theremote_shell
command itself would not work, because the wrapper utility does not recognize theremote_shell
command as a compiler invocation. In fact, this technique can be used to transform any command that is not recognized by the wrapper utility into one that is recognized: simply insert a wrapper call that wraps the recognized form (in this call, the call to gcc*).Sometimes a build script will build a utility program and execute that utility to generate additional source files that are later compiled into the real application. You might not want to run static analysis on the utility program. (After all, it is not part of your real product.) By selectively omitting the wrapper calls on build steps for the utility program, you effectively exclude the utility program from the build specification.
Probably the most challenging case is where your application is built by some kind of opaque program that does not expose the commands it will execute in any text form. In this case, you have no commands to wrap. However, in this case, you may be able to capture a log that shows what commands were executed and with what options. You can then transform this log using a text editor into a series of commands that will, when run, repeat the build. By replacing each command with a wrapper invocation, you can produce a script that, when run, produces a build specification.
Syntax
inspxe-wrap -save-spec <output build spec> [-no-run] -- <command>
inspxe-wrap -save-spec buildapp_sca.spec -- icl $(CFLAGS) file1.c
Note
The actions created by your instrumented build will be appended to the previous contents of the build specification. Therefore, before you execute your modified build, you should delete the output build specification file.
Dealing with Multiple Projects, Multiple Configurations, and Shared Code
Your development team may use a master build script that builds several projects or several configurations of the same project. For example, a build script might compile and link the debug and release versions of several different applications.
Running a build script like this under the injection utility (or after instrumentation with the wrap utility) will generate a single build specification that, when executed, scans everything that was built. This is inconvenient because it does not allow you to scan one project by itself. Also, it may not be useful to scan more than one configuration of the same program, as all configurations of the same project generally contain the same defects.
If your master build script supports the capability to build only a single configuration of a single project, then you should use this to create a separate build specification file for each project. This still gives you the ability to scan individual projects; you can then write a script that scans all the projects.
Sometimes common source files or libraries are built into multiple projects. In these cases, there is often considerable overlap in analysis results. That is, defects in shared files tend to appear in every project that uses that file. It is possible that a defect in a common file will be detected in some project contexts and not in others. To cover this possibility, you may want to analyze the results for that file in every project. You will need to decide if the additional coverage is worth the effort.
It may want to choose one primary project where the analysis results for a shared file will be investigated. (For a library, the natural choice is the analysis results for the library itself.) For extra coverage, you can compare the results of analyzing the primary project with the results of investigating another project to see if any new problems in the shared file were discovered.
Using the Build Specification File
Once you have created a build specification, you can use it to perform static analysis. Remember to update your build specification each time a file is added or removed from the project or when compilation options change. Otherwise, full analysis of your entire application will not occur.
To perform static analysis from a build specification, use the following command line utility.
inspxe-runsc -spec-file <build spec> [<options>]
<options>
represents additional options to be passed to the compilation (and link) steps.
Build Specification Utility Options
Option | Result |
---|---|
-?, -h, -help | Describes command line options. |
| Disables warning with specified id. |
| Enables warning with specified id. |
| Specifies level of static analysis (default = 3). |
| Specifies directory where information is logged. |
-no-return-app-exitcode | Sets the return code based on success of the tool, not the underlying result (default for inspxe-inject). |
| Specifies the file containing command line options. |
-q, -quiet | Suppresses non-essential messages. |
| Specifies the directory where analysis results are created (inspxe-runsc only). |
-return-app-exitcode | Sets the return code based on success of underlying operation, not the tool (default for inspxe-wrap and inspxe-runsc). |
| Specifies the file containing build specification (inspxe-wrap and inspxe-inject only). The wrap utility appends to this file; the injection utility overwrites this file. |
| Specifies the directory where temporary files are created. |
-v, -verbose | Prints additional information. |
-V, -version | Displays the version number of the utility. |
A user error in usage, such as an invalid command line option, causes a return code of '1'. An error in the tool itself causes a return code of '2'. In addition, the following rules apply:
- inspxe-wrap returns the return code of the wrapped command.
- inspxe-runsc returns '0' if the analysis results are complete and '4' if an error occurred that prevented complete analysis.
- inspxe-inject returns '0'.
Adding the -return-app-exitcode to the inspxe-inject command line causes the inspxe-inject utility to return the return code of the observed build command. This is recommended if the build command return code is a reliable indicator of whether the actions recorded in the build specification are complete and correct.
If no options are specified, the option to enable level 3 static analysis is added by default.