[preprocessor] computed include possible?

I am wondering if it would be possible to write a computed include macro that is sufficiently compiler independent? E.e. given a macro #define BOOST_PLATFORM_INCLUDE(hdr) ... definition missing ... which should be usable as: #include BOOST_PLATFORM(foo.h) The effect being win32/foo.h included on one linux/foo.h included on another platform. I have yet figured out a way that can achieve something close, but gcc does not allow to use a parameterized macro. I would be interested if someone has some experience with this. Roland

Roland Schwarz wrote:
I am wondering if it would be possible to write a computed include macro that is sufficiently compiler independent?
E.e. given a macro
#define BOOST_PLATFORM_INCLUDE(hdr) ... definition missing ...
which should be usable as:
#include BOOST_PLATFORM(foo.h)
The effect being win32/foo.h included on one linux/foo.h included on another platform.
I have yet figured out a way that can achieve something close, but gcc does not allow to use a parameterized macro.
Where is the problem? #if defined(linux) || defined(__linux) || defined(__linux__) # define PLATFORM_HEADER_DIRECTORY linux #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) # define PLATFORM_HEADER_DIRECTORY windows // [...] #endif #define PLATFORM_HEADER(header) <PLATFORM_HEADER_DIRECTORY/header> #include PLATFORM_HEADER(foo.h) Should work. I've no idea how portable it is, though. If you need quotes instead use BOOST_PP_STRINGIZE: #define PLATFORM_HEADER(header) \ BOOST_PP_STRINGIZE(PLATFORM_HEADER_DIRECTORY/header) Regards, Tobias

Tobias Schwinger wrote:
Where is the problem? [snip]
#include PLATFORM_HEADER(foo.h)
Should work. I've no idea how portable it is, though.
This exactly is the problem. This works with MS compilers, but not with gcc. It complains with: #include' expects "FILENAME" or <FILENAME>" However the following does work with gcc: #define PLATFORM_PFX <boost/whatever/windows/ #define PLATFORM_HDR foo.hpp #define PLATFORM_SFX > #include PLATFORM_PFX PLATFORM_HDR PLATFORM_SFX Unfortunately this wont work on MS compilers. My question was if it would be possible to get something that is compileable on a couple of platforms. I am aware that macro expansion after precompiler prefix seems to be implementation dependent. I am not even sure if the standard has to say anything about this. At least gcc seems not to conform to what is said in this (rather dated) document: http://www.lns.cornell.edu/public/COMP/info/egcs/cpp/cpp_1.html#SEC6 Roland

Roland Schwarz wrote:
Tobias Schwinger wrote:
Where is the problem?
[snip]
#include PLATFORM_HEADER(foo.h)
Should work. I've no idea how portable it is, though.
This exactly is the problem. This works with MS compilers, but not with gcc. It complains with: #include' expects "FILENAME" or <FILENAME>"
That's interesting... I tested the code before posting with gcc 3.4 and there were no problems. Regards, Tobias

Tobias Schwinger wrote:
That's interesting... I tested the code before posting with gcc 3.4 and there were no problems.
You are correct. Great! I did it slightly different and this was causing the error message, because PLATFORM_HEADER_DIRECTORYheader was interpreted as token, which of course can't work. The wollowing DOES NOT WORK: #if defined(linux) || defined(__linux) || defined(__linux__) # define PLATFORM_HEADER_DIRECTORY <linux/ #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) # define PLATFORM_HEADER_DIRECTORY <windows/ // [...] #endif // PLATFORM_HEADER_DIRECTORY must be separated by something that // causes header to be a separate token. #define PLATFORM_HEADER(header) PLATFORM_HEADER_DIRECTORYheader> #include PLATFORM_HEADER(foo.h) Thank you again! Roland

Roland Schwarz wrote:
The wollowing DOES NOT WORK:
#define PLATFORM_HEADER(header) PLATFORM_HEADER_DIRECTORYheader>
Sure the names are one token -- it even looks sorta strange, doesn't it ;-). You can use a nullary, function like macro for PLATFOR_HEADER_DIRECTORY to make this variant work, however: // [...] # define PLATFORM_HEADER_DIRECTORY() <mylib/win32/ // [...] #define PLATFORM_HEADER(header) PLATFORM_HEADER_DIRECTORY()header> Regards, Tobias

