Full disclosure: total iOS development amateur here. My background is embedded firmware development.
TLDR: I'm trying to include a shared library, written in C, into a swift project, but getting "undefined symbols" errors
For a project, I'm trying to include a shared library written in C, that I manually cross compiled for ios-arm64 architecture (using xcrun -sdk iphoneos clang -arch arm64 on a macbook ), and I'm trying to include this into a swift based iOS application: as the most simple example let's take the default swift application you get when starting a new iOS application in xcode.
If I understand correctly, the way I should approach this, is adding a target framework to the project (Editor > Add Target > Framework ) and then dragging my shared library (let's name it libcustom.dylib) and my header (custom.h) into the target framework. And then adding this custom header into the framework header file. I also set the framework settings to embed & sign the shared library.
Next, I try to call a function in this shared library in the ViewController.swift file. So what I do is import the framework header and then call the function, let's call it perform_custom_action() (xcode editor also autocompletes it), but when trying to build I get the following error:
Undefined symbol: _perform_custom_action
So there is a linking issue, probably it's not linking the library, but I dont know how I can link it in this xcode environment. I see in the compile output that it includes the framework, but I dont know if this framework is correctly including the library...
Does anyone know how I can fix this?
PS: some sanity checks:
libcustom.dylib is cross-compiled for arm64, output of file libcustom.dylib is:
libcustom.dylib: Mach-O 64-bit dynamically linked shared library arm64
_perform_custom_action is part of the symbols inside libcustom.dylib, when executing nm libcustom.dylib I get
...
00000000005a544 T _perform_custom_action
...
EDIT: extra info:
When creating the target framework, a bridging header is automatically created, after adding my own header to it, it looks like this:
//
// custom_framework.h
// custom_framework
//
// Created by <user> on 13.01.22.
//
#import <Foundation/Foundation.h>
//! Project version number for custom_framework.
FOUNDATION_EXPORT double custom_frameworkVersionNumber;
//! Project version string for custom_framework.
FOUNDATION_EXPORT const unsigned char custom_frameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <custom_framework/PublicHeader.h>
#import "custom_framework/custom.h"
EDIT2: when manually setting linker flags, namely:
Library Search Paths : set to $(PROJECT_DIR)/custom_framework
Other Linker Flags : set to -lcustom
Then it builds succesfully, so to me it looks like something is wrong in the framework
Related
I'm trying to integrate 2 dynamic libraries (written in C) together with its API header (one header) into a xcode framework, let's call it nanogen_c, so that I can call its functions inside a swift application.
For this I'm creating a framework in xcode, build it, and then I would expect the framework to contain the symbols of the dynamic libraries, so that ultimately I can create a xcframework containing both the arm64 and x86_64 frameworks, and when including it in a project it would be able to link.
But when checking the symbols of the framework, it's (almost) empty:
% nm -gU nanogen_c
0000000000007ff8 S _nanogen_cVersionNumber
0000000000007fc8 S _nanogen_cVersionString
And so when creating an xcframework out of these, I get linking issues because the function symbols are not found in the framework.
I'm pretty sure I'm missing some step in building the framework, but I can't figure out what...
The steps I do to make the framework (here for the arm64 architecture):
Create new Xcode project > Framework called nanogen_c
Drag libraries and headers into the project
At pop-up : Check ‘Copy items if needed’
In project settings > Build Settings
Set ‘Enable Bitcode’ to No
Set ‘Build Libraries for Distribution’ to Yes
Set ‘Skip Install’ to No
In project settings > General > Frameworks and Libraries
Change ‘Embed’ options for both dylibs to ‘Embed & Sign’
In project settings > Build Phases > Headers
Move the API header to public
In nanogen_c.h framework header, append this line at the end:
#import "nanogen_c/<name_of_api_header>.h"
Set build target to ‘Any IOS Device (arm64)’
Press ‘cmd + B’ to build
Framework is built into /Users//Library/Developer/Xcode/DerivedData/nanogen_c-/Build/Products/Debug-iphoneos/nanogen_c.framework
Check contents of nanogen_c.framework, it contains the dylibs and header, but nanogen_c file doesnt contain the symbols from the dynamic libraries.
I know that the dynamic library itself contains all the necessary symbols, because when manually adding linker flags to the xcode project it succesfully links/builds, however this is no permanent solution because afterwards when trying to install the application to the iphone, the dynamic libraries are not installed with it.
Does anyone know what I'm missing?
I’m working on Xamarin and trying to install an iOS app on my iPad.
I want to link an Ada static library.
So I have a libMyLibrary.a + libgnat.a file and a C header code (MyLibrary.h).
In Xamarin, I created a binding library project and added my library.
In Xamarin, I added the above project as a reference to my iPad app.
To communicate with the library I used the P/Invoke with a DllImport(“__Internal”) and an assembly for my lib (so I don’t have any MTouch arguments) :
[assembly: LinkWith(“libMyLibrary.a”, SmartLink=true, ForceLoad=true)]
[assembly: LinkWith(“libgnat.a”, SmartLink=true, ForceLoad=true)]
But when I deploy it to the iPad I have a lot of native linking errors:
Native linking error: warning: could not create compact unwind for XXX does not use standard frame (MT5209)
I tried to use the monotouch arguments but no success:
-Wl,-no_compact_unwind ! see ld: warning: too many personality routines for compact unwind to encode and https://software.intel.com/en-us/forums/intel-math-kernel-library/topic/279914
LDFLAGS="-Wl,-no_compact_unwind : see https://bugzilla.mozilla.org/show_bug.cgi?id=1188030#c14
Any ideas?
Configuration:
iOS 10.3.2
Xamarin 6.3
Deployment target 10.3
After struggling around with this for a few days, we came up with something working.
The exact directives we've given to Monotouch are as follows:
-gcc_flags "-L${ProjectDir} -lMyLibrary -lgnat -force_load ${ProjectDir}/libMyLibrary.a -Wl,-no_compact_unwind"
Notice that :
the gnat lib file is put aside libMyLibrary.a
libMylibrarry is referenced twice in the command
And ... voilà !
Apprently, I didn't add it properly at the first time...
The error that Im running into is Undefined symbols for architecture arm64:. Below I have provided more in-depth screenshots. The source of the error according to Xcode is within the watchKit extension within the interfaceController. The Class is referenced from a dynamic library. If I actually CMD+Click the framework that Im importing Im taken to the framework in Swift thats fully ported over to Swift, it is originally written in Objective-C. The second image shows my import statement for the class, and the 3rd image shows how I have setup the import statements within the .h of the framework file.
On the right sidebar when those files are selected, under Target Membership, is your app (with the little pencil icon) checked as a Target Membership?
That should fix your problem.
It's look like dynamic library doesn't have arm64 architecture is it. In order to verify please use following command against the static library of your dynamic library.
lipo -info <libraryName>.a
Please make sure that library is added into extension target.
If your library is not static library, and it is framework like .framework, please follow following step.
1. Go to framework using cd command
cd /Users/<User>/<Path>/<Library_Name>.framework
2. Use ls command and list out all the files within framework file. You will see three files named as "Library_Name, Headers and Versions".
3. Use following command to display all architecture that library has.
lipo -info <Library_Name>
4. You can see list of all architecture that library was build for.
I read the tutorial on how to use core plot (http://www.raywenderlich.com/13269/how-to-draw-graphs-with-core-plot-part-1)
The project I am working on is written in swift.
I did everything to import the CorePlot library.
To make sure I did it right, I created a new objective C file and called
#import "CorePlot-CocoaTouch.h"
it worked in the test objective-c file (built without errors)
I then put the import statement in the bridging header file, and got 27 errors ALL saying '... the current deployment target does not support automated __weak'
From this post (CorePlot in Swift can not call “numberForPlot”),
I know I can make core plot work in my swift project somehow.
Can anyone recommend something ?
Thank you for helping.
I followed these steps to import the library :
Static Library Install
You can also just copy the Core Plot library directly into your project in binary form.
Copy the CorePlotHeaders directory to your Xcode project
Copy the Core Plot library to your Xcode project.
Open your apps Target Build Settings, and for Other Linker Flags include this:
-ObjC
(-all_load used to be required as a linker flag, but this is no longer needed in Xcode 4.2)
Add the QuartzCore framework to the project.
Add the Accelerate framework to the project (release 2.0 and later).
Change your C/C++ Compiler in the project build settings to LLVM GCC 4.2 or LLVM 1.6.
I am developing a iOS static library and use CoreLocation and MapKit framework within the static library. Xcode 5 with LLVM 5 has new build setting 'Enable Modules (C and Objective-C)' and 'Link frameworks Automatically'
These settings eliminate the need to add the dependent framework while including the static library in Target application.
However, this seems to be working only if '-ObjC' flag is added to other linker flags, even though the flag is unnecessary as I do not have Objective C categories to be loaded from static library.
You can find a sample project here (http://cl.ly/0Z1i1U1w3C3P) to try this out. Please let me know any suggestions. Is there any interconnection between -ObjC flag and new build setting in LLVM5?
Regarding Sample app:
There are two projects
1. libTest
2. StaticLibApp
Open StaticLib App and libTest is added as its subproject
libTest has class libTest.h and .m with a single class method +(void)check. Where I am trying to refer to CLLocation and MKMapView objects.
StaticLibApp compiles fine if the '-ObjC' flag is added to other linker flags, otherwise it raises a compile Error saying CLLocation and MKMapView class symbol not found.