Environment: I am using MS-VC++ 6.0,
- I include a group of header file with some data.
- The header files change often, so on every change I change the path setting and re-compiler
- A log file is generated based on the included header files
For tracking of the header file from the log file, I wish to print the header file path inside the log
Question-1: Is getting the header file path from inside the program possible?
- Qu开发者_C百科estion-2: I am using VC++, but if it is possible in gcc, then I can easily port, so, please let me know, if it is possible in any other environment like gcc
In VC++, compiling with the option /FC
will put the currently processed file's entire path in the __FILE__
macro.
That will account for your changes to the include path.
Details here.
Sure - inside the header file put:
static const char *header_path = __FILE__;
..then just print the string pointed to by header_path
into your log.
Do you mean that having #include "path/to/header.h"
, you want to print "path/to/header.h" from the program itself?
#define INCLUDE_FILE "path/to/header.h"
#include INCLUDE_FILE
printf("Included: %s\n", INCLUDE_FILE);
You can get the list of include files like this.
(project)
(export makefile)
(write dependencies when writing make files)
export the make files, which creates .mak files and .dep files. The include files are listed in the .dep files.
As to the idea of getting the full path to the include files from within the running program. One might be able to use use the msvc 6 object model, to pull the list of include file paths out of the IDE. Once that list is known. One could use find file, to search that list of paths for the include files of interest.
Ok, here is a solution (now I hope I understood you correctly).
It uses Recursive Templates, the __FILE__
macro, and the __COUNTER__
macro.
A special headerlisting.h
header file contains the logic for the template recursion, and includes two useful macros (plus some helper macro's)
ADD_HEADER_FILE
, just add this line to every header file you want to include in your list.LIST_HEADER(headers)
, which you can put in your source to retrieve at run-time a list of all the included header files
I'm sure there is an easier way to do this, maybe with Boost's templating p0werz, please comment.
Below is first headerlisting.h
, and then an example program containing two example headers and a main() source file. This works on Linux with g++, hope it works in Visual Studio too (can't test right now).
headerlogic.h
#ifndef __HEADERLOGIC_H__
#define __HEADERLOGIC_H__
// By catchmeifyoutry, 2009-12-08
// See http://stackoverflow.com/questions/1863995/getting-included-header-file-path-in-vc
#include <vector>
#include <string>
namespace HeaderListing
{
// Recursive templates to store header files, templatized by a header index I.
// Header files will be stored by template specialization, adding new specializations
// for every new header.
//
// The recursive headers depend on the assumption that the for the previous index I-1
// there is a HeaderFile<I-1> defined which contains a method
// void HeaderFile<I-1>::list_headers(std::vector<std::string> &headers)
// to list all I-1 previous header files.
// The I-th HeaderFile then defines it's own list_header(...) to add one name
// to the list.
// -------------------------------------
// Recursive case
// By default, list_headers() adds no name to the list, but if this default case
// is specialized with c-string for name, it will add to the list
template <int I>
class HeaderFile
{
public:
typedef HeaderFile<I-1> PrevHeader;
// in the specalization, this will store the name of header file;
// but if no header with index I is given, name will be NULL by default
static const char * name;
// in the recursive case
static inline void list_headers(std::vector<std::string> &headers)
{
PrevHeader::list_headers(headers);
if (name != NULL) {
headers.push_back(name);
}
}
};
template <int I> const char * HeaderFile<I>::name = NULL;
// -------------------------------------
// Base case
// Ensures recursion ends, implements dummy list_headers()
template <>
class HeaderFile<-1>
{
public:
static inline void list_headers(std::vector<std::string> &headers)
{ /* end of recursion, do nothing! */ }
};
}; // namespace HeaderListing
// -------------------------------------
// Macros to add header files
// Add n-th header file name (as a string) to the list
#define ADD_HEADER_FILE_NAME_N(n, file) template <> const char * HeaderListing::HeaderFile<n>::name = __FILE__; \
// Add a given string (e.g. a header filename) to the to the list
// Uses built-in __COUNTER__ macro to track the current header count.
// NOTE: it doesn't matter if count was used in between since there can be gaps in between the header indices
#define ADD_HEADER_FILE_NAME(file) ADD_HEADER_FILE_NAME_N(__COUNTER__, file)
// Add the current (header) file to the list
// Uses the built-in __FILE__ macro.
#define ADD_HEADER_FILE ADD_HEADER_FILE_NAME(__FILE__)
// List all defined header files
// The "headers" argument should be a std::vector<std::string>
#define LIST_HEADERS(headers) HeaderListing::HeaderFile<__COUNTER__>::list_headers(headers);
#endif // __HEADERLOGIC_H__
Now for the example program:
head1.h
#ifndef __HEAD1__
#define __HEAD1__
#include "headerlisting.h"
ADD_HEADER_FILE
#endif // __HEAD1__
head2.h
#ifndef __HEAD2__
#define __HEAD2__
#include "headerlisting.h"
ADD_HEADER_FILE
#endif // __HEAD2__
headertest.cpp
#include <iostream>
#include <vector>
#include <string>
#include "headerlisting.h"
#include "head1.h" // <-- TRY COMMENTING THESE OUT!
#include "head2.h" // <-- TRY COMMENTING THESE OUT!
using namespace std;
int main()
{
// list included header files
vector<string> headers;
LIST_HEADERS(headers);
// display included header files
size_t n = headers.size();
cout << "Found " << n << " headers" << endl;
for (size_t h = 0; h < n; ++h)
{
cout << "header " << h << " :\t" << headers[h] << endl;
}
return 0;
}
The generated output should look like this (if you don't exclude the head1.h or head2.h from headertest.cpp, that is):
Found 2 headers
header 0 : head1.h
header 1 : head2.h
Please tell me this works.
精彩评论