Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't compile a simple dynamic library #2173

Open
ul opened this Issue Apr 3, 2019 · 9 comments

Comments

Projects
None yet
3 participants
@ul
Copy link
Contributor

ul commented Apr 3, 2019

I started to write a simple LV2 plugin in Zig. Because I'm a novice in both, I do it step by step and try to build regularly to catch compilation errors early. I stuck while trying to export the first function required by LV2 API:

const lv2 = @cImport({
    @cInclude("lv2/lv2plug.in/ns/lv2core/lv2.h");
});

const std = @import("std");
const allocator = std.heap.c_allocator;

const PortIndex = enum {
    Gain   = 0,
    Input  = 1,
    Output = 2,
};

const Amp = struct {
    gain   : *const f32,
    input  : [*]const f32,
    output : [*]f32,
};

export fn instantiate(
    descriptor  : *const lv2.LV2_Descriptor,
    rate        : f64,
    bundle_path : [*]const u8,
    features    : [*]const *const lv2.LV2_Feature
    ) lv2.LV2_Handle {
        return @ptrCast(lv2.LV2_Handle, allocator.create(Amp) catch null);
}

When I try to compile it with zig build-lib src/main.zig --name simple-amplifier --ver-major 0 --ver-minor 0 --ver-patch 1 -dynamic I get compiler crashed with the following error:

TODO implement get_c_type for more types
fish: “zig build-lib src/main.zig --na…” terminated by signal SIGABRT (Abort)

For my inexperienced eye code snippet looks innocent and very familiar to how functions are exported in documentation examples.

Would you mind helping me to get it work?

@ul

This comment has been minimized.

Copy link
Contributor Author

ul commented Apr 3, 2019

Played with it a little bit and it looks like that problem is with

descriptor  : *const lv2.LV2_Descriptor,

when I make its type just *c_void it compiles fine.

@ul

This comment has been minimized.

Copy link
Contributor Author

ul commented Apr 3, 2019

Okay, it seems that LV2_Descriptor has function pointer fields and functions are not supported yet

zig/src/codegen.cpp

Lines 8829 to 8830 in 85edf55

case ZigTypeIdFn:
zig_panic("TODO implement get_c_type for more types");

Are there any plans to fix it soon?

@andrewrk andrewrk added this to the 0.5.0 milestone Apr 3, 2019

@andrewrk

This comment has been minimized.

Copy link
Member

andrewrk commented Apr 3, 2019

Thanks for the report. High level, what's going on here, is that although this is one of the central, important use cases for zig, you're actually sort of the first person (that I know of) actually exercising the use case. So you're pioneering the path. I appreciate that you're taking the time to report issues.

This is a problem with Zig's .h file generation code not supporting functions yet. This is actually quite contributor friendly if you are interested in helping decide exactly how zig should generate .h files for libraries. So that's one approach you could take to move forward on this. That particular panic would be fixed if we teach Zig what to put in .h files when exporting a function.

Another approach you can take is to simply disable .h file generation. I tried your example with --disable-gen-h and the panic disappeared.

@ul

This comment has been minimized.

Copy link
Contributor Author

ul commented Apr 3, 2019

Thank you for the detailed answer! I will go with --disable-gen-h for now as I don't really need a header for this dynamic library.

I'm afraid that I'm not competent in C enough even for such simple task as header codegen, but I'll give it a go one of the weekends.

If you don't mind, one more related question: is it possible to mark a function as C ABI compatible but not export it? For example, instantiate is not supposed to be called by the host by name, but rather by pointer to it which is returned as a part of LV2_Descriptor from the only exported entry point lv2_descriptor.

@andrewrk

This comment has been minimized.

Copy link
Member

andrewrk commented Apr 3, 2019

is it possible to mark a function as C ABI compatible but not export it?

Yes, that is generally what the extern keyword does. See:

// this function is guaranteed to have the C ABI but is not exported (unless you use @export)
extern fn foo() void {
    // ...
}

ul added a commit to ul/zig that referenced this issue Apr 3, 2019

handle LibExeObjStep.disable_gen_h
It is sometimes useful to skip generating of the header file (e.g. ziglang#2173), and zig compiler provides an option `--disable-gen-h` to control that behaviour. However, setting `lib.disable_gen_h = true` in a typical `build.zig` didn't append the option to arguments. This commit fixes it and adds a convenient `setDisableGenH` setter.

andrewrk added a commit that referenced this issue Apr 3, 2019

handle LibExeObjStep.disable_gen_h
It is sometimes useful to skip generating of the header file (e.g. #2173), and zig compiler provides an option `--disable-gen-h` to control that behaviour. However, setting `lib.disable_gen_h = true` in a typical `build.zig` didn't append the option to arguments. This commit fixes it and adds a convenient `setDisableGenH` setter.
@ul

This comment has been minimized.

Copy link
Contributor Author

ul commented Apr 4, 2019

I published my simple example just in case someone else will find the idea to build LV2 plugins using Zig exciting as I did and will be interested in some bootstrapping: https://github.com/ul/simple-amplifier

@emekoi

This comment has been minimized.

Copy link
Contributor

emekoi commented Apr 4, 2019

how would you determine if a type had been exported already?

@andrewrk

This comment has been minimized.

Copy link
Member

andrewrk commented Apr 4, 2019

It's a compile error to export the same name twice. So you can't do it on accident. And then have a single canonical place where that thing is exported (or not). Zig's declarative top level declarations should make that easy.

@emekoi

This comment has been minimized.

Copy link
Contributor

emekoi commented Apr 5, 2019

i mean for the functions, so you can tell if a return or parameter type needs to be exported. or would that be a compile error?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.