Linting With Eclipse and the GNU ARM Embedded Launchpad Compiler
For mission critical software, the more information about potential bugs, the better. This article describes using PC-lint to perform analyis of an application destined for space.
Join the DZone community and get the full member experience.
Join For FreeFor a space project we have to make sure that things are not failing while our hardware orbits around Mother Earth. Therefore, we are using different static and dynamic analysis tools, and one of them is using PC-lint from Gimpel to catch as many errors and bugs as possible. For that project, we are using Eclipse with the GNU ARM Embedded (launchpad) ARM compiler and Eclipse as IDE with the GNU ARM Eclipse plugins. There are commercial plugins available for linting with Eclipse (e.g. Linticator), but with a few tweaks it is possible to lint with Eclipse free-of-charge. So this article is about how to lint an Eclipse project with PC-Lint.
Lint messages in Eclipse
PC-Lint
If you are serious about software development, you want to check your source code as much and as early as possible. A tool I have used for a very long time is PC-lint from Gimpel. It is not a free tool (costs around $390) but it has saved me countless hours so far. There are open source alternatives which I’m using in parallel, but PC-lint is still a kind of reference for me. For Linux users there is a version for that hosts the operating system too.
The challenge with fully using PC-lint is to make it aware of all the library include path and settings, plus to make it aware of all the compiler built-in defines to properly lint code with libraries. This post should help you to solve that challenge. :-)
PC-Lint and Eclipse
You might check out one of my early articles about how to lint with Eclipse without a plugin (see http://mcuoneclipse.com/2012/04/10/linting-without-a-plugin/). Since then, things on the Eclipse side has been changed a bit. This post has improved error handling and shows how to use it with the GNU ARM Embedded (launchpad) tools including properly including the libraries.
In the steps below I’m using the following tools:
- Eclipse Luna (Freescale (now NXP) Kinetis Design Studio V3.0.0) (Installed in C:\Freescale\KDS_3.0.0)
- GNU ARM Embedded (launchpad) 4.9 2015 q2
- GNU ARM Eclipse C/C++ plugins (1.13.1.201504061754)
- PC-lint v9.0 (installed in C:\Freescale\lint)
The approach I’m using is this:
- In a first step, create the proper lint configuration files to be used with co-gcc.lnt
- Create a new build configuration (e.g. ‘lint’) for the existing project to be linted
- In that build configuration, call a batch file to run lint
- The batch file will call lint with the proper operations and configuration files
- The list of files to be linted will be specified in a configuration files, specified manually
Lint Configuration Files for co-gcc.lnt
In my earlier linted projects, I have used co-gnu.lnt.
Lint uses .lnt files for options and configurations. Many configurations files are delivered with the lint installation in /lnt
The co-gnu.lnt is an older version and does not play well with newer gcc compilers. Instead, the co-gcc.lnt should be used which is located in the ‘lnt’ subfolder of the PC-lint installation:
/* Date Stamp */ -d"_lint_co_gcc_lnt=co-gcc.lnt modified 4-Jan-2012"
/* To document usage use: -message( "Using " _lint_co_gcc_lnt ) */
/* co-gcc.lnt: This is the seed file for configuring Lint for use with
GCC versions 2.95.3 and later.
Like all compiler options files this file is intended to be used
as follows:
lint co-gcc.lnt source-files-to-be-linted
Some of the information that co-gcc.lnt requires needs to be furnished
with the help of the gcc system itself. The easiest way to generate
this information is to use the makefile co-gcc.mak (supplied with the
Lint distribution) in an invocation of GNU Make; for details, see the
commentary at the top of co-gcc.mak.
*/
-cgnu // Notifies FlexeLint that gcc is being used.
// ===========================
// Preprocessor Configuration:
+fdi // GCC starts its #include search in the directory of the including
// file.
++fln // Allow:
// # digit-sequence " [s-char-sequence] " new-line
// as a synonym for:
// # line digit-sequence " [s-char-sequence] " new-line
// GCC additionally allows flag values to follow the
// s-char-sequence, but currently Lint ignores them.
-header(co-gcc.h) // Includes headers generated by GCC (bringing in
// predefined macros).
+libh(co-gcc.h) // Marks that header as library code.
gcc-include-path.lnt // This .lnt file should contain --i options
// and should be generated by invoking gcc with its '-v' option.
// (GCC's implicit #include search path is presented in the output.)
// This happens automatically when 'make -f co-gcc.mak' is invoked.
// Assertion directives (a feature of GCC's preprocessor) have been
// considered obsolete in GCC's documentation since version 3.0, so we do
// not use them here. If support for #assert is needed in the form of a
// lint option, one may use '-a#' like so:
// -a#machine(i386) // #assert's machine(i386) (SVR4 facility).
+cpp(.cc,.C) // extensions for C++ that are commonly used in addition
// to the default extensions of .cpp and .cxx
// =============
// Size Options:
// +fwc // wchar_t might be builtin; if so, uncomment this option. (NOTE:
// // this option needs to be set before a size option is given for
// // wchar_t; see the documentation for -sw# in the Lint manual.)
size-options.lnt // This .lnt file should be generated (preferrably
// by a program created by invoking GCC with the compile options that
// are used in the compilation of the project to be linted). This
// happens automatically when 'make -f co-gcc.mak' is invoked.
// ===========================================
// +rw and -d options to cope with GNU syntax:
+ppw(ident) // Tolerate #ident
+ppw(warning)
// GCC provides alternative spellings of certain keywords:
-rw_asgn(__inline,inline)
-rw_asgn(__inline__,inline)
-rw_asgn(__signed__,signed)
-rw_asgn(__signed,signed)
-rw_asgn( __volatile__, volatile )
-rw_asgn( __volatile, volatile )
++d__const=const // gconv.h uses __const rather than const
++dconst=const // ensure const expands to const.
-rw_asgn( asm, _up_to_brackets )
-rw_asgn( __asm, _up_to_brackets )
-rw_asgn( __asm__, _up_to_brackets )
// This re-definition of the various spellings of the asm keyword enables
// Lint to pass gracefully over expression-statements like:
// __asm __volatile ("fsqrt" : "=t" (__result) : "0" (__x));
// But it may be necessary to suppress certain error messages that are
// triggered by tokens that are part of an assembly declaration or
// statement. For example:
-d"__asm__(p...)=/*lint -e{19}*/ __asm__(p)"
// ...causes Lint to be quiet about the semicolon that follows an
// __asm__() declaration. Note, the -e{N} form of suppression takes
// effect only for the forward-declaration, definition or
// [possibly-compound] statement that immediately follows. Because a
// semicolon is seen as a declaration-terminator, Error 19 will be
// re-enabled immediately after the semicolon in '__asm__(...);'.
// (The elipsis after the macro parameter p allows zero or more commas to
// appear in the operand.)
//
// If you encounter other diagnostics that appear to need suppression in
// or near assembly regions, please let us know!
//
-esym(123,__asm__)
-rw_asgn(__alignof__,__alignof)
// "__extension__" is GCC's way of allowing the use of non-standard
// constructs in a strict Standard-conforming mode. We don't currently
// have explicit support for it, but we can use local suppressions. For
// example, we can use -e(160) so that we will not see any Errors about
// GNU statement-expressions wrapped in __extension__().
++d"__extension__=/*lint -e(160) */"
++d__builtin_va_list=void* // used by stdarg.h
++d__builtin_stdarg_start()=_to_semi // ditto
++d__builtin_va_end()=_to_semi // ditto
++d"__builtin_va_arg(a,b)=(*( (b *) ( ((a) += sizeof(b)) - sizeof(b) )))"
++d__null=0
+rw(_to_semi) // needed for the two macros above.
+rw(__typeof__) // activate __typeof__ keyword
-d__typeof=__typeof__ // an alternative to using __typeof__
+rw( __restrict )
+rw( __restrict__ )
-rw(__except) // This MS reserved word is used as an identifier
+rw( __complex__, __real__, __imag__ ) // reserved words that can be ignored.
++d__builtin_strchr=(char*) // permits the inline definition ...
++d__builtin_strpbrk=(char*) // of these functions to be linted ...
++d__builtin_strrchr=(char*) // without drawing a complaint
++d__builtin_strstr=(char*) // about the use of a non-standard name
++d__PRETTY_FUNCTION__=___function___ // lint defines ___function___ internally
++d__FUNCTION__=___function___ // lint defines ___function___ internally
++d__func__=___function___ // Some C++ modes suport the implicit __func__
// identifier.
// =========================================================
// Other options supporting GNU C/C++ syntax:
+fld // enables the processing of _L_abel _D_esignators E.g.:
// union { double d; int i; } u = { d: 3.141 };
// =========================================================
// Generally useful suppressions:
-wlib(1) // sets the warning level within library headers to 1
// (no warnings, just syntax errors). Comment out if you
// are actually linting library headers.
-elib(123) // 123 is really a warning, but it's in the "Error" range.
-elib(93) // allow newlines within quoted string arguments to macros
-elib(46) // allow bit fields to have integral types other than
// '_Bool' and 'int'.
-elibsym(628) // Suppress 628 for __builtin symbols.
-esym(528,__huge_val,__nan,__qnan,__qnanf,__snan,__snanf)
// We don't care if we don't reference some GNU functions
-esym(528,__gnu_malloc,__gnu_calloc)
// The following functions exhibit variable return modes.
// That is, they may equally-usefully be called for a value
// as called just for their effects. Accordingly we inhibit
// Warning 534 for these functions.
// Feel free to add to or subtract from this list.
-esym(534,close,creat,fclose,fprintf,fputc)
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
-esym(534,strncat,strncpy,unlink,write)
// For non-ANSI compilers we suppress messages 515 and 516
// for functions known to have variable argument lists.
// For ANSI compilers, header files should take care of this.
-esym(515,fprintf,printf,sprintf,fscanf,scanf,sscanf)
-esym(516,fprintf,printf,sprintf,fscanf,scanf,sscanf)
-esym(1702,*operator<<,*operator>>)
-esym(534,*operator<<,*operator>>)
-esym(1055,*__builtin*)
-esym(718,*__builtin*) // The compiler does not need these ...
-esym(746,*__builtin*) // declared and it knows their prototypes.
However, as every gcc might have different settings, this co-gcc.lnt requires several extra generated files:
- gcc-include-path.lnt: list of include paths to find the library headers.
- size-options.lnt: standard type sizes.
- lint_cmac.h and lint-cppmac.h: header files with all compiler predefined C and C++ defines, used by co-gcc.h.
As both files depend on the compiler installation path and compiler options, these files are not part of the PC-lint installation. Instead, they have to be created.
In the next sections I describe how to create these to files. You might skip the creation steps and directly use and adopt my generated files instead.
co-gcc.mak
To create these files, there is a make file (co-gcc-mak) inside the \lnt folder. It uses the GNU compiler itself to create these files. This is a very smart way to do this, however it does not work well for embedded cross compilers (will see later). The make file
The make file depends on several tools which need to be installed and present in the PATH:
- GNU awk: http://gnuwin32.sourceforge.net/packages/gawk.htm
- GNU make: e.g. from https://sourceforge.net/projects/gnuarmeclipse/files/Build%20Tools/
- GNU core utilities (touch, rm, …): http://gnuwin32.sourceforge.net/packages/coreutils.htm
- GNU compiler toolchain with gcc and g++ (GNU ARM Embedded (launchpad))
I had to run the setup version of the GNU core utilities, as otherwise the tools reported some missing DLL files on Windows :-(.
The make file will create the following files (see <lint-installation-path>\lnt\gcc-readme.txt):
- lint_cmac.h
- lint_cppmac.h
- gcc-include-path.lnt
- size-options.lnt
The size-options.lint file shall be created with a small executable (that step will fail, we will see).
To simplify running the make file, and in order not to change my global PATH variable, I have created the following batch file co_gcc.bat inside <lint-installation-path>\lnt:
@REM make sure that make, awk, gcc, g++, touch are in PATH
@REM Path to make
SET MAKE_PATH=C:\Freescale\KDS_3.0.0\bin
@REM Path to GNU awk
SET AWK_PATH=C:\GNU\gawk-3.1.6-1\bin
@REM Path to GNU core utilities (touch)
SET CORE_PATH=C:\Program Files (x86)\GnuWin32\bin
@REM Path to GNU ARM Embedded
SET GNU_PATH=C:\Freescale\KDS_3.0.0\toolchain\bin
@REM append GNU path to PATH
SET PATH=%PATH%;%MAKE_PATH%;%GNU_PATH%;%AWK_PATH%;%CORE_PATH%
@REM call make file
make -f co-gcc.mak GCC_BIN=arm-none-eabi-gcc GXX_BIN=arm-none-eabi-g++
@REM note that the last step will fail (to link and execute the file for the type sizes). This is expected.
You will need to adopt the path settings to match make, awk, gnu core utilities, and GNU gcc installation on your system.
The other consideration is that the gcc called with that make file should match the compiler settings used in the Eclipse project to be linted, as the .lnt files produced need to match the compiler settings used.
In the last step, it calls the make utility. On my system, the output is as below:
C:\Freescale\lint\lnt>co_gcc.bat
C:\Freescale\lint\lnt>SET MAKE_PATH=C:\Freescale\KDS_3.0.0\bin
C:\Freescale\lint\lnt>SET AWK_PATH=C:\GNU\gawk-3.1.6-1\bin
C:\Freescale\lint\lnt>SET CORE_PATH=C:\Program Files (x86)\GnuWin32\bin
C:\Freescale\lint\lnt>SET GNU_PATH=C:\Freescale\KDS_3.0.0\toolchain\bin
C:\Freescale\lint\lnt>make -f co-gcc.mak GCC_BIN=arm-none-eabi-gcc GXX_BIN=arm-n
one-eabi-g++
rm -f \
lint_cppmac.h \
lint_cmac.h \
gcc-include-path.lnt \
size-options.lnt
rm -f co-gcc.mak.temp-empty*
touch co-gcc.mak.temp-empty.cpp co-gcc.mak.temp-empty.c
arm-none-eabi-gcc -Wno-long-long -E -dM co-gcc.mak.temp-empty.c -o lint_cma
c.h
arm-none-eabi-g++ -Wno-long-long -E -dM co-gcc.mak.temp-empty.cpp -o lint_cpp
mac.h
arm-none-eabi-g++ -Wno-long-long -v -c co-gcc.mak.temp-empty.cpp 2>&1 \
| awk ' \
BEGIN {S=0} \
/search starts here:/ {S=1;next;} \
S >> /Library\/Frameworks/ {next;} \
S >> /^ / { \
sub("^ ",""); \
gsub("//*","/"); \
sub("\xd$",""); \
sub("/$",""); \
printf("--i\"%s\"\n", $0); \
next; \
} \
S {exit;} \
' >gcc-include-path.lnt
rm -f co-gcc.mak.temp-generate-size-options*
arm-none-eabi-g++ -Wno-long-long co-gcc.mak.temp-generate-size-options.cc -o
co-gcc.mak.temp-generate-size-options
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-abort.o): In function `abort':
abort.c:(.text.abort+0x10): undefined reference to `_exit'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-signalr.o): In function `_kill_r':
signalr.c:(.text._kill_r+0x1c): undefined reference to `_kill'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-signalr.o): In function `_getpid_r':
signalr.c:(.text._getpid_r+0x4): undefined reference to `_getpid'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x20): undefined reference to `_write'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0x18): undefined reference to `_close'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek'
c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../
arm-none-eabi/lib\libc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x20): undefined reference to `_read'
collect2.exe: error: ld returned 1 exit status
co-gcc.mak:132: recipe for target 'sizes' failed
make: *** [sizes] Error 1
C:\Freescale\lint\lnt>
Notice that it fails in the last step to build an executable to be executed. This is expected to fail for a cross-compilation toolchain (we build on the host, but execute on an embedded ARM processor on another board). But the three other files have been generated:
generated files by co_gcc.bat
size-options.lnt
This failing last step is supposed to create the size-options.lnt file with this code:
\
extern "C" int printf(const char*, ...);\
int main() {\
printf( "-ss%u ", sizeof(short) );\
printf( "-si%u ", sizeof(int) );\
printf( "-sl%u ", sizeof(long) );\
printf( "-sll%u ", sizeof(long long) );\
printf( "-sf%u ", sizeof(float) );\
printf( "-sd%u ", sizeof(double) );\
printf( "-sld%u ", sizeof(long double) );\
printf( "-sp%u ", sizeof(void*) );\
printf( "-sw%u ", sizeof(wchar_t) );\
}
With some basic knowledge about the type sizes used by the compiler, I can create that size-options.lnt file by hand as below. It tells lint with the -s option about the size of the different standard types:
// size_options.lnt
// type sizes
-ss2 // short
-si4 // int
-sl4 // long
-sll4 // long long
-sf4 // float
-sd8 // double
-sld8 // long double
-sp4 // void*
-sw4 // wchar_t
gcc-include-path.lnt
What it has sucessfully created is the gcc-include-path.lnt: It tells lint where to find all the GNU library include files
// gcc-include-path.lnt
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/include/c++/4.9.3"
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/include/c++/4.9.3/arm-none-eabi"
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/include/c++/4.9.3/backward"
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/include"
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/include-fixed"
--i"c:\freescale\kds_3.0.0\toolchain\bin\../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/include"
You can take above template and easily adopt to your compiler version and installation path.
lint_cmac.h and lint_cppmac.h
The generated lint_cmac.h and lint_cppmac.h contain all the predefined macros of the gcc compiler.
I have posted my files on GitHub here: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-K64F120M/FRDM-K64F_pc-lint/lint
Below is an example of lint_cmac.h:
Linting With Eclipse
To lint a project with Eclipse, I recommend to create a local "lint" folder and place all needed files into it:
see my project on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-K64F120M/FRDM-K64F_pc-lint
lint configuration files inside project
lint_cmac.h, lint_cppmac.h, gcc-include-path.lnt and size-options.lnt are the files from the previous step.
do_lint.bat and Related Files
do_lint.bat is a batch file I will call from the build configuration (later more about this):
@rem call this batch file from the Eclipse project settings
@rem The arguments for this batch file:
@rem %1: The path to the project root folder
@rem ------------------------------------------------------
@rem Path to the project folder
SET PROJ_PATH=%1
@rem Path to lint-nt.exe (NO SPACES!!!)
SET LINT_EXE=C:\Freescale\lint\lint-nt.exe
@rem Path to my lint configuration files
SET LOCAL_LNT_FILES=C:\Freescale\lint\lnt
@rem Path to my local lint folder inside the project with the lint files
SET PROJ_LINT_PATH=%PROJ_PATH%\lint
@rem Lint configuration files and includes
SET LNT_INCLUDES=-i"%PROJ_LINT_PATH%" -i%LOCAL_LNT_FILES%
@rem --------------- Run PC-lint ---------------------------
%LINT_EXE% %LNT_INCLUDES% %PROJ_LINT_PATH%\eclipse_msg.lnt %PROJ_LINT_PATH%\proj_options.lnt %PROJ_LINT_PATH%\proj_files.lnt -vf
It configures the path/tool settings and then it calls the PC-lint executables. It needs the following files which are explained below:
- eclipse_msg.lnt: this configures the messages so the Eclipse Problems view can parse it
- proj_options.lnt: has the project specific options used e.g. to disable/enable warnings/errors
- proj_files.lnt: has the source files to be linted
In eclipse_msg.lnt the message format is defined:
// Configure PC-lint messages so they show up in the Eclipse 'Problems' view
-hF1
+ffn
// Normally my format is defined as follows:
//-"format=%(\q%f\q %l %C%) %t %n: %m"
// For eclipse-usage, the GCC error format is necessary,
// since we have only the default eclipse error parser available.
-"format=%(%f:%l:%C:%) %t: [%n] %m"
// Enable warning 831 if you are interested.
-frl
// Do not break lines
-width(0)
// And make sure no foreign includes change the format
+flm
In proj_options.lnt it uses the co-gcc.lnt as configuration files. Additionally list here all your include paths of the project sources, plus any other options (e.g. to inhibit messages):
-fff
// Include standard GNU options
co-gcc.lnt
// Include paths used
-i%PROJ_PATH%\Includes
-i%PROJ_PATH%\Sources
// inhibit messages for Processor Expert libraries
-elib(19, 10)
-e766
+libh(Events.h, Cpu.h)
In proj_files.lnt I list all the source files to be linted:
%PROJ_PATH%\Sources\test.c
%PROJ_PATH%\Sources\main.c
I was thinking about an extra step to generate the list of files automatically. But at the end it was simpler and easier to maintain that list by hand, and I can simply comment lines to only do a partial lint run.
Eclipse Build Configuration
To lint a project in Eclipse, I create a new build configuration for it. I select the project in the Project Explorer view and use the menu Project > Build Configuration > Manage to create a new configuration with the ‘New’ button:
New Configuration to Lint
Then change the newly created configuration (lint in my case), deselect 'Use default build command', deselect 'Generate Makefiles automatically', and enter the following build command to launch the batch file:
${ProjDirPath}\lint\do_lint.bat "${ProjDirPath}"
Build Command for PC-Lint
With that build command I’m calling the batch file (do_lint.bat) from the previous step. As argument I pass the project path to it with the Eclipse $ProjDirPath variable.
Now I can lint (aka compile) the project with that build configuration:
Linting Project
And it will show all the lint messages in the Eclipse problem view:
Lint messages in Eclipse
That’s it. :-). Everything else will depend on your project: add new files to be linted, adopt the settings, and happy linting. :-)
Summary
Linting project files is a valuable way for me to increase software quality (lint early and often). I have been deliquent for a while not doing it often recently, but that space project reminded me to start this good habit again, even if it takes some time to do it. To use lint with Eclipse projects is not straight-forward at the beginning, but with some infrastructure and getting used to it, it is very easy. And I hope this article motivates others to use lint more. PC-lint is not free, but it might be very worthwile. Otherwise I hope the above setup can help as well with other similiar tools.
Published at DZone with permission of Erich Styger, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments