Mar 4, 2010

Using Lint in Eclipse

 

What is Lint?

Lint is a tool intended to pick the nits out of your C/C++ code. You can think of it as an optimizing compiler with an attitude. It is a very useful code analysis tool. If you’ve programmed in C# and used ReSharper you can think of it as the code analysis portion of ReSharper on steroids. The version I am familiar with is PC-Lint by Gimpel. It is made to run under windows. Gimpel also makes FlexeLint which runs under many operating systems including Linux and Mac OS X.  PC-Lint even has  options to look for, and enforce the coding recommendations in Scott Meyer’s Effective C++ series. A few sample things a good lint will find include:
  • Identifying unused includes
  • Finding member methods that can be made static
  • Warning about loss of sign and precision in assignments
  • Recommending  when parameters should be made const references 
  • missing default constructors
  • destructors that should be virtual
  • “newed” items that aren’t deleted (i.e. Memory Leaks)
  • finding unreachable code (you probably have more than you think)
  • all the constructors that should have the explicit qualifier (you knew about explicit right?)
  • Initialization parameters that are out of order
  • … and a few hundred more.

If you find this article helpful check out my Pluralsight courses Eclipse Guided Tour – Part 1   and Eclipse Guided Tour – Part 2 - Until April 30, 2015 You can get an annual Pluralsight subscription for 40% OFF! in celebration of their 4,000th course being published.

Why don’t you use Lint?

There are several possible reasons. You’ve never heard of it.  It doesn’t come pre-integrated into your IDE. You don’t want to pay for it. You tried and it and got so many warnings it made your head hurt and you felt insulted and moved on. It was too hard to get it working. The intent of this post is to address most of these issues for those of you using Eclipse. You do still have to pay for it though. As a bonus for those that are doing embedded development for the NetBurner I’m including a .lnt file that suppresses a lot of spurious errors from the standard libraries. It’s nowhere near as seamless to use as a tool like ReSharper and it can take a while to get it set up and tweaked for your coding style but this is a one-time effort and the benefits will last a lifetime. You have probably already had many long debugging sessions finding a coding error that lint would have either found or prevented in the first place. If you consider yourself a professional C/C++ developer you should have very good reasons for NOT using a tool like lint.

Getting it Working with Eclipse

You want to start with External Tools Configuration… menu as shown in the diagram.
image
This will bring up the following dialog.
 image
This example uses Gimpel’s PC lint, but if you have a different tool the changes should be minor and obvious. 
  1. Click the icon to add a new configuration.
  2. Give it a name.
  3. Use the browse button to browse to your lint .exe file.
  4. Specify your working directory. There are multiple options here including using ${project_loc} but I’ve found that using ${container_loc} works the best for me.
  5. Add arguments for the command line invocation.
I use two .lnt configuration files. One named netburner.lnt contains the settings I want to be the same for all my netburner projects. The second one named project.lnt varies from project to project. You can see that I store netburner.lnt at a common location. The project.lnt file on the other hand is stored in the working directory of each project I want to lint. You can use any names you want for these files.
The first argument in step 5 tells lint the location of my project.lnt file. If you don't need or want a project specific lint file you can leave this argument off. In the second argument line you can see that I’m telling it to include netburner.lnt which is a .lnt file I have customized for the NetBurner development. You might use std.lnt here or any name you chose. The -u flag tells lint to only process the current file (unit) and the ${resource_Name} option tells it that the file to use is the current file.

image Once you’ve configured the tool you’ll want to add it to the tool menu as shown in the first image. Use that same menu and this time select the Organize Favorites… option, and in the resulting dialog click the Add button. Any new tool that isn’t in the menu will show up. In the image you can see I’ve added Test New Tool. Clicking the checkbox and pressing OK will add it to the dialog and the Up and Down buttons can be used to position it in the tools menu.
When you want to lint a file you make sure your the file you want to lint is active and select your newly added command from the menu. The console area will update with the results of the check. I like to modify the background of both my Run/Debug console and C++Build Consoles to different colors so I always know which output I’m looking at.

Output from Lint when nothing is wrong.

image

Setting up your *.lnt files

