-
Notifications
You must be signed in to change notification settings - Fork 36
Description
I've worked on a small piece of code to preprocess C++ files so that importing code with macros will work without pulling in all the types defined in #includes. It's not perfect, but I think it will work for almost all of the common use cases.
The basic idea is this: We extract the macros from the included files to substitute into our target file, but we ignore the contents of the included files themselves.
To do this, first we invoke
$ cpp -dM a.hpp -o a.hpp.macros
We then append a.hpp to a.hpp.macros, and manually remove all the #include directives. We run the preprocessor on this file, and and get a properly "preprocessed" file, which has all the macros substituted, but no extra data structures included.
Of course, this could fail if #include directives were used in funky ways, but for the standard use of just including header files, it will work perfectly.
I've written the function do do this preproprocessing. There are only 3 options which need to be exposed to the user: The C Preprocessor executable command (on most unix systems just "cpp"), the include search path options (which they can copy from the build system), and the working directory from which the preprocessor should be invoked (significant when #includes use relative paths). The nice thing is that this function fails gracefully. If anything goes wrong, it will just return the original filename you fed in, which the DoUML C++ parser can handle just as in previous versions (albeit without macros substituted).
Thanks for your work keeping DoUML alive and open source, it's very useful to me.
#include <qstringlist.h>
#include <qstring.h>
#include <qtextstream.h>
#include <qfileinfo.h>
#include <qdir.h>
#include <qprocess.h>
QString j_preprocess(const QString &cpp_exec, const QString & f,const QString& working_dir, const QStringList& include_args) {
QString macrosfilenm(f+".included");
QProcess process;
process.setWorkingDirectory(working_dir);
QStringList get_macros_args(include_args);
get_macros_args << "-dM" << f << "-o" << macrosfilenm;
process.start(cpp_exec, get_macros_args);
if(!process.waitForFinished()) {
return f;
}
QFile srcfile(f);
if(!srcfile.open(QIODevice::ReadOnly)) {
return f;
}
QFile macrosfile(macrosfilenm);
if(!macrosfile.open(QIODevice::WriteOnly | QIODevice::Append|QIODevice::Text)) {
return f;
}
QTextStream in(&srcfile);
QTextStream out(¯osfile);
while(!in.atEnd()) {
QString line = in.readLine();
if(!line.startsWith("#include",false)) {
out << line << "\n";
}
}
srcfile.close();
macrosfile.close();
QString outpfilenm(f+".preprocessed");
QStringList preprocess_args;
preprocess_args << macrosfilenm << "-o" << outpfilenm;
process.start(cpp_exec,preprocess_args);
if(!process.waitForFinished()) {
return f;
}
if(!QFileInfo(outpfilenm).exists()) {
return f;
}
return outpfilenm;
}