Link to home
Start Free TrialLog in
Avatar of miv
miv

asked on

Finding unused units in Delphi

I need a tool to find unused units in the uses clauses of a large Delphi 4 app. I have all the source.

I have tried SourceCoder, but without luck.
Avatar of Alisher_N
Alisher_N

I think Delphi removes unused entries by itself...

why do you think there is something extra in the list ?
Yeah i agree, what would be nice is if the compilers would just take buts out of the units and not the whole lot..... (i may be wrong?)
unit consists of:

1)public variables declared in units
2)public functions & procs
3)init part
4)local variables
5)local functions & procs

if you use at least one function from unit Delphi includes to your project
1) 3) and ONLY functions you actually use

if you don't use any functions - nothing nothing included (it makes no sence)

Avatar of miv

ASKER

Alisher_N:

This is a 400.000 line project, with apx. 1000 units and there is no "visual programming" (RAD) and therefore no dfm files involved.

The least of my problems is the Delphi units...which is not even added automaticly when you create everything at run-time and not at design time.
it doesn't matter if they 'native' Delphi units or you own - it is checking aall your 1000 units and removes unsed code or whole unit from project... I am not quite sure what is exactly your problem then.
hello,
what about that beta stuff:
The current version (0.0.1.5) only takes care of unit interfaces
http://www.multimania.com/vincentmahon/out.htm

Maybe you can give it a try ?
....
What are you trying to achieve?

a:Kick out the unused units from the project?
b:Reduce the Uses clauses in all units to the minimum needed?
c:Both?

Do all the Uses clauses in the whole project look like the include unneccessary references?

Did I understand you right: the whole project consists only of *.pas files?

Thomas
Can't you write a program to get a directory listing of all .pas files in your project's location, then write some code to parse all of these files for the key word 'uses' (up until the ';'), and compares these filenames with those in the file listing...  Any that remain unmatched in the file listing, are unused...

Well, might be unused at least...

Tim.
Listening...
Avatar of miv

ASKER

jeurk: The OUT tool is exactly what I need. But the beta is not working...you´ll get the points, if Vince can fixe the errors :-)

xsoft: Both, yes, yes (expect for some res files).

AttarSoftware: Not a solution. If that was what i wanted, i could just remove all dcu files and build the project. The files with no dcu twin afterwards would be unused.

I've asked him for sources.
I'll tell you when I get something.
Ahhhh, I see you problem now :O)

Please excuse me :O)

Tim.
Avatar of miv

ASKER

Adjusted points from 500 to 666
Listening...
Maybe you should take a look at:
www.delphicase.com/

ModelMaker 5 - the Borland Delphi Productivity / CASE tool

(Concerning the size of your project it seems that a Case tool could be helpful anyway.)
This case tool also includes a Unit dependency analyser that you can use as an independent tool.

On the page www.delphicase.com/Tips.htm they describe the tool like this.

"Unit dependency analyser
In main menu Tools|Uunit Dependencies you'll find the unit dependency analyser. This allows you to analyse uses relations and dependencies (inverse uses relations). Inputs for the analyser are: a searchpath (top left list) and a set of 'root files'. The root files are the top-level heirarchy files that you want to analyse. The analyser scannes all root files and the files they contain in the interface 'uses' and implementation 'uses' sections. Root files can be a single .dpr or all files in directory such as all files in Delphi\VCL\Source. The use of root files gives the flexibility to analyse not only dpr's but also a set of units. Building the search path and the roots is done most conviniently by drag-drop from the windows- (NT) explorer.

After the search path and root files have been defined and the 'analyse' button has been clicked, a list of all scanned units is displayed in which a unit can be selected for analyses. This list may be filtered for 'found files only' which omits nay files which were not found on the search path, or 'selected directory only' which displays only thoses files found in the directory selected in the searchpath list.

On the right there is a tabbed notebook which shows the uses and dependencies trees. These trees contain the main analyses information. Different bitmaps in the trees show whether a unit is used in the interface or implementation section of a unit. Left from the trees a list shows all units (indirectly) used by the analysed unit.

The unit analyser is an independent tool which has no relations with other parts of ModelMaker."

I am not using this tool at the moment (but I might be soon...) so I cannot tell you how the analyzer works. But you can download a trial version with which you should be able to find out.
As I read by someone else in the newsgroups (borland.public.delphi.oodesign) the respond quite fast to questions and to suggestions from users and I think also from potential users so I would imagine, that this link would point you in the right direction.

Thomas
Listening
Avatar of miv

ASKER

xsoft: ModelMaker seems like a nice tool and it can analyze our unit structure.
But it can´t tell me which units in the uses clause are unneccesary...
I´ll contact the creators and check if they have a solution.

thanks for the help so far,
  Michael
Avatar of miv

ASKER

Answer from the ModelMaker guys:
(Fast support! :-)

