Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

A C or C++ compiler looks for header files using a strict set of rules: relative to the directory of the including file (if "" was used), then along the specified and default include paths, fail if still not found.

An ancillary tool such as a code analyzer (which I'm currently working on) has different requirements: it may for a number of reasons not have the benefit of the setup performed by a complex build process, and have to make the best of what it is given. In other words, it may find a header file not present in the include paths it knows, and have to take its best shot at finding the file itself.

I'm currently thinking of using the following algorithm:

  1. Start in the directory of the including file.

  2. Is the header file found in the current directory or any subdirectory thereof? If so, done.

  3. If we are at the root directory, the file doesn't seem to be present on this machine, so skip it. Otherwise move to the parent of the current directory and go to step 2.

Is this the best algorithm to use? In particular, does anyone know of any case where a different algorithm would work better?

share|improve this question
3  
Why don't you try and find out the list of include paths that the compiler would use? It should not be that difficult: there are some default ones, and the rest is passed in the command line using some compiler option (-I, /I, etc). –  Giorgio Nov 13 '11 at 17:49
    
Yes, and if the project has a single command line, indeed this is not difficult. But many projects use thousands of lines of configuration files for build systems like autotools or cmake; worse yet, many projects use thousands of lines of custom build systems that an ancillary tool can't possibly know about; so for practical purposes, that information may not be available. –  rwallace Nov 13 '11 at 17:59
    
Maybe you can run an indexer that indexes the available headers in the entire FS, make searching an already indexed file "step 0" followed by the steps you mentioned. I've seen the "locate" program on Linux that uses indexing(something like that) and is real fast. –  yati sagade Nov 13 '11 at 18:43
    
That is certainly a possibility, but the issue is, supposing there are several header files in the filesystem with the same name, which one should be used? Not a hypothetical scenario: download the source code for a few large projects and see how many occurrences of e.g. config.h or index.h you end up with. –  rwallace Nov 13 '11 at 18:58
    
Without knowing what include path the preprocessor is using (built-in defaults, provided on the command line or both), there is no way to conclusively determine which files will be included, period. Attempts to guess, no matter how educated, will sometimes come up with the wrong file, leading your code analyzer to go off half-cocked and produce incorrect results. –  Blrfl Nov 13 '11 at 19:31

2 Answers 2

up vote 2 down vote accepted

I'm currently thinking of using the following algorithm:

  1. Start in the directory of the including file.

  2. Is the header file found in the current directory or any subdirectory thereof? If so, done.

  3. If we are at the root directory, the file doesn't seem to be present on this machine, so skip it. Otherwise move to the parent of the current directory and go to step 2.

Is this the best algorithm to use? In particular, does anyone know of any case where a different algorithm would work better?

I have been working in projects that had a setup like this:

prj
|
+-config.h
|
+-sub_A
| |
| +-config.h
| +-...
|
+-sub_B | |
| +-config.h
| +-...
|
+-...

Those are then referred to as

#include "config.h"
#include "sub_A/config.h"
#include "sub_B/config.h"
...

Simply searching for a header with a matching file name would blow this, which I believe means that a different algorithm would work better.

share|improve this answer
    
Okay, how does your build system distinguish between the two? At first glance it would seem likely that sub_A/foo.c would want sub_A/config.h, but then how is prj/config.h referred to? –  rwallace Nov 13 '11 at 19:39
    
@rwallace: See my edit. –  sbi Nov 13 '11 at 19:45
    
Ah! Presumably with compiler switch -Iprj. Is there a reason to use "config.h" instead of <config.h>? Normally the quotes form tells the compiler to look first in the directory of the including file, which would seem not to apply here? –  rwallace Nov 13 '11 at 19:49
    
@rwallace: I'm not sure I understand. The project is in prj, and that's also from where the build process is started. It's like the root of the build's file system. Files in the build folder are certainly included using the "" notation. –  sbi Nov 13 '11 at 19:54
    
Sure, but there's a fine but important distinction: for most compilers, "" does not take the current directory as being the one from where the build process was started, but the one in which the file doing the including is located, as discussed here: stackoverflow.com/questions/7645024/… - are you saying you use a compiler that behaves otherwise? If so, which one? –  rwallace Nov 13 '11 at 20:01

I think with any algorithm you won't succeed without knowing compiler command line used for particular file compilation. So, I see only two possibilities to use static analyzer with any build system:

  1. "lint way" (which is probably not very well aligned with you requirements) place utility right before or instead of compiler invocation, passing all the same arguments. In this case you should dig into any build system/makefile to find all rules responsible for compilation.
  2. "coverity way" run every build process under your tool, i.e. as a child/ren process(es). Thus, your tool should be clever enough to track which files are currently opening by compiler, which flags are passed. This is complicated but reliable way though.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.