On May 8, 2012, at 10:09 AM, Mike Pall wrote: > Sadly, it's not that easy to automatically generate the target > definitions. And the host compiler may not grok the target includes. > So one probably has to parse the output of $(CROSS)$(CC) -E and > grab only the needed definitions, but without all of the internal > cruft. Here's a snippet from preprocessor-fodder and a Makefile to go with it: ==== /* We would like to avoid including half the C library. Therefore lines generated between BARRIER1 and BARRIER2 are snipped from output. */ #include <stdint.h> #include <stddef.h> BARRIER1 #include <stdio.h> #include <errno.h> #include <math.h> [...] BARRIER2 /* We don't care about the internals of stdio, but some debug functions mention it. */ typedef struct { void*dummy;} FILE; extern FILE *stdin, *stdout, *stderr; #include "config.h" #include "libfoo/foostring.h" #include "libfoo/fooformat.h" [...] #include "lua-fooformat-const.h" ==== lua-foo.i: lua-foo.E $(CC) -x c -E $(CPPFLAGS) $(CFLAGS) $< | \ awk '/^BARRIER1/,/^BARRIER2/ {next} /^#/ || /^[ \t]*$$/ {next} {print}' >$@ ==== The contents of lua-foo.i are then suitable for feeding into the ffi parser. Wait, so what's that lua-fooformat-const.h file at the end? It exists because libfoo uses "#define FOO_MYCONST expr" a lot. It can *mostly* be mechanically generated: perl -l -n -e '/^#define\s+(\w+)\s/ && print "static const int l$1 = $1;";' $s/libfoo/fooformat.h >lua-fooformat-const.h This generates a lua-format-const.h containing: ==== static const int lFOO_FLAG_OPT_X = FOO_FLAG_OPT_X; static const int lFOO_FLAG_OPT_Y = FOO_FLAG_OPT_Y; ==== which the previous preprocessor stage will deal with. It is stupid; if you have #ifdef NEW_API #define FOO_FLAG_OPT_X 8 #else #define FOO_FLAG_OPT_X 10 #endif it will spit out two static const int lFOO_FLAG_OPT_X declarations. I hand-edited that file anyway to deal with other stuff. It seemed like less work than writing a smarter #define-reader. > With a cross-compiler you can't run the target > program. (This is so cute I can't resist posting about it over and over again.) This is not necessary in many cases, surprisingly. Autoconf gained this functionality when I wasn't looking. AC_LANG_BOOL_COMPILE_TRY will evaluate boolean expressions at compile time. http://git.savannah.gnu.org/cgit/autoconf.git/tree/lib/autoconf/c.m4?h=branch-2.59#n229 . The basic trick is to declare static int test_array[1 - 2 * !(your_boolean_expression)]; which is a compile-time error when it evaluates to declaring a negative length array. AC_COMPUTE_INT will just compile and run a printf() of an expression when compiling natively, but falls back to _AC_COMPUTE_INT_COMPILE when it's not able to run programs. In essence, it can use AC_LANG_BOOL_COMPILE_TRY to binary-search the integers for the value of the expression, one trial compilation at a time. http://git.savannah.gnu.org/cgit/autoconf.git/tree/lib/autoconf/general.m4?h=branch-2.59#n2462 is the actual implementation. Jay