I'm having trouble linking to a static library in Xcode 5. I did read the chapter on building and using a static library in the Pro iOS 5 Tools. What it told me to do after creating your static library, was to link against the framework in the Build Phases tab. That part is pretty straight forward. Then it says in the Build Settings, under "Header Search Paths", to add:
$(BUILT_PRODUCTS_DIR)
Then in order to use my static library, I just import it like so:
#import "ConversionCalculator/ConversionCalculator.h"
So this used to work up until yesterday. I tried adding a new static library to my project which didn't seem to work. So I cleaned my project, and tried rebuilding again, but now Xcode complains about #import "ConversionCalculator/ConversionCalculator.h". It says
Lexical or Preprocessor issue. 'ConversionCalculator/ConversionCalculator.h' file could not be found.
I was wondering if anyone has any tips on debugging this. I've looked through different tutorials like this:
http://blog.stevex.net/2012/04/static-libraries-in-xcode/
http://cocoamanifest.net/articles/2011/06/library-management-with-xcode-workspaces.html
http://www.raywenderlich.com/41377/creating-a-status-library-in-ios-tutorial
But I can't seem to find the "golden way" to link to a static lib, or how to troubleshoot why Xcode cannot find my file. My file structure is setup on my machine like so:
Projects\
DistanceCalculator\DistanceCalculator.xcodeproj
ConversionCalculator\ConversionCalculator.xcodeproj
DistanceCalculator.workspace
Like I said, this all used to work too when I followed the tutorial in Pro iOS 5 Tools book. Now I don't know why my workspace cannot find ConversionCalculator when it has used it before. The part I find hard is different articles say different things about the header search path, and I'm not sure what the best way to populate that field is. Any thoughts? Thanks in advance!
Edit:
I'll add that I can build for the device without errors. But when I switch to the iPhone simulator, it gives me that error about not being able to find the file. I also see that I get this warning:
ConversionCalculator was rejected as an implicit dependency for 'libConversionCalculator.a' because its architectures 'i386' didn't contain all required architectures 'i386 x86_64'
Looking at that, I'm not sure what that means. If it means that my library is not being built for all architectures, I just tried creating a Target that builds for all architectures according to the wenderlich article in the above link. That seems to work as when I go to the dervieddata folder, I see for debug, release, and universal, I see the libConversionCalculator.a file. But then when I go back into the workspace and try to rebuild the project for the simulator, I get that could not find file error and the implicit warning.
Edit #2:
I just saw a warning flag on Xcode that says upgrade to recommended Build Settings. Now I get no errors. Not sure what happened... but I guess no errors is good.
I would follow the description available in Xcode's Help topic "Linking Against Your Library" in chapter Configuration Your Application in Introduction to Using Static Libraries in iOS
(you may search within Xcode Help, too).
Except that I would recommend to include your headers from libraries always using angle brackets:
#import <ConversionCalculator/ConversionCalculator.h>
Using double quotes may inadvertently search and find files with the same name in some sub-folder relative to the file where this import directive is written. Only after there was no file in any sub-folder the preprocessor starts searching with the specified header search paths.
Using angle brackets, the preprocessor immediately searches only at the specified header search paths.
So, since you actually want to find headers for the corresponding library, always use angle brackets.
Note: If you follow the recommendation to create a static library project, you don't need to explicitly set a header search path in the target that links agains the library: Xcode will already add a search path:
$(BUILT_PRODUCTS_DIR)/includes
Your library headers are located in
$(BUILT_PRODUCTS_DIR)/includes/<product-name>
which are placed there through the "Copy-Files" phase of the iOS static library target, whose "Destination" is set to "Products Directory" and whose "Subpath" is set to "includes/${PRODUCT_NAME}" per default.
You may change these default settings to other reasonable and sensible values. (if you do, consider the the consequences for Xcode's default search paths!)
Related
From the beginning of my project, I use a custom framework, let's call it "custom.framework". But there was a bug in this framework and now I want to use another version of the "custom.framework".
At first, I simply removed the "custom.framework" file from my project and added the new one. But nothing changed, the bug was still there.
After multiple tries and hours, I understood that Xcode add the old version in memory and used this one instead of the new version. I know it because in the new version I added a method and when I cmd+click the class I've add the method into, it's not there and the file's path is unavailable.
Searching through the web, I tried to change some version parameters to my framework projects: Compatibility version, Curent Library version, Framework version. But this didn't change anything to Xcode which keeps using the old version.
I also tried to make the framework's project as a sub-project and add resulting framework as a dependency to my target. It worked well, but as the framework's project is on a separated remote git repository, I don't think this is an acceptable solution.
So my last try was to build a "custom2.framework", to force Xcode to use the real file and not some cached version. But again, it doesn't work and when building I get errors telling me that all my classes in custom2.framework are duplicated symbols of its cached version of "custom.framework".
So my question is simple: how can I finally tell Xcode to deleted its cached old version and let me use the file I gave him? I already tried to delete my project's derivedData but it seems cached frameworks aren't there.... I'm so desperate :(
Edit: Here are 2 screenshots to illustrate the issue
First screenshot is the path as shown by Xcode when I opened the file from the .framework object in the project navigator.
Second screenshot is the path as shown by Xcode when I opened the file from a cmd+click to a "DCEquipmentManager" in code.
As you can see, the framework linked with the code is not the framework in the project.
it seems problem with binding in new framework, your project still linked with old framework files.
try to remove all files and folder related to your "custom.framework and also remove path for that framework from project setting--> build setting --> search Path
Then after Drag and Drop Your "custom.framework" files in project.
it works for me.hope it resolve your problem.
Please try to clear derrived data:
Window -> Organizer
at the right side you will see projects list. Find your project and tap on it. I the top part of window you will see button delete in front of Derrived data, tap on it.
I guess it will solve your problem.
It might sound silly, but sometimes restarting XCode or the whole machine fix things.
Did you remove the old framework from Build Phases --> Link Binary With Libraries?
Use Clean Build Folder: option-shift-command-K, or select it from the Product menu when holding down the alt/option key.
First lets say something upfront. The build stage is a(are) command line tool(s) that is managed by Xcode according to your Build Settings.
So when Xcode doesn't find your Framework - the Build System will usually also not find it. This forces you to act but may end up in confused Xcode to catch an older reference.
Yes it may happen that the Header Xcode is pointing to is correct but the build system still uses an old copy somewhere. An outdated copy can dangle around literally anywhere depending on the steps you took before.
It (Xcode) assumes where it is located but the Build System still uses another version or the Search Paths just pointing in the wrong Locations even if they are visible to you and even your Framework icons are visible in the lists. So when you erase the last build you actually only force Xcode to rebuild from the known arguments, the settings stay the same, the lists stay the same. Even restarting Xcode does not change anything, the problem persists.
Ergo: Compiler Instructions, Xcode settings and Build System settings don't match what the code tells with #import <NAME/Name.h>
So you will check at least those 6 stages again:
Is your Framework Header File published in your Framework project?
are Build Settings really pointing to the right Framework Search Paths or System Framework Search Paths?
Is your Framework in linking list?
Is your Framework in Embed Framework list?
Does your framework appear in the Framework Group Folder in Workspace/Project Browser? (usually the very last Group Folder in the Browser below all your other files)
Is my Folder Structure correct?
At least 1 to 4 must be right otherwise it will fail.
Here a random list of common causes
Framework is located outside your Source Paths structure
Structure got changed after you added it to the project
You use Workspace's where Framework development and Final Application can appear side by side but you assume Xcode uses this to change its Search Paths
The contained build settings are misleading from former drag and drop operations, ending up tricking Xcode in the "wrong" corner. In this case recreating a project is just one of the possible ways to fix it but not the solution.
Also dragging a Framework into your Project > General or separated in Build Phases > Link Binary list or Embed Framework lists does not make Xcode aware of the wrong Build Settings.
The Linking works, embedding works, but compiling does not. The Header information is still missing.
The solution must be to correct your Build Settings.
As mentioned above Build System and Xcode are two different things. In particular only setting the right Framework Search Paths will solve those issues, even if you managed to kick your derived data manually.
Erasing Derived data?
Derived data is the place where precompiler collects data to compile. So it can be seen as expression of what all the settings are told to do. Erasing it does of course not change the settings but may fix inconsistencies related to former Build Settings. It would erase the derived data and rebuild from the Build System Settings you gave.
Correcting Linking?
Also Linking is not the same as making Xcode aware of the desired Headers. Linking is for your final Product to know where Symbols are to call on them at runtime, it does not change Framework Search Paths and System Framework Search Paths, they stay the same as given.
But it is not wrong to start fixing first with
Product > Clean Build Folder, it forces your build to parse all and compile all again on the next Build.
When the troubles come up because of folder structure in parallel or Frameworks are simply placed outside the Source Directory then you must point to them directly or relative.
Most likely you should place one extra entry in your Framework Search Paths like $(SRCROOT)/../Yourframeworksource/build/Debug. expression to point to relative higher folder structure.
Needless to say that a Release Build likely needs another entry ending in "/Release".Hint: Well you can have different Search Paths for different Compile Schemes..
This works particular good after you cleaned Linking List, Embed Frameworks List and then also check the very last Group Folder "Frameworks" for double entries to drag and drop a fresh Framework reference in there.
How to know if leading /../ will fix it?
Click on the dropped Framework Icon inside the workspace Framework Group Folder (lower most) while your Project is the active selected to work on, now watch for the relative Path information on the very upper right side of Xcode, if there is some /../ you know you need it as well.
Sorting of Framework Search Paths
play a role of course, just the same as #import/#include rule sorting matters.
Remember the first found, first wins rule because often we use #import that works different then #include but ignores second attempts to declare. This leads to once wrongfully declared headers to hide corrected declarations later on in parsing that share the same filename or define rules
#ifndef xyz
#define xyz
// all your code here.
// a second read attempt would be ignored
// a second read is hidden also when you use #include then.
#endif
So you can sort those entries either by code and/or in the build settings if needed because of course it matters what is declared before other declarations depend on it.
When I'm writing simple code in ViewController, I wanted to run it and boom. Apple Mach-O linker error as shown. I don't know what is the problem. Then, I've made a quick research, according to research; I deleted Derived Data folder, I deleted Derived Data folder contents, I deleted test hosts in build settings(it is already empty), I cleaned the build folder and I applied clean action. But nothing changed same errors. Is there any specific solution of this error depends on app and what is that solution?
EDIT:
I moved the codes to a new xode project and I noticed that when I add the line let ftp = CkoFtp2(), the error occurs otherwise it compiles. But it is coloring the CkoFtp() part of line and I'm not getting any specific errors there. Just Match-O and linker command.You can see the CkoFtp2 code here.
I had the same issue. Please make sure to follow the directions on chilkat's site, particularly the following:
Add libChilkatCocoa.a to your list of libs for linking. In your project build settings, find Build Phases, Link Binary with Libraries, select Add Other, navigate to the libChilkatCocoa.a, and add it.
The Chilkat library internals are written in C++. Therefore, your Swift application will need to link against the C++ runtime libraries. In your Build Settings, go to the Linking section and add -lstdc++ to the Other Linker Flags.
https://www.chilkatsoft.com/chilkatSwiftCocoa.asp
I also ran into trouble because the libChilkatCocoa.a library resided in a folder that had a space in its name. Avoid that, or make sure it is correctly escaped under Build Settings.
Looks like you've got a reference to a framework located in your Downloads folder. Chances are you moved that somewhere else, yes? Remove the SimpleUnzipper framework from the project and re-add it from wherever you moved it to.
After the edits, this is clearly not the problem...
It's hard to tell from just the error message, but it appears that you're using a library that you downloaded from another developer. Are you sure you followed their instructions for setting things up? The linker error means that you're not linking your program with the library, though it looks like you've managed to set up a bridging header so that you can call the function without getting a compiler error.
First of all, my project builds fine initially.
Then I integrate VideoStream SDK for iOS into a standalone app, and it works.
Then I integrate VideoStream SDK into my actual project, and set up search paths for header files for the library, but then my project gets these issues:
I'd have a look if one of your source header files has the same name as a standard C++ or C header file. Quite possibly this prevents inclusion of the standard header file that defines struct tm. Look if there is a file "time.h" or "locale.h" or something like that has become part of your project.
I have not seen this solution posted ANYWHERE after so much time googling since the time I posted, but I disabled Always Search User Paths under Search Paths of Build Settings, and the project built.
Base on this question
Why don't iOS framework dependencies need to be explicitly linked to a static library
I read the selected answer and still don't understand so I made an example project
Test Project on Github
In the test project, I remove all framework from Link Binary With Libraries and File navigation for both main project and the static library (including Foundation.framework and UIKit.framework too), basically, both project link to 0 frameworks.
Questions are
In static library, it's including MapKit/MapKit.h without referencing the Mapkit.framework to the project, why is its still working?
In main project, I remove UIKit.framework and Foundation.framework from the project, why is it still working?
Since it's working for now, will there be any issue later?
Thank you for your comment.
P.S. By working, I mean I can run on the simulator and I can archive the main project without any error.
Edit 25/07/2014
I tried with the real app that I'm working on, it's the same.
I highlight Foundation, UIKit, CoreData and 10 another frameworks in File Navigation, well, all of them.
Uncheck the target in Utilities Panel --> Target Membership
Build : Pass, Run : Pass
Every functionality of my app is still working as expected. I don't get this.
Check your project build settings. Underneath LLVM 5.1 — Language — Modules you should see the option 'Link Frameworks Automatically'. In your case it sounds like it's set to 'YES', the default.
In that case, instead of producing an error when you reference a class that the compiler doesn't know, it'll figure out which Framework contains that class and link it. In your code it'll be MKMapView or one of the other MapKit classes that triggers the linkage.
EDIT: from the relevant 'What's New?' document:
Auto Linking is enabled for frameworks imported by code modules. When
a source file includes a header from a framework that supports
modules, the compiler generates extra information in the object file
to automatically link in that framework. The result is that, in most
cases, you will not need to specify a separate list of the frameworks
to link with your target when you use a framework API that supports
modules.
Another way of looking at it is that the compiler is smart enough to mutate #import to #import when the framework has been built appropriately. All system frameworks have been.
To elaborate #Tommy's answer, a framework that supports modules satisfies the following 2 conditions:
Under Build Settings > Packaging
Define Modules is set to YES
Module Map File exists.
So, if you're certain that the framework you're using in your code modularizes like that, you can choose to not explicitly add it in the link phase as it will be automatically added as long as in the project file, under Apple Clang - Language - Modules, The option Link Frameworks Automatically is set to YES.
So im trying to use the route-me widget in my app, but xcode keeps complaining that it cant find FMDatabase.h, yet its included in the project (albeit under a different project that is included into my project). I've copied how a sample app has been made yet the sample project doesnt get this error. The RMDBMapSource.h file is contained within the MapView project, so i shouldn't need to include the fmdb stuff myself (and because the sample project doesn't do that)
Surely if the files are under compile sources / copy headers under build phases, that means it should be able to find the file? This is a pretty lackluster explanation of my problem, but if anyone has used the route-me library before maybe they have had the same problem and can point me in the right direction
Resolved my own mistake. First off in the build settings of the main project, the 'search for header paths' was not set correctly, it was set to /MapView/ instead of /MapView/** that resolved the FMDatabase.h missing error.
Then in case someone else had a linker error like i did after i resolved the first issue, make sure you have libMapView.a included in your link binary with libraries section. (i had it their before, but during a version control commit, somehow our project file decided to not add that library anymore and i had totally forgotten about it, so took me quite a while to find out that it was missing)