SCANDEP 1.00 ------------ Purpose ------- SCANDEP is a C/C++ programmer's utility to generate dependency lists for one or more source files. Dependencies are displayed in either a hierarchical format or formats suitable for makefiles. SCANDEP was developed with and for the Microsoft compiler (MSVC), but I know of no reason why it wouldn't work with source for any standard C/C++ compiler. SCANDEP is a DOS command-line utility, but of course it can be run in a DOS window under Windows or OS/2. If you don't know what a dependency list is, or what a dependent file is, then you probably don't need this program. Why? ---- I recently needed a DOS program to generate makefile-suitable lists of file dependencies for a large number of C++ source files and assumed that it would be pretty easy to find one on CompuServe or the Internet. I did find several, but none worked quite right. Either they missed files for no obvious reason, or they automatically included all of the "system" headers (like stdio.h), or they didn't recognize that some of the #include directives were commented out. Particularly troubling was that most of the ones I found did not search for included files in the same way that C/C++ compilers do. For example, MSVC never explicitly searches the current directory for an include file. It looks in the directory of the file that does the including (and of the file that included that, etc.), and this may very well result in a search of the current directory, but it never looks in the current directory unless one of its "includers" lives there. Most of the dependency generators I tried didn't understand this, or, more generally, the basic search pattern for include files. Anyway, this simple program is the result. It may or may not be free of bugs, but it does attempt to follow the search patterns of MSVC (the only C/C++ compiler I'm familiar with); it understand comments; and it's flexible about the handling of system includes. Output formats -------------- SCANDEP can generate its output in three formats; we'll describe these before we begin with SCANDEP's syntax and options. Let's assume that you have asked SCANDEP to scan the source file PROJECT.CPP and that we have the following project file structure: PROJECT.CPP: #include "project.h" #include "common.h" PROJECT.H: #include "stuff.h" STUFF.H: #include "common.h" COMMON.H: // no includes The default SCANDEP output format generates a makefile-suitable description block like this: project.obj: project.cpp \ project.h \ stuff.h \ common.h As you can see, this block shows that the object file PROJECT.OBJ is dependent on the source files PROJECT.CPP, PROJECT.H, STUFF.H, and COMMON.H. The block is ready for the addition of the necessary build commands to create PROJECT.OBJ. The second format conforms with that used by MSVC in makefiles that it creates. MSVC users will have noted that the description blocks in MSVC-generated makefiles do not explicitly list all of the dependencies. Instead, the dependencies (excluding the primary source file) are assigned to a macro, and the macro is used in the description block. SCANDEP can generate output in this format; it would look like this: PROJECT_DEP = project.h \ stuff.h \ common.h project.obj: project.cpp $(PROJECT_DEP) The third format is not for makefiles. It simply displays the include file structure in hierarchical format: c:\project\project.cpp c:\project\project.h c:\project\stuff.h c:\project\common.h c:\project\common.h This clearly shows that PROJECT.CPP #includes PROJECT.H and COMMON.H; that PROJECT.H #includes STUFF.H; and that STUFF.H #includes COMMON.H. Note that, unlike the makefile blocks, files can appear more than once (as COMMON.H does), and that absolute paths are shown. Syntax ------ The basic syntax is: scandep [options] {target[=ext]} The targets are the source files that you want to scan; the options affect how SCANDEP operates. If there are many targets or options, the command line may become too long, or inconvenient to type. In that case, you can store the targets and/or options in a text file called a "response file" and run SCANDEP in this way: scandep @response-file We'll describe response files more fully below. Specifying targets ------------------ Targets are the source files that you wish to scan. They must be C/C++ source files or MSVC-compatible resource files (.RC extension). You must specify at least one target, or SCANDEP will complain that it has nothing to do. The simplest usage of SCANDEP just specifies a single target: scandep myfile.cpp This will scan the target MYFILE.CPP for dependencies (i.e., #include files) and create a makefile-suitable dependency list. It might look like this: myfile.obj: myfile.cpp \ myfile.h \ common.h \ stdafx.h Note that SCANDEP has assumed that the ultimate target file is MYFILE.OBJ (created from MYFILE.CPP); it has actually created a dependency list for MYFILE.OBJ rather than MYFILE.CPP. Of course, you can redirect SCANDEP's output to a text file for editing and/or merging into makefiles. For example: scandep myfile.cpp > myfile.dep You can specify multiple targets, and you can use wildcards. Paths are OK, including paths relative to the current directory. For example: scandep *.cpp res\*.rc This will scan all *.CPP files in the current directory and all *.RC files in the subdirectory RES. Each target produces a separate dependency list. Specifying target extensions ---------------------------- In the previous example, SCANDEP assumes that the makefile target to be created for MYFILE.CPP is MYFILE.OBJ (since MYFILE.CPP would typically be compiled to MYFILE.OBJ). SCANDEP recognizes three extensions: .CPP -> .OBJ .C -> .OBJ .RC -> .RES If you have targets with any other extension, or if you want different extensions used as the makefile target, specify "target extensions" with your targets. Specify the extension for a target by following the target with an equals sign and the new extension: target=ext For example, suppose you have C++ source files with the extension .INL that compile to .OBJ files. SCANDEP will not handle these automatically because it doesn't recognize INL as a C++ source file. You would need to specify the extension on the command line as follows: scandep myfile.inl=obj This would create the desired makefile target: myfile.obj: myfile.inl \ ... Target extensions are a non-issue in hierarchical output format because SCANDEP does not create a makefile target. Options ------- SCANDEP's options are: /A Use absolute paths in dependency lists /Ef Set error handling mode for #include not found /Er Set error handling mode for recursive #include /Et Set error handling mode for target not found /Ex Set error handling mode for unknown extension /H Output dependencies in hierarchical format /M Output dependencies in MSVC format /I Specify additional include search path(s) /S Read system includes (#include ) /X Exclude named file from dependency lists /? Display brief help Options are case-insensitive (/a == /A). They may be specified in any order, and may precede, follow, or be mixed in with targets. All options are processed before any scanning begins. Multiple options must be separated by spaces, i.e., "/H /S" rather than "/H/S". The options are described in the following sections. /A: absolute paths ------------------ When generating dependency lists, SCANDEP uses paths relative to the main target. For example, suppose we have this: c:\one\two\myfile.cpp: #include "myfile.h" #include "\one\common.h" #include "\one\two\res\resource.h" The dependency list would look like this: myfile.obj: myfile.cpp \ myfile.h \ ..\common.h \ res\resource.h Note that all paths are relative to the directory containing the target, MYFILE.CPP. This allows projects to be easily moved without requiring makefiles to be completely re-made. However, if you prefer absolute paths, use the /A option: scandep /A myfile.cpp This command would generate the following dependency list: myfile.obj: c:\one\two\myfile.cpp \ c:\one\two\myfile.h \ c:\one\common.h \ c:\one\two\res\resource.h Regardless of the presence or absence of /A, SCANDEP always uses absolute paths in three cases: 1. For any dependent that is not located on the same drive as the target. 2. For dependents that descend from a different first-level directory than the target. 3. For system includes, i.e., those enclosed in <>: #include Note that system includes are only scanned if the /S option is present. An example of case 2: if MYFILE.CPP also #included c:\x\y\some.h, the list would be: myfile.obj: myfile.cpp \ myfile.h \ ..\common.h \ res\resource.h \ c:\x\y\some.h As you can see, the full path from the root is specified for SOME.H; it is not relative to the location of MYFILE.CPP. This is because SOME.H lies below the first-level directory X rather than MYFILE's first-level directory ONE. /E: error handling modes ------------------------ Certain potentially recoverable errors can occur when scanning for dependencies. These are: - Target file not found. - #include file not found. - Unknown target extensions (extension not .C, .CPP, or .RC, and no target extension provided). - Recursive includes (a file that directly or indirectly #includes itself). You can control how SCANDEP responds to each of these situations using the /E option. /E is followed by a single letter specifying an error condition: /Ef: include not found /Er: recursive include /Et: target not found /Ex: unknown extension Following the error condition is a single digit, which must be 0, 1, 2, or 3 (e.g., /Er2). These mean: 0: ignore the error 1: report the error but continue processing 2: report the error and exit 3: report the error, display a list of active source files, and exit The default settings are: /Ef2 (error exit on #include not found) /Er1 (report recursive includes but continue) /Et2 (error exit on target not found) /Ex2 (error exit on unknown extensions) Mode 3 affects /Ef and /Er only. For /Et and /Ex, mode 3 is the same as mode 2. /H: use hierarchical output format ---------------------------------- Adding the /H option causes SCANDEP to generate its output in the hierarchical format described above: scandep /h myfile.cpp When /H is specified, /A has no effect (the output always uses absolute paths), and unknown target extensions are of no significance. /H overrides /M; if both are specified, the output will be in hierarchical format. /I: specify include path ------------------------ When searching for #included files, SCANDEP follows the standard MSVC search pattern (see online help for #include). This includes the directories containing all "parent" files of the file being included and the directories specified by the environment variable INCLUDE. MSVC provides the /I option, which allows you to specify additional directories search; SCANDEP provides a very similar option. To use it, just specify /I followed by a directory name: scandep /I\projects\common myfile.cpp To specify multiple directories, either use multiple /I options or use a PATH-like specification, separating directories with semicolons: scandep /I\projects\common /I\toolkit\include ... scandep /I\projects\common;\toolkit\include ... In either case, SCANDEP adds \PROJECTS\COMMON and \TOOLKIT\INCLUDE to its list of searchable directories. These directories are searched before the INCLUDE variable directories, by the way. MSVC users: note that, unlike MSVC, there is no space between /I and the directory name. /M: use MSVC format ------------------- Adding the /M option causes SCANDEP to generate dependencies in "MSVC format" as described above: scandep /m myfile.cpp In this format, dependencies are assigned to makefile macros, and the macros are used in the description blocks. /S: scan system includes ------------------------ Normally, SCANDEP ignores the "system" includes, i.e., include files specified with <>: #include "myfile.h" // SCANDEP scans this... #include // ...but not this This is because system headers rarely change and are typically not included in makefiles. However, you can force SCANDEP to scan the system headers by using the /S option: scandep /s myfile.cpp /X: exclude dependents ---------------------- Occasionally you may wish to exclude specific dependents from dependency lists. Do this with the /X option, which is followed by a filename. For example: scandep myfile.cpp /Xresource.h This command would omit RESOURCE.H from all dependency lists. Note that SCANDEP doesn't scan excluded files for dependencies. In other words, both the excluded file and its dependents are omitted from the output. The filename as specified must exactly match the filename provided in the #include directive. If you've used "/Xresource.h", then SCANDEP will recognize and exclude: #include "resource.h" but not: #include "c:\myfile\resource.h" /X excludes dependents (include files), not targets. If your target is *.C, all C source files will be scanned; you can't exclude a specific C source file by using, for example, "/Xuseless.c". /?: display brief help ---------------------- The /? option displays a screen comtaining a brief summary of SCANDEP's syntax and options. scandep /? If /? is used, all other options and targets are ignored; SCANDEP displays the help screen and terminates. Using response files -------------------- If the command line grows too long, or if you want to run SCANDEP regularly on a particular project, you can use a response file. To create a response file, use your regular text editor to create a text file containing any number of targets and/or options. Lines in the response file may be empty; they may contain one target or option; or they may contain multiple targets and/or options (just like the command line). However, individual lines are limited to 500 characters. A response file might look like this: myfile.cpp fileiter.cpp sources.cpp res\resource.cpp common.cpp /Xresource.h /S /I\library\include /M To use the response file, simply put its name on the command line follwing an @, e.g.: scandep @scandep.rf It's perfectly OK to mix command line options and targets with a response file: scandep /S target.c @scandep.rf You can use multiple response files, but they can't be nested. Errorlevels ----------- SCANDEP returns one of the following DOS errorlevels on completion: 0 no errors 1 recursive header found (/Er2 mode) 2 unknown target extension (/Ex2) 3 include file not found (/Ef2) 4 include file could not be opened 5 target not found (/Et2) 254 system exception (out of memory, file I/O error) 255 usage error; response file not found; response file line too long Implementation limits --------------------- 1. Source files are assumed to be text files consisting of lines no longer than 2000 characters. Excess characters are discarded. 2. Response files are assumed to be text files consisting of lines no longer than 500 characters. Longer lines will generate an error. 3. SCANDEP does not recognize the RCINCLUDE directive in MSC resource files. 4. SCANDEP is a DOS program and it can run out of memory if many targets are specified, if the dependency lists are extremely large or if not much memory is available. Try reducing the number of targets per run. Problems/comments/suggestions ----------------------------- Please report any problems and send any comments or suggestions to me at the email addresses below. Release history --------------- 6/26/97 v1.00: initial release Copyright/License/Warranty -------------------------- This document and the program file SCANDEP.EXE ("the software") are copyrighted by the author. If you are an individual, the copyright owner hereby licenses you to use the software, make as many copies of the software and documentation as you wish, give such copies to anyone, and distribute the software and documentation via electronic means. There is no charge for any of the above. However, you are specifically prohibited from charging, or requesting donations, for any such copies, however made; and from distributing the software and/or documentation with commercial products without prior permission. An exception is granted to not-for-profit user's groups, which are authorized to charge a small fee (not to exceed $7) for materials, handling, postage, and general overhead. Businesses, institutions, and governmental entities must obtain a specific license agreement from The Cove Software Group in order to use the software. No copy of the software may be distributed or given away without this document; and this notice must not be removed. There is no warranty of any kind, and the copyright owner is not liable for damages of any kind. By using this free software, you agree to this. The software and documentation are: Copyright (C) 1997 by Christopher J. Dunford The Cove Software Group 10551 Rivulet Row Columbia, Maryland 21044 Tel: (410) 992-9371 CompuServe: 76703,2002 email: cd@cis.compuserve.com