capnproto icon indicating copy to clipboard operation
capnproto copied to clipboard

How to add search directories for capnp?

Open Biswa96 opened this issue 3 years ago • 8 comments

In MSYS2/MinGW, the include directory is /mingw64/include/ for x86 and /mingw64/include/ for x86_64. But according to the docs, I have to add -I option in command line to include the search directory. Is it possible to add search directory path at build time? See the discussion at https://github.com/msys2/MINGW-packages/pull/6910.

Biswa96 avatar Sep 16 '20 12:09 Biswa96

Hi @Biswa96,

It sounds like in this environment, you should tell the build system to install to a different prefix than the default /usr/local. You probably want to invoke configure like so:

./configure --prefix=/mingw64

If you do this, the resulting capnp binary will have /mingw64/include in its default include path. Also, setting --prefix this way will cause make install to install Cap'n Proto into /mingw64 in general, which seems like what you want.

If you aren't using the autotools build, you can define the preprocessor symbol CAPNP_INCLUDE_DIR to specify an additional include path. This macro should expand to a string literal. So, you could use a compiler flag like '-DCAPNP_INCLUDE_DIR="/mingw64/include"' -- note that the outer single-quotes are necessary so that the inner double-quotes don't get removed by the shell.

kentonv avatar Sep 16 '20 17:09 kentonv

Here are something I have tried:


CFLAGS+=' -DCAPNP_INCLUDE_DIR=\"/mingw64/include\"' \
CXXFLAGS+=' -DCAPNP_INCLUDE_DIR=\"/mingw64/include\"' \
cmake.exe
// other options here

This compiles but the capnp.exe contains full path of /mingw64/include directory. This causes problem because my installation may not be same with others.


CFLAGS+=' -DCAPNP_INCLUDE_DIR="/mingw64/include"' \
CXXFLAGS+=' -DCAPNP_INCLUDE_DIR="/mingw64/include"' \
cmake.exe
// other options here

This causes compiler error.


Tried to replace /usr/include with /mingw64/include in src/capnp/compiler/capnp.c++ file. Then compiled it. Compilation went fine. capnp.exe contains /mingw64/include string. But capnp compile fails with error: Import failed: /capnp/c++.capnp.

Biswa96 avatar Sep 17 '20 06:09 Biswa96

I see, so a compile-time constant is not sufficient here, because you want to be able to redistribute the binary and other users may use different installation locations.

I suppose what we really need to do is find the capnp binary itself, then look up ../include relative to it.

This comes with further questions, though. What if the binary is a symlink? Do we look relative to the symlink, or to the executable it points to, or both? What if it's a chain of symlinks?

Also, what's the right way to find the executable's own path? Search for argv[0] using standard PATH rules? Or something more like /proc/self/exe (or Windows equivalent)?

kentonv avatar Sep 18 '20 16:09 kentonv

I suppose what we really need to do is find the capnp binary itself, then look up ../include relative to it.

Now I am thinking that my question is somewhat msys2 specific. Though searching for ../include is somewhat hardcoded thing.

what's the right way to find the executable's own path?

GetModuleFileName(NULL, buffer, size).

Though I am thinking somewhat like --with-native-system-header-dir option in GCC. I don't know how it is done in GCC. But it may bring some familiarity for everyone.

Biswa96 avatar Sep 18 '20 16:09 Biswa96

GetModuleFileName(NULL, buffer, size)

Right, that's the Windows version of Linux's /proc/self/exe. The problem is, it'll report the final path after symlink resolution. But maybe that's what we want? It seems pretty unclear how symlinks should be handled here.

kentonv avatar Sep 18 '20 17:09 kentonv

Just a note that this is also a problem for conda packages.

By default, conda modifies the capnp binary so that the CAPNP_INCLUDE_DIR value set at build time is changed with the correct value at install time but this leads the binary to generating an exception at runtime when the new path is shorter than the placeholder path used at build time. The exception is thrown here https://github.com/capnproto/capnproto/blob/54a702d014515aaed809e83787482fa461cd9eb7/c%2B%2B/src/kj/filesystem.c%2B%2B#L322 because of the added null terminators (see ref https://docs.conda.io/projects/conda-build/en/latest/resources/make-relocatable.html)

LehMaxence avatar Jan 27 '22 17:01 LehMaxence

https://docs.conda.io/projects/conda-build/en/latest/resources/make-relocatable.html

That's... terrifying...

kentonv avatar Jan 31 '22 21:01 kentonv

For the record, editing string literals in the capnp compiled binary will not work. KJ does not use NUL terminators to decide a string's length, so if you patch a NUL byte into a string literal, that NUL byte is going to show up in your data. So you'll end up with capnp constructing filenames like /opt/capnp-install-path/include\0\0\0\0\0\0\0\0\0\0\0\0\0/capnp/schema.capnp, which (if not for the aforementioned KJ_REQUIRE) would end up with the OS always trying to open /opt/capnp-install-path/include (a directory) instead of the file you intended.

I do agree that having a way to discover the install location dynamically seems desirable but, as mentioned above, I'm not clear on exactly what the desired behavior is.

kentonv avatar Jan 31 '22 22:01 kentonv