Tobias,
# define PLATFORM_HEADER_DIRECTORY() <mylib/win32/ // [...] #define PLATFORM_HEADER(header) PLATFORM_HEADER_DIRECTORY()header>
How about: #ifdef ... #define PLATFORM_DIRECTORY win32 #elif .... #endif #define BOOST_INCLUDE(includeFile) <includeFile> #include BOOST_INCLUDE(PLATFORM_DIRECTORY/myFile.h) Tom

Tomas Puverle wrote:
Tobias,
# define PLATFORM_HEADER_DIRECTORY() <mylib/win32/ // [...] #define PLATFORM_HEADER(header) PLATFORM_HEADER_DIRECTORY()header>
How about:
#ifdef ... #define PLATFORM_DIRECTORY win32 #elif .... #endif
#define BOOST_INCLUDE(includeFile) <includeFile>
#include BOOST_INCLUDE(PLATFORM_DIRECTORY/myFile.h)
How about: #ifdef __WIN32__ #include <win32/myfile.hpp> #elif ... ... #endif So that dependency analysis works with Boost.Build without yet more special case kludges ;-) And so that people with smart text editors can select the include file and open it directly. And so that other people reading the code have a chance at understanding it. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

Rene Rivera wrote:
#ifdef __WIN32__ #include <win32/myfile.hpp> #elif ... ... #endif
So that dependency analysis works with Boost.Build without yet more special case kludges ;-) And so that people with smart text editors can select the include file and open it directly. And so that other people reading the code have a chance at understanding it.
;-) I still prefer having an appropriate include path set by the build system. However, the OP asked how to #include files with macro-ized names... The code above looks like a copy-and-paste solution (given the project has more than one platform dependent translation unit). But while we're at it: it's probably not too bad of an idea to have BOOST_PLATFORM_<PLATFORM> or something like that defined by Boost.Config to normalize between the different name/underscore combinations there are (see boost/config/select_platform_config.hpp)... Regards, Tobias

Tobias Schwinger wrote:
Rene Rivera wrote:
#ifdef __WIN32__ #include <win32/myfile.hpp> #elif ... ... #endif
So that dependency analysis works with Boost.Build without yet more special case kludges ;-) And so that people with smart text editors can select the include file and open it directly. And so that other people reading the code have a chance at understanding it.
;-)
I still prefer having an appropriate include path set by the build system. However, the OP asked how to #include files with macro-ized names...
True... But this is a list about the Boost Libraries. If it was a general question perhaps c.l.c++ is a better forum.
The code above looks like a copy-and-paste solution (given the project has more than one platform dependent translation unit). But while we're at it: it's probably not too bad of an idea to have BOOST_PLATFORM_<PLATFORM> or something like that defined by Boost.Config to normalize between the different name/underscore combinations there are (see boost/config/select_platform_config.hpp)...
Absolutely, and I'm already working on it. See the wiki for some notes about that <http://tinyurl.com/p4hb3>. I have more up to date notes that I've gathered as I try to implement those changes. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

in my frame im instantiating it here m_txtctrl = new wxTextCtrl( this, id_txtctrl, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY ); m_logger = new wxLogTextCtrl( m_txtctrl ); m_logger->SetActiveTarget(m_logger); I have narrowed it down to this, if I comment this line m_logger->SetActiveTarget(m_logger); the leak goes away Detected memory leaks! Dumping objects -> {2446} normal block at 0x00B2ABC8, 48 bytes long. Data: <x1Y > 78 31 59 00 00 00 00 00 00 00 00 00 00 00 00 00 Object dump complete. -- Happy coding :) Richard V. Day richardvday@verizon.net richardvday@yahoo.com