"ModelMaker has a unit dependency analyzer which will: -1- scan units "uses"
clauses and display them in depedency and uses trees, and -2- instantly
visualize these trees (from mm5.16 onwards)

ModelMaker will not do full parsing of code to see which units are actually
referenced which is needed for your question.

Gerrit Beuze
ModelMaker
"

Too bad...anybody else has any suggestions?
Avatar of miv

ASKER

Adjusted points from 666 to 1000
For that amount of points.
I'll try to write you something if I get some time... This is hard stuff my friend...It won't be easy...but we'll see.

Is someone in that thread near from a working solution ?

John.
Perhaps there's some information in the debuginfo...
I don't know if this helps you now, but when I work on a major project with a lot of units, I comment the 'uses' line with each unit.

Sometimes I only use one function out of a whole unit so I just list the function in a comment next to the listed unit.

uses
  SysUtils,  // Now
  MyUnit1,   // MyFunction1
  MyUnit2,   // To display about box
  MyUnit3;   // Etc.

This way if anything ever gets removed, you can look at the uses clause to remove the unit that it belonged too.

Hope this helps in your future projects.  Sorry it isn't much help to you now.
Miv...
Would you give me an adress where I can
write you when I come up with something ? Some Day ?
Because this may take longer then the time the question lasts...
CU
Avatar of miv

ASKER

Sure: miv_world@hotmail.com

Good luck!
OK - here is how to do it, it requires writing a simple program, which I do not at the present have time to write - but it is very simple. Here are the steps:


1. Turn Map File to Detailed in Linker Options
2. Build the app (Use Buil all option)
3. Write simple Delphi routine to parse .MAP file which looks for lines that look like this:

Line numbers for Consts(Consts.pas) segment .text

You can just check for a line starting with "Line numbers for" and parse out the file name.

Add each filename to a string list.
4.  Write another routine to rename all pascal source files not in the list created in step 3 so that they have a leading underscore (eg: fred.pas --> _fred.pas if fred.pas is not in the lsit)

5. Build the application again. The compiler will now obligingly stop at each unit in the uses clause which had no code included from it in the resulting executable.

Yes step 5 may be tedious - but use of a simple batch replace utility like breplace.exe (from DSP?) will allow you to remove all instances of each offending unit in all the files in a single step. And you only need to do it once (or at least very seldom...)

Cheers,

Raymond.
Avatar of miv

ASKER

Seems like a solution which could work...but I need a working program!

I don´t have the time to write it myself at the moment, so I´ll open the Q for other answers.

Thanks for the effort so far.

  Michael
whooohooooooooooo @1000 points......
ASKER CERTIFIED SOLUTION
Avatar of rwilson032697
rwilson032697

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
miv: Have you tried the program?

Cheers,

Raymond.
Avatar of miv

ASKER

Not yet, on vacation at the moment.
I´ll do it as soon as possible.

  Michael
No problem - have a great holiday!

Cheers,

Raymond.
Your stuff is working Raymond...
But it's only handling the files of the current project.
It would be cool to also be able to tell all the unit names that are included in the units and that are no longer needed.
Like components units, etc...
But I agree, it's not hard to do...
CU all...
Well, it already does this. This loop:

      for I := 0 to Files.Items.Count - 1 do
        if FileNames.IndexOf(Files.Items[I]) = -1 then
          RenameFile(Files.Items[I], '_'+Files.Items[I]);

is running through all the unused units by filename. The unit name as used in the uses clause may be retrieved like this:

AUnitName := ChangeFileExt(ExtractFileName(Files.Items[I]), '');
 
Cheers,

Raymond.

I agree,
I mean that it will only remove the units no longer used in the project (only those in the current dur?).
But let's say someday you used the rxdbgrid... This will add the rxgrids to your uses clausule. Let's say someday you change for gxdbgrid and you forget to remove the rxgrids clausule.
Then I think that your routine will not be able in that state to say that I should remove the rxgrids from the uses clausule in the xxxx.pas unit.
Is it ? I'm not sure...
And for example, if you use the rxgrids units in some of your projects units...
If someday you remove the rxdbgrid from most of your forms but not all...
Will your routine say, which units no longer need to include the rxdbgrids unit ?
It's only things I'm asking myself, ok ?
It's not that I contest your answer...That's not my goal ;)

Regards...
I see what you mean.

Yes, the code does assume all the source you are using is in a single location (which is a little idealistic - the app I am working on has no fewer than 20 folders containing source compiled into the app). However, it could be modified to search a path list to retrieve all files on the set of paths, or you could temporarily point your source control working directories to a single location while doing this excercise.

As long as the code can find the source in the given location it will identify unused units, whether thay are the likes of rxdbgrid or something else. Another useful enhacement might to be cater for components released only as DCUs - but then you would get bitten by those released only as .BPLs.

This code won't say which units use other units that are not used any more. It will say which units are no longer used. Grep is a much more effective tool for this!

Cheers,

Raymond.