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

Proposal: Add linkname in addition to linksection #19999

Open
ikskuh opened this issue May 19, 2024 · 8 comments
Open

Proposal: Add linkname in addition to linksection #19999

ikskuh opened this issue May 19, 2024 · 8 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ikskuh
Copy link
Contributor

ikskuh commented May 19, 2024

Right now, exported and imported symbols in Zig use verbatim the name that is given when using export fn/extern fn or use a much more complex scheme when using @export/@extern.

Problem

So if i want to export (or import) a function with another name than i want to have it in Zig, i have two options:

// import
extern fn SDL_CreateWindow(…) …;
pub const createWindow = SDL_CreateWindow;

// export
export fn SDL_CreateWindow(…) … {}
pub const createWindow = SDL_CreateWindow;

or

// import
pub const createWindow = @extern(
    *const fn(…) callconv(.C) …,
    .{ .name = "SDL_CreateWindow" },
});

// export
pub fn createWindow() callconv(.) … { … }
comptime {
    @export(
        createWindow,
        .{ .name = "SDL_CreateWindow" },
    );
}

Both options feel clunky when i only want to change the name of the emitted symbol, so a C library will have a nice prefixed variant that doesn't clash names, and the Zig variant feels way more ziggy.

Proposal

Thus, i propose introduction of a new keyword named linkname which is valid whereever linksection is valid which changes the way a function symbol is emitted internally:

// import
pub extern fn createWindow(…) linkname("SDL_CreateWindow") …;

// export
pub export fn createWindow(…) linkname("SDL_CreateWindow") … { }

Use Case

Ashet OS

Ashet OS uses dynamic linking as the primary kernel interface, and i keep my symbols nicely namespaced and grouped:

ashet.kernel.process.debug.write_log

which sadly leads to Zig code looking likes this:

pub extern fn @"ashet.kernel.process.debug.write_log"(…) void;

which doesn't really read well, and renaming all symbols manually is tedious and error prone

C Library Wrappers

Using wrappers in Zig is common and having a simple wrapper that would export SDL functions without SDL_ prefix would make the code much nicer to read:

- const window = sdl.SDL_CreateWindow(…);
+ const window = sdl.CreateWindow(…);

apigen

apigen will gain support for something like global_prefix SDL_ which adds this prefix to all exported/imported symbols.

This would allow making nice generated Zig "Headers" which do not expose this prefix on the API surface in Zig, making the usage and the reading/writing way more convenient.

@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label May 19, 2024
@Vexu Vexu added this to the 0.13.0 milestone May 19, 2024
@ikskuh
Copy link
Contributor Author

ikskuh commented May 19, 2024

Additional potential drive-by proposal by myself:

Replace extern "libname" fn func () T with extern fn func() linklibrary("libname") T, the extern "libname" always felt out-of-language

@Vexu
Copy link
Member

Vexu commented May 19, 2024

Replace extern "libname" fn func () T with extern fn func() linklibrary("libname") T, the extern "libname" always felt out-of-language

Could you make that a separate, easy to accept, proposal? That syntax often gets confused with C++'s extern "C".

@ikskuh
Copy link
Contributor Author

ikskuh commented May 19, 2024

Replace extern "libname" fn func () T with extern fn func() linklibrary("libname") T, the extern "libname" always felt out-of-language

Could you make that a separate, easy to accept, proposal? That syntax often gets confused with C++'s extern "C".

sure!

@kubkon
Copy link
Member

kubkon commented May 19, 2024

What does it boil down to on Windows? What will the linker see?

EDIT: actually, I should probably expand the question to "what happen on each platform". Do we get two exports, one being an alias for the other? Or is the primary definition a local, while linkname emits the global name? Or in MachO lingo, is the primary a private external visible only to the linkage unit?

@ikskuh
Copy link
Contributor Author

ikskuh commented May 19, 2024

What does it boil down to on (whatever)? What will the linker see?

Basically what you do is that you have a Zig symbol name and a linker symbol name. Right now, these are the same unless @export is used.
The linker will see whatever is written in linkname() while the programmer sees the other name.

@kubkon
Copy link
Member

kubkon commented May 19, 2024

What does it boil down to on (whatever)? What will the linker see?

Basically what you do is that you have a Zig symbol name and a linker symbol name. Right now, these are the same unless @export is used.

The linker will see whatever is written in linkname() while the programmer sees the other name.

Nice, ok, so there's no aliasing. In that case I am in favour of this change.

@hqnna
Copy link
Sponsor Contributor

hqnna commented May 20, 2024

I'm assuming this is similar to how Hare does linking?

export @symbol("glfwInit") fn init() void; 

which would link the init function to the glfwInit symbol from GLFW and expose it for use, similarly with this proposal

pub extern fn init() linkname("glfwInit") void;

would do the same, I imagine? I feel like this syntax would be a lot easier to understand than the status-quo.

@ikskuh
Copy link
Contributor Author

ikskuh commented May 20, 2024

I'm assuming this is similar to how Hare does linking?
</snip>
would do the same, I imagine? I feel like this syntax would be a lot easier to understand than the status-quo.

Yep! Exactly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

4 participants