ned14 / pcpp

A C99 preprocessor written in pure Python
Other
215 stars 39 forks source link

collapsing to single header #9

Closed psteinb closed 6 years ago

psteinb commented 6 years ago

Hey @ned14, I finally found the time to look at this. I'd like to use pcpp to collapse a library into one single-header file. After reading the docs, I tried a couple of things on the command line, but to no avail. So I am wondering, if you could lend a hand. My project structure is like so:

include/
tests/
CMakeLists.txt

and the code lives in include. this directory looks like this:

entry.hpp
detail/variant1/implementation.hpp
detail/variant2/implementation.hpp

where entry.hpp contains:

#include detail/variant1/implementation.hpp
#include detail/variant2/implementation.hpp

etc. How could I accomplish producing one single-header from this nested header-file structure with pcpp?

thanks in advance - P

psteinb commented 6 years ago

I should say that I tried this:

$ pcpp --passthru-defines --passthru-unknown-exprs entry.hpp

and that appears to work but gives me tons of errors about not being able to include std header files. I opened this issue mostly to find out if this is a bug or feature. ;)

psteinb commented 6 years ago

aha ok, I think I got it:

$ pcpp --passthru-defines --passthru-unknown-exprs compass.hpp 2> /dev/null

Super dangerous to ignore errors, but apparently the outcome looks good. I'll try to compile it now. If you have an opinion about this, let me know.

psteinb commented 6 years ago

ok, I got it to work somehow, but the produced header file doesn't work though as in the compiler throws errors. If you want to have a look, the setup is contained in this PR: https://github.com/psteinb/compass/pull/7

ned14 commented 6 years ago

Can you send me a demo of the compile failure using https://wandbox.org/ please?

psteinb commented 6 years ago

there it is: https://wandbox.org/permlink/rhvGhL0HRPDXXXuz

I just ran the cmake -DPCPP_PATH=which pcpp` plusmakethe normal way on the code from the branch I pointed to above. The wandbox link above contains the collapsed single header version of the library and a simple test inside themain` function. If you need anything else, let me know.

ned14 commented 6 years ago

I ran this:

pcpp -o compass-all.hpp include/compass.hpp --passthru-defines --passthru-unfound-includes --passthru-unknown-exprs --line-directive

And I get this: https://wandbox.org/permlink/nKhv47id5xe2ai4l, which suggests x64 is not supported.

The cause is the defining followed by undefining of COMPASS_CT_ARCH_UNSUPPORTED. pcpp thinks it always defined because it never executes any of the preprocessor which undefines it (how could it?). This is what the magic macro __PCPP_ALWAYS_TRUE__ is for.

Replacing your unilateral define of COMPASS_CT_ARCH_UNSUPPORTED with:

#if !__PCPP_ALWAYS_TRUE__  // Always execute except on pcpp
#define COMPASS_CT_ARCH_UNSUPPORTED
#endif

And now the desired output is generated, and it fails on something else entirely: https://wandbox.org/permlink/3BLInNMsbOCf7QLs

You should have enough now to fix your problems. Let me know how it goes.

psteinb commented 6 years ago

Superb. I'll see to it. Thanks for dealing with code and providing feedback. I'll close the issue once I have it running in compass. Thanks a bunch again!

psteinb commented 6 years ago

yeah, I've been working on this here and there for the last days. It's tricky. I have 3 header files (./rt/x86/gnu_cpuid.hpp ./rt/x86/intel_cpuid.hpp ./rt/x86/llvm_cpuid.hpp) each including a common header ./rt/x86/cpuid_common.hpp to reuse some code therein. cpuid_common.hpp contains an include guard statement. The headers above are then used in the client facing code like so:

#include "detail/rt/x86/llvm_cpuid.hpp"
#include "detail/rt/x86/gnu_cpuid.hpp"
#include "detail/rt/x86/msvc_cpuid.hpp"
#include "detail/rt/x86/intel_cpuid.hpp"

It looks to me that once llvm_cpuid.hpp defines the include guard of cpuid_common.hpp, pcpp will not include cpuid_common.hpp inside gnu_cpuid.hpp. :/

psteinb commented 6 years ago

Alright, I fixed that now, by moving #include "detail/rt/x86/cpuid_common.hpp" into the client facing code. So, I now have:

#include "detail/rt/x86/cpuid_common.hpp"

#include "detail/rt/x86/llvm_cpuid.hpp"
#include "detail/rt/x86/gnu_cpuid.hpp"
#include "detail/rt/x86/msvc_cpuid.hpp"
#include "detail/rt/x86/intel_cpuid.hpp"

but the single header version runs into other problems now. :/

psteinb commented 6 years ago

same pattern with another header and now it works! Not sure though, if I erred or pcpp.