#Linking error from a duplicate symbol, one imported from C

1 messages · Page 1 of 1 (latest)

gray ridge
#

I am new to zig, but am hoping to use it to consume a yacc generated parser. I'm using the very simple hoc1 language from Pike & Kernighan's "UNIX Programming Environment". Instead of the parser printing out the result, I have modified to assign the result to a global variable.

The grammar file is here: https://gist.github.com/cdcarter/cb64f5b28482f28c904119f9694d93f0#file-hoc-y
this results in the following hoc.tab.h header: https://gist.github.com/cdcarter/cb64f5b28482f28c904119f9694d93f0#file-hoc-tab-h
which I translated into zig with zig translate-c: https://gist.github.com/cdcarter/cb64f5b28482f28c904119f9694d93f0#file-hoc-zig
I then use those symbols in my main.zig: https://gist.github.com/cdcarter/cb64f5b28482f28c904119f9694d93f0#file-main-zig
finally, I build this all and used "addCSourceFile" to include the actual parser implementation: https://gist.github.com/cdcarter/cb64f5b28482f28c904119f9694d93f0#file-hoc-tab-c

This results in:

% zig build                                                                                  
MachO Flush... error(link): symbol '_result' defined multiple times
error(link):   first definition in '/Users/cdcarter/hoc/zighoc/zig-cache/o/e854fcc73548dd9fd6af4076f010bf6c/hoc.tab.o'
error(link):   next definition in '/Users/cdcarter/hoc/zighoc/zig-cache/o/c63d0ae58538b1896e72d0d704793ff4/zighoc.o'
error: MultipleSymbolDefinitions
error: zighoc...

I know I'm not doing anything too complicated, but I'm not sure where to turn next to debug this. hoc.tab.c, the C source for the parser, does not define result, its defined in the header file that I dutifully translated to zig.

I assume my mental model of importing from C is broken, but I can't figure this one out. Any advice would be appreciated!

Gist

GitHub Gist: instantly share code, notes, and snippets.

#

I tried to switch to @cImport instead of running translate-c...

const std = @import("std");
const c = @cImport({
    @cInclude("hoc.tab.h");
});

pub fn main() void {
    std.debug.print("Result: {d}\n> ", .{c.result});
    _ = c.yyparse();

    std.debug.print("Result: {d}\n", .{c.result});
}
```, but this instead resulted with the compile failing entirely
```/Users/cdcarter/hoc/zighoc/main.zig:2:11: error: C import failed
const c = @cImport({
          ^~~~~~~~
referenced by:
    main: /Users/cdcarter/hoc/zighoc/main.zig:7:42
    comptime_0: /opt/homebrew/Cellar/zig/0.10.1/lib/zig/std/start.zig:59:50
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
```.
Adding `-freference-trace` results in no additional reference.
hasty vault
#

The error is correct, result gets defined in the c obj and zig obj - what might be a solution
in hoc.zig

- pub export var result: f64 = 0;
+ pub extern var result: f64;
gray ridge
#

oh, sigh, of course! manually editing the generated zig works fine. and now that I think about it, of course I need to separate the definition and declarations of the symbol in the yacc, even if this were C.

thanks for pointing out the obvious. now we're off!

#

Manually modifying the generated zig worked, but even if I try to just declare result in the c but never assign a 0 to it, the zig is now generated as

pub export var result: f64 = @import("std").mem.zeroes(f64);

I wonder what C I need to craft to get the translator to give me the right zig...I probably won't worry about it much for now because I have something that works.

hasty vault
#

the proper way to do it is to extern double result; in the header and double result = 0; in a single c file (otherwise you'd be defining a result every time you include the (translated) header)

gray ridge
#

Yep, that does it! curiously, the cImport version still fails. but the translate works perfectly, thank you!

hasty vault
#

that's because cImport requires the file to be in within an -I
(exe.addIncludePath("./src"); if using build.zig)