rpav / c2ffi

Clang-based FFI wrapper generator
GNU Lesser General Public License v2.1
234 stars 39 forks source link

Invalid constants generated from system headers #87

Closed spaceotter closed 3 years ago

spaceotter commented 3 years ago

I'm having a bit of trouble understanding how this is supposed to be used. See here: https://github.com/spaceotter/cifgen

The issue is that, first I had to manually specify the system include paths. Is that normal? The bigger issue is that including a system header unearths a whole lot of macros that cause c2ffi to barf, like:

./test.m.hh:1:51: error: expected expression
const long __c2ffi___restrict_arr = __restrict_arr;
                                                  ^
./test.m.hh:6:69: error: expected expression
const long __c2ffi___attribute_nonstring__ = __attribute_nonstring__;
                                                                    ^
./test.m.hh:7:33: error: expected expression
const long __c2ffi___wur = __wur;
                                ^

Then it exits with status 1. While the output spec file looks like it might be usable, since c2ffi returns an error status cl-autowrap will fail on a simple c file that uses any system header. So I don't understand how a project like ZMQ4L can work? Is there a way to exclude entries in specific header files when creating the macro constants file?

spaceotter commented 3 years ago

I changed the script to use clang 11.0.1 as both the compiler and the source for headers. It prints a different list of errors every time I run it.

rpav commented 3 years ago

It's often necessary to specify system header paths, as c2ffi can only guess at the basics (or could... it's possible they've added API since but I haven't dived into it in a bit).

It looks like you're generating a "macros" header file, which will definitely cause a lot of errors. This is expected, since macros can be basically anything and there's no way to tell if it's a useful expression that evaluates to a constant in some context, or syntactic nonsense. Fortunately, clang will keep parsing and generally extract the useful values.

spaceotter commented 3 years ago

It makes sense that macros would be annoying like that. But, if this is the expected behavior, then cl-autowrap will basically always throw a condition in c-include. So I'm confused about how that's intended to be used.

rpav commented 3 years ago

Wait, is autowrap actually throwing an error? It should be ignoring error status, but perhaps there was a breaking change to some dependency. There was a recent change to c2ffi which let you explicitly fail on error, but that's not the default, and shouldn't be enable in autowrap either.

spaceotter commented 3 years ago

I updated quicklisp. This is with sbcl, ecl was behaving the same way, iirc. The testc.h file contains:

#include <stdint.h>

/* test.h - abbreviated from example */
typedef struct foo {
  int a, b;
  char c[3];

  struct {
    unsigned int b0 : 2, b1 : 3;

    struct {
      char x, y;
    } s;
  } x[2];
} foo_t;

foo_t* get_foo();
void free_foo(foo_t *foo);
int* get_int();

I added :error-output t to the run-check function so that I could tell what was going on. I have to add the working directory to sysincludes, or this happens:

CL-USER> (macroexpand-1 '(autowrap:c-include "testc.h" :sysincludes '("/usr/include" "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include")))
/tmp/tmpJXWE1HN2.tmp:1:10: fatal error: 'testc.h' file not found
#include "testc.h"
         ^~~~~~~~~
Skipping invalid Decl:
VarDecl 0x55c85becb410 </tmp/tmpV4YQ0HKA.tmp:1:1, col:12> col:12 invalid __c2ffi__POSIX_SOURCE 'const long'
; Evaluation aborted on #<UIOP/RUN-PROGRAM:SUBPROCESS-ERROR {1005D0D753}>.

If I do that (and erase the spec files):

Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1009AA9403}>
 with command ("build/bin/c2ffi" "/tmp/tmp4RNSVVC1.tmp" "-o"
               "/home/███/src/cifgen/testc.x86_64-pc-linux-gnu.spec"
               "-A" "x86_64-pc-linux-gnu" #1="-i" "/usr/include"
               #1#
               "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include"
               #1# "/home/███/src/cifgen")
 exited with error code 1
   [Condition of type UIOP/RUN-PROGRAM:SUBPROCESS-ERROR]

The value of ignore-error-status is NIL.

rpav commented 3 years ago

Ah, well, you probably need to tell it where to find testc.h .. it might work if it's in the cwd, but I don't actually remember. Also in your repo, it's test.hh if that makes any difference.

spaceotter commented 3 years ago

I created a different C test case because I assumed cl-autowrap wouldn't work with c++.

spaceotter commented 3 years ago

I guess this should be an issue on cl-autowrap. I'm experimenting with some changes to macro handling in my fork. https://github.com/spaceotter/c2ffi/commit/a5c974bd3f66e1bb22f1eefce9789e2cc14ff7ea