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

exportc symbol not exported, leading to link error #11651

Closed
timotheecour opened this issue Jul 4, 2019 · 3 comments

Comments

@timotheecour
Copy link
Contributor

commented Jul 4, 2019

exportc symbol is not exported in some cases, leading to link error. This seems to occur only when the proc body is disabled via conditional compilation (eg via when false_condition: foo or similar).

Example

# fun1.nim
proc myfun() {.importc.}
proc myfunWrap*() = myfun()
# main.nim
import ./fun1

proc myfun() {.exportc.} = # ditto with {.exportc, dynlib.}
  # discard # works
  when false: discard # has the BUG

proc main() = myfunWrap()
main()

Current Output

nim c main.nim

Undefined symbols for architecture x86_64:
  "_myfun", referenced from:
      _myfunWrap_i40p9axSiEKMrYIQZ70IbKw in fun1.nim.c.o

Expected Output

should compile and link

Possible Solution

looks like when the body is disabled (eg via when false: foo) the exportc symbol is not exported; it works with an empty discard; looks like a codegen bug

Additional Information

  • Your Nim version (output of nim -v).
    tried 0.18 through 0.20 + latest devel 0718d6c; all versions have that issue
    (on osx but shouldn't matter)

  • A link to a related issue or discussion.

I use this pattern (importc+exportc) as a workaround for lack of cyclic imports (as discussed here https://forum.nim-lang.org/t/4004#24925), which allows me to reduce dependencies between certain key modules; actually the pattern I use is a bit more sophisticated and allows to also skip type definitions using some macro magic. The reduced bug above is what I had encountered here: https://forum.nim-lang.org/t/4004#24925 (how to forward declare a proc in module A and define it in module B?)

I currently have to work around this bug by adding dummy calls to the exported procs.

@Clyybber

This comment has been minimized.

Copy link
Contributor

commented Jul 4, 2019

Does

proc myfun() {.exportc.} = # ditto with {.exportc, dynlib.}
  # discard # works
  when false: discard # has the BUG
  else: discard

work?
I think the original snippet should error, since after evaluating the when condition the proc will have an empty body, which Nim normally doesn't allow.

@timotheecour

This comment has been minimized.

Copy link
Contributor Author

commented Jul 4, 2019

I think the original snippet should error, since after evaluating the when condition the proc will have an empty body, which Nim normally doesn't allow.

it's perfectly legal:

proc myfun() {.exportc.} = when false: discard
myfun()

Does [...] work?

ya but my example was a reduced case, in more complex examples it's trickier, eg the original issue I encountered happened when the body was a template eg:

template myThirdPartyFun() = # maybe defined in another imported module over which I have no control
  when someCondition: foo1

proc myfun() {.exportc.} =
  myThirdPartyFun()
@timotheecour

This comment has been minimized.

Copy link
Contributor Author

commented Jul 4, 2019

=> PR #11658

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