May 10, 2021

On Sunday, 9 May 2021 at 19:35:52 UTC, Gavin Ray wrote:

>

However, I had an idea which I haven't seen tried yet, and have been prototyping:

  • Using cppyy in Python (which uses cling) for runtime bindings to C++ and ability to write raw C++ code in Python strings and JIT compile it.

  • Allow users to write "drivers"/"clients" in Python which do the codegen. Since Python isn't compiled, this means you can realtime tweak and visualize your output much faster than manually recompiling a C++ based LibTooling application.

I am thinking of some kind of API where you can declare rules using annotations for AST nodes above functions for handling them. Something like:

class DCodegen:
    # "t" here is a LibTooling AST node and we can use all of Clang/LibTooling's AST API
    @rule(lambda t: t.is_pointer() or t.is_reference() and \
                    t.pointee().is_record_indirection())
    def input(cls, t, args):
        return f"{{interm}} = &{c_util.struct_cast(t, '{inp}')};"

    @rule(lambda t: t.is_pointer() or t.is_reference())
    def input(cls, t, args):
        raise ValueError("unsupported input pointer/reference type {}".format(t))

This would allow people to contribute or tweak the codegen to their liking very rapidly.

It's all libclang under the hood though. Never looked at the sources of cppyy or cling, but very likely this works for them because of libs such as pybind11 that wraps C++ stuff in C++, while the other tools trying to rely on C API(very limited) or keep fighting with C++ API, you've already seen that all that tools from that list except gentool is using C API and what capabilities each provides.

Can't say I hate that idea, but it has same issues as SWIG, writing any non trivial rule becomes next to impossible as there is practically zero examples and very poor documentation, the whole process becomes trial and error marathon without chance to win, and it is basically write-only code that is as worse as C++ templates. But it is definitely better than SWIG in that regard as you can get type and functions information using dir() and help() and your trusty IDE with debugger.

My current plan though is to provide predefined pre-generate and post-generate rules that is applied declaratively in project config,
for example
ignoreDecls *::new[]
that will ignore all new operator overloads in any namespace, or one of any other existing rules that deals with specific patterns, and at some point later allow users to write their own rules like you described.
After all this is binding/translator tool, not an universal one-for-all code generator.

>

For distribution, it could be done in an Ubuntu Docker container that comes with LLVM and Python in it, and the scripts, then mapped to local filesystem for read access + also if you want to edit the DCodegen script or supply your own Python file as the driver.

No way, Docker is too heavy and not very user friendly or even CI friendly. It is ok to have builds optionally packed in container, but not as the only way to distribute. It might work for cppyy/cling because they rely on specific dynamic library properties or fork process on *NIX that is not there on Windows.

May 10, 2021

On Monday, 10 May 2021 at 07:11:26 UTC, evilrat wrote:

>

Can't say I hate that idea, but it has same issues as SWIG, writing any non trivial rule becomes next to impossible as there is practically zero examples and very poor documentation, the whole process becomes trial and error marathon without chance to win, and it is basically write-only code that is as worse as C++ templates. But it is definitely better than SWIG in that regard as you can get type and functions information using dir() and help() and your trusty IDE with debugger.

Yeah, this is true. I actually ran into this issue already -- you have extreme devspeed + flexibility with Python but you're essentially "blind" as to the API and it's a lot of trial-and-error if it's not a very trivial C++ library.

I think the end goal of being able to provide some way to easily hook into the codegen pipeline so that users can make tweaks easily & contribute them back, or customize it for personal use is probably more important than the "how". This was just the best "how" I could come up with at the time, hah.

>

My current plan though is to provide predefined pre-generate and post-generate rules that is applied declaratively in project config,
for example
ignoreDecls *::new[]
that will ignore all new operator overloads in any namespace, or one of any other existing rules that deals with specific patterns, and at some point later allow users to write their own rules like you described.
After all this is binding/translator tool, not an universal one-for-all code generator.

What about adding cling for interpreted JIT C++ without handicaps?

https://blog.llvm.org/posts/2021-03-25-cling-beyond-just-interpreting-cpp/

This would let both you and users rapidly develop/iterate-on the codegen part without needing to recompile the entire solution.

The main application hosts the cling process, and you don't do anything except bring the codegen bits in as JIT-interpreted files. It's not like performance is critical here, you know?😅

The end result is that you (or anyone else) can modify the actual codegen code, and re-run the compiled binary without needing to do anything else. cling will take care of acting as the engine to sort out #include's, template instatiations, global context, etc.

I dunno, I don't really know that much about this area at all. So there's also a good chance this idea couldn't/wouldn't work, and is not a good one -- but in my naive head it sounds good!

>

No way, Docker is too heavy and not very user friendly or even CI friendly. It is ok to have builds optionally packed in container, but not as the only way to distribute. It might work for cppyy/cling because they rely on specific dynamic library properties or fork process on *NIX that is not there on Windows.

Yeah, so the issue there was that cppyy needs dynamic libs to be able to work.
LibTooling hilariously enough can't even be compiled as a dynamic lib on Windows, since there's a limit of ~65,000 exported visible symbols and LINK.exe will error.

So between wanting the user to have a fairly recent, self-compiled version of LLVM, and not working on Windows at all, the easiest thing seemed to be to ask "Hey, just do docker run and that'll run an Ubuntu image with LLVM 13 built with LLVM_ENABLE_SHARED_LIBS and Python 3 and all of this set up for you."

Not ideal but also I think maybe the only way to make the cppyy thing work haha.

1 2
Next ›   Last »