Rene Rivera schrieb:
How about:
#ifdef __WIN32__ #include <win32/myfile.hpp> #elif ... ... #endif
So that dependency analysis works with Boost.Build without yet more special case kludges ;-)
I adopted #define PLATFORM_HEADER(header) <PLATFORM_HEADER_DIRECTORY/header> Interestingly the Boost.Build seems so smart that it _does_ recognize if a header has changed. Hmm, while thinking about this I am not sure if it really is, since I might have referenced the include from the corresponding src files explicitely. But even if so, for library writers this will pose no problem since they simply have to reference the platform headers explicitely rather than by computed include. At least the src files are platform dependant too. For user code on the other hand this never is a problem since the headers just reference library code. And I think it is not too much a problem to force a rebuild if the library has been changed. Another idea to overcome this problem: There could be a include header that lists all platform headers say: #if 0 #include <boost/thread/pthread/condition.hpp> #include <boost/thread/win32/condition.hpp> #endif This will do no harm to the compiler and keep the dependency generation happy. What do you think? I already checked in code that uses the macro, in the boost rewrite branch. However I would prefer a boost macro that lives in boost.preprocessor. Boost.config on the other hand could be extended so that the platform chooser also provides a reusable macro that could be used in the following manner: #include BOOST_PLATFORM(thread, condition.hpp) and would expand into: #include <boost/thread/linux/condition.hpp>
And so that people with smart text editors can select the include file and open it directly. And so that other people reading the code have a chance at understanding it.
Yes, but this comes at the cost of lot of boiler plate code. And if you want to change the logic of the platform chooser you will need to change all this code too. Roland

Roland Schwarz wrote:
Rene Rivera schrieb:
How about:
#ifdef __WIN32__ #include <win32/myfile.hpp> #elif ... ... #endif
So that dependency analysis works with Boost.Build without yet more special case kludges ;-)
I adopted #define PLATFORM_HEADER(header) <PLATFORM_HEADER_DIRECTORY/header>
Interestingly the Boost.Build seems so smart that it _does_ recognize if a header has changed. Hmm, while thinking about this I am not sure if it really is, since I might have referenced the include from the corresponding src files explicitely.
Yes, that would be why it's catching the header change.
But even if so, for library writers this will pose no problem since they simply have to reference the platform headers explicitely rather than by computed include. At least the src files are platform dependant too.
For user code on the other hand this never is a problem since the headers just reference library code. And I think it is not too much a problem to force a rebuild if the library has been changed.
The flaw in that rational is that many other Boost libraries are "users" of other Boost libraries. So not having the dependency chains work causes problems during testing because dependent libraries are then not retested when dependencies change.
Another idea to overcome this problem: There could be a include header that lists all platform headers say:
#if 0 #include <boost/thread/pthread/condition.hpp> #include <boost/thread/win32/condition.hpp> #endif
This will do no harm to the compiler and keep the dependency generation happy. What do you think?
I believe that is what other libraries that do, or something similar. It's not even needed to have the "#if 0", the headers could be mentioned in a comment. Just as long as they look like valid #include's: /* For build dependency: #include <boost/thread/pthread/condition.hpp> #include <boost/thread/win32/condition.hpp> */ More informative comment would be good of course.
Yes, but this comes at the cost of lot of boiler plate code. And if you want to change the logic of the platform chooser you will need to change all this code too.
Understood :-) I was just bringing up some issues that have come up in the past due to such use of macro includes. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

On Saturday 08 April 2006 20:18, Roland Schwarz wrote:
I am wondering if it would be possible to write a computed include macro that is sufficiently compiler independent?
E.e. given a macro
#define BOOST_PLATFORM_INCLUDE(hdr) ... definition missing ...
which should be usable as:
#include BOOST_PLATFORM(foo.h)
Roland, I'm not sure if that will help you, but I know that STLport uses a similar technique to include native headers (i.e. the compiler's string.h from their string.h), I think the macro is called _STLP_NATIVE_INCLUDE_PATH or something like that. Uli
participants (6)
-
Rene Rivera
-
Richard V. Day
-
Roland Schwarz
-
Tobias Schwinger
-
Tomas Puverle
-
Ulrich Eckhardt