UPDATE: The information below on netburner.lnt  is now out of date. Gimpel recommends the use of co‑gcc.lnt now instead of co‑gnu3.lnt. The other information below on project.lnt is still relevant. Please see my updated lint post for complete examples of all the needed .lnt and .h files.

Gimpel supplies a lot of sample lnt files for a lot of development environments (see the lnt folder under your Lint installation directory), but they don’t have one for Eclipse and as you might imagine they don’t have one optimized to minimize NetBurner errors, but I do.

netburner.lnt

Here’s my netburner.lnt file which I leave in the root C:\Lint directory so it’s available for all projects. This is the file referenced on the second arguments lines in STEP 5 in the above image. Feel free to cut and paste this into your .lnt file.
//  Gnu C/C++ (version 2.95.3 or later), -si4 -sp4, 
//  Standard lint options
co-gnu3.lnt
-iC:\nburn\include
-iC:\nburn\gcc-m68k\m68k-elf\include
-iC:\nburn\gcc-m68k\m68k-elf\include\c++\4.2.1
-iC:\nburn\gcc-m68k\lib\gcc\m68k-elf\4.2.1\include
-iC:\nburn\gcc-m68k\m68k-elf\include\c++\4.2.1\m68k-elf
-iC:\nburn\MOD5272\include
//THESE COULD go in a project specific lnt file but since most of my
//NB projects share these problems I'm just putting them here
-esym(119,round)  //lint is seeing  as taking no params
-esym(119,abs)  //lint is seeing  as taking no params
-esym(119,sprintf)  //lint is seeing  as taking no params
-esym(119,printf)  //lint is seeing  as taking no params
-esym(119,iprintf)  //lint is seeing  as taking no params
-esym(119,strcpy)  //lint is seeing  as taking no params
-esym(119,strlen)  //lint is seeing  as taking no params
-esym(119,strncpy)  //lint is seeing  as taking no params
-esym(119,strcat)  //lint is seeing  as taking no params
-esym(119,strncat)  //lint is seeing  as taking no params
-esym(119,strtok)  //lint is seeing  as taking no params
+libclass(angle,foreign,ansi )
+libdir(C:\nburn\* )
//The repeated include file you might want to comment out. Itjust caused me a significant number
//of errors when I was starting with lnt and disabling it made it easier to concentrate on
//more serious issues.
-e537  //repeated include file
//-e747 //significant prototype coercion
-e534 //ignoring return value of function - doesnt handle cout correctly
-e716 // ignore while(true) or while(1) my preferred way of defining a forever loop
//if you like for (;;;) ugh:( don't use the above option)
//Coerce messages for Eclipse
-hF1
+ffn
//-"format=%(%f:%l:%C:%) %t %n: %m"
//or for shorter lines without the filename -- keep in mind that most solutions that allow you to double-click
//a lint error and jump right to the problem do require the filename.
-"format=%(%l:%C:%) %t %n: %m"
-frl
-width(0) 
+flm
-esym(652,BOOL) 
-esym(715,sParam)  //symbol not referenced
-esym(715,INVALID_ERR_MSG)  //symbol not referenced
-esym(715,pd)  //symbol not referenced
-esym(818,sParam)  //could be ptr to const
-esym(818,pd)  //could be ptr to const
-esym(714,AppName)
-esym(765,AppName)
-esym(714,UserMain)
-esym(765,UserMain)
-esym(766,NetworkDeb*)
-esym(755,NBGpioH)
-esym(758,str*)
-esym(1714,Scpi*)
//don't know why but lint thinks the following are unused
-esym(551, NError::TEMP_MSG_BUF_LEN) 
-esym(551, NOutputQueue::DFLT_QUEUE_SIZE)
-esym(551, SCPI_RESPONSE_BUF_LEN)
-esym(551, NState::MAX_SERIAL_NUM_LENGTH)
-esym(551, FIRMWARE_REV_MSG)
-esym(551, NOutputQueue::MAX_QUEUE_MSG_SIZE)
-esym(676, CTcpServer::_rxBuffer)
-e759 //move symbol from header to module
-e757 //lots of spurious not referenced vars for strings in ScpiCommandConstants.h
//Suppress errors from 3rd party JPA Scpi parser library
//
-e768
-e769
-esym(755,SCPI_*)
-esym(755,END_OF*)
-esym(755,C_NO_*)
-esym(755,MAX_UINT64_T)
-esym(526,SCPI_*) //ignore not define warnings from jPA scpi parser
+fie  //allow enum to int conversions
+fdi //look under current specified includes for other includes
-passes(2)
project.lnt

