2

The app I've been working on uses an external library, pdlib, which has it's own externals (.c files) which I've been importing via the bridging header #import "Uzi.c" and calling in my main Swift file via Uzi.c's setup function Uzi_setup() in my ViewController class. I've had no problem with this until after updating to new public Xcode 8 a few days ago (I had no problem with Xcode 8 Beta 1 over the Summer).

Here are the 7 errors I get, listed under a single "Mach-O Linker Error" umbrella:

Undefined symbols for architecture x86_64:
"_Uzi_bang", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_class", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_float", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_new", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_pause", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_resume", referenced from:
  _Uzi_setup in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Those undefined symbols are 6 functions and a class declare from Uzi.c. Here's a link to the whole c file: https://github.com/electrickery/pd-miXedSon/blob/master/hammer/Uzi.c

I've tried every solution I've found online for dealing with similar problems, with no solution yet... I tried changing the "Architecture" and "Valid Architecture" settings to only armv7 and armv7s (no arm64) and changed "Build Active Architecture Only" to "No". These step seem to help others in similar situations, but they didn't work for me (and taking away arm64 causes additional errors to appear).

XCode 8 is pretty recent (the public version was released Sept. 13), so there are virtually no other questions about this upgrade causing a similar problem.

Any help would be greatly appreciated!

PlateReverb
  • 654
  • 1
  • 7
  • 21

1 Answers1

0

Solved by @danomatika on GitHub: https://github.com/libpd/libpd/issues/149

"You generally shouldn't include/import an implementation file aka .c, .cpp, .m, etc. This is what is causing the duplicate symbol issue.

This is what the "forward function declaration" in the header file is for: to tell the compiler that a function exists and what data it takes/returns. The compiler then assumes the actual implementation of the function exists in an implementation file. If it can't be found, then you get an "undefined symbol error." If you somehow end up declaring the function twice, aka include both a header with the forward declaration and the implemetaton of the function itself in the .c file, then you get a "duplicate symbol error."

This is all lower-level stuff that is only really an issue since Pd externals are designed around being dynamic libraries, so are not built or provided with headers which include the function declarations. This is why you have to do a little extra work and do it yourself.

Their are two easy fixes for this, both of which involve declaring the required function you want to call from the .c file in a header file.

  1. Simply declare the function in the bridging header:

    void uzi_setup();

  2. Create a header, say Externals.h, and declare all of the externals stuff there:

    // forward declare setup functions only found in .c implementations void uzi_setup();

    // convenience wrapper function void externals_setup() { uzi_setup(); }

    Then import the file in your bridging header:

    #import "Externals.h"

    And in swift, you can now do:

    externals_setup()

PlateReverb
  • 654
  • 1
  • 7
  • 21