I also want to show you a sample project.lnt file. I prefer not to litter my code with lint comments to suppress errors so I tend to put them in a project file. Also on most projects I’m using includes from library projects I’ve written. I want lint to know about them so I give includes here. There are a couple of ways to do this. One is to hard code the path like:
  • -iC:\SomeProjectPath\FolderWithIncludes
Easy enough but fragile. Who wants to go back and edit project.lnt files just because you moved the location of the workspace. The slightly more complicated but less fragile was is to use environment variables. At first I wanted to use Eclipse’s variables in the include file. That is I wanted to do something like this:
  • -i${workspace_loc:/ProjectLib/src}  //never going to work
DosEnvVarsAfter banging my head against the wall for a while I realized that by the time the project.lnt file is processed lint is in control and it knows nothing about eclipse variables. It does know about DOS variables, so the key is to use the Environment tab under the External Tools Configuration dialog and set up a variable for each path you want to include. I start by using the  workspace_loc variable. There are tools in the edit box that will help you build the variables but the image shows you the proper format. The two variables shown in the image are just examples of the syntax, you'll have no need of the SyncorLibrary variable but it shows how to combine workspace_loc with additional subdirectories. The Workspace variable is useful by itself and may be all you need.  Now in the project.lnt file you can use the DOS variable character % to surround the variable name and have it expand automatically as shown in the code snippet below in the top two lines.  The first line does an include on the Boost libraries in my path. The second includes a path to a project called "someProject" in the eclipse workspace.

-i%BoostLib%
-i%Workspace%\someProject
//UnitTest++
//In unit testing code we take shortcuts we wouldn't take with normal code
//and UnitTest itself does some things we don't want to be warned about. 
//These really belong in a separate file like UnitTest.lnt so multiple projects can use them
-e717 //Unit Testing CHECK Macros use do while(0) construct.
-esym(1732, *Fixture)
-esym(1733, *Fixture)
-esym(1551, *Fixture)
-esym(1725, Suite*)
-esym(1704, Suite*)
-esym(1712, Suite*,*Fixture*)
-esym(1768, Suite*)
-esym(1502, UnitTest*)

Linting the Entire Project

All of the above steps allow you to lint a single file at a time. However, it’s also important to lint your entire project as it allows lint to find project wide errors. The steps are almost identical, you create a new entry, name it sometimagehing like Lint All and duplicate all the settings from Lint Current File, you just need to leave off the –u flag. Now when you run Lint All you need to be on a text file that contains the names of all the files you want to lint. If you keep all your files in a single folder this file can just contain the file names. If you use a src folder and subfolders you want to include relative paths as shown.


image 

Common things that go wrong

When linting a single file it easy to think you have an active current file when you really don’t. If you get the following error, just try clicking inside the source code of the file you want to lint and try again.


image 
If lint runs but gives you an error about a file it can’t open you need to do a little detective work. On new projects it easy to forget to create a project.lnt file and still use the Lint Current File option which is expecting one.


image  

Parsing The Errors

Due to some information in the comments (thanks Colin) I now have a workable solution for parsing the errors produced by lint so that they show up in the Problems tab and clicking them takes you to the correct line in the source. Please see the blog post Parsing Lint Errors in Eclipse.

Related Posts


Ten Tips for Eclipse Part 3
Parsing Lint Errors In Eclipse
Using Lint with GCC and NetBurner
Meet the New Workspace–Same as the Old ...
C++'s Most Misleading Compiler Option

About Me

My photo
Tod Gentille (@todgentille) is now a Curriculum Director for Pluralsight. He's been programming professionally since well before you were born and was a software consultant for most of his career. He's also a father, husband, drummer, and windsurfer. He wants to be a guitar player but he just hasn't got the chops for it.