Removing a method call from inside a static lib(.a) without recompiling - objective-c

I'm using a static lib thats giving me a warning when uploading my binary for review by apple.
The method in the static lib that causes the warning(non-public selectors) is never called by me, its corresponding .h is deleted from my proj, but warning still persists.
Given that I know the method name causing the problem, is there a way for me to open/edit this .a and comment/delete the offending piece of code and then use the modified .a in my project.
I don't have access to the .a source to recompile it, and its very old and the creator of it has no contact details for me to track down.
Many Thanks,
-Cake

Quick and dirty solution: Open the .a file in a hex editor and change all instances of the name. Leave the function name the same length so that offsets in the file don't change, just change a letter or something like that. I did a quick test, adding a dummy function to a subproject we're building as a static library then tweaking the function name in the .a file (there were five instances, for what that's worth) and everything built okay. I don't see any reason it wouldn't pass the App Store check after that.
I'm really surprised the function was still there in the final build, though—I thought Dead Code Stripping was supposed to clean out any unused code. Huh.

http://opensource.apple.com/source/cctools/cctools-809/
I don't presume to get your bounty, because I haven't provided an easy solution. But yes, it in theory is possible. You have your work cut out for you.

There are several solutions, depending on your lib and project.
In your build settings :
Enable "dead code stripping" if possible : If the method is never used (even internally), the symbol will be deleted.
Use "Unexported symbol file" : Simply add the symbol into a file and it will be removed from the binary. This will work even if the symbol is used internally.
Enable "Deployment Postprocessing" and "Strip Linked Product" with "Strip Style" set to "All symbol"
(Not sure) Use "Symbols Hidden by Default". This is related to the code generation and should not affect linking, but just in case everything above failed...

No need to hack the binary files. Just turn off the compiler's "unused selectors" warning: -fno-unused-selectors.

Related

Xcode cannot find ProductModuleName-Swift.h

I'm attempting to import my "-Swift.h" file into one of my Objective-C .h files but xcode keeps telling me that the file doesn't exist
#import "Aesculus-Swift.h"
If I command click on the file name it will take me to the generated header file so I know it exists. Why is xcode not able to find it?
This seems like just another issue with Xcode and it's complex tool chain of static analysers and compilers.
Openradar lists radar://21362856 - Swift to Objective-C bridging is unreliable. I am sure there are more but I stopped looking after finding one for this example.
The author imarcelv notes in the description:
I asked a Swift engineer at WWDC in a lab and even he didn't know how to fix this issue.
Steps to Reproduce:
Add a ramdom Swift class to an Objective-C project
Add the #import "ModuleName-Swift.h" file that Xcode generates automatically
Try to use it or just try to compile the project
From time to time it simply doesn't work
It's probably best to file a radar on this issue as it seems that others are already calling it out.
One other thing you could try...
Historically, it was possible for Xcode to completely lose it's syntax highlighting and you could always find out what files the static analyser was giving up on by increasing log level of clang.
I'm not sure if it's still relevant but if I was in your position I'd be trying this command:
defaults write com.apple.dt.Xcode IDEIndexingClangInvocationLogLevel 3
This generates logs you can search with using Console.app for just xcode to highlight the messages. You'll want to trash the derived data of your project to force it to re-compile things.
Although not the same issue as what you're seeing, I have had this post on the syntax highlighting issue bookmarked for years for the above defaults write command to try in times like these.
I solved this recently by adding the following entry to my .xcconfig (you could add it in Xcode's Build Settings > User Header Search Paths if you prefer).
USER_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/MyFramework.framework/Headers
This tells the compiler to search for headers in the build output directory, which is where Xcode puts the generated header (at least in the case of this framework).
In my case this is a directory like ~/Library/Developer/Xcode/DerivedData/MyProject-LongCode/Build/Products/Debug-iphonesimulator/MyFramework.framework/Headers/MyFramework. You might find your generated header in there too.
Xcode's header and dependency management is a hot mess, and it's not surprising that it doesn't work for you.
I had trouble with this stuff & found that your -Swift file is the Product name of your Target ( not just the name of your Target ) . I found the details here helpful: http://ericasadun.com/2014/08/21/swift-calling-swift-functions-from-objective-c/
When you encounter such situation, just find your kinda "ProductName-Swift.h" file by just cmnd+click on it (even if xcode shows warning about it is not found, the #import "Aesculus-Swift.h" string is still clickable) and then in opened code editor window choose context menu and "Show in Finder" item, then explicitly add it to your project.

XCode warning - duplicate CMakeLists.txt while trying to change project name

I tried to change the name of my xcode project, (which uses the cocos2d framework), but for some reason my main files folder (the one that contains all the .h and .mm files) wouldn't change the name. so then i manually clicked under "MyProj TARGETS -> Build Settings" and manually changed the fields:
Info.plist File
Header Search Paths
User Header Search Paths
Prefix Header
to be using "MyProj/" instead of "PrevName/" (the previous name i had named the project) but now i'm getting these two strange warnings:
Warning: Multiple build commands for output file /Users/me/Library/Developer/Xcode/DerivedData/MyProj-fzlkaghtvjzkgkenbpejhzwvxsft/Build/Products/Debug-iphonesimulator/MyProj.app/CMakeLists.txt
Warning: The Copy Bundle Resources build phase contains this target's Info.plist file 'MyProj/Resources/Info.plist'.
you'll see that this is also mentioned under: http://www.cocos2d-iphone.org/forum/topic/33245 but no one has answered this part
and i tried to look under Xcode warning: "Multiple build commands for output file" to see under "Build Phases -> Copy Bundle Resource"... and indeed, there were 2 CMakeLists.txt files. one is:
MyProj/libs/Box2D
and the other is:
MyProj/libs/kazmath/src
which one do i need? or do i need both, since i think xcode used to be compiling with both??
i should mention that my project seems to be running okay right now if i leave the warnings in. but i don't like warnings that i don't understand, and i know that i could just swap my source/assets to a new project to get rid of the warning, but i'd like to know for future reference how to properly rename everything in a xcode project.
Thanks
Oh wow... I had no idea the traffic on stackoverflow is so low these days...(or at least for xcode & iOS dev) sighs
Anyways, I think I figured out a fix.
I read apple developer guilde for the second Warning
For the first Warning, I looked at another file that I had created, and I compared my project's settings to the other project's settings. (such a simple solution, duh, why didn't I think of this >_<) and it turns out, under Copy Bundle Resources, you're only supposed to have:
Your .png files and other resources used in code (but NOT your plist file, for the very reason given in the link above)
iTunesArtwork
ChangeLog
Actually, i'm not sure if you even need #2 or #3. I'll give an upvote to whoever experiments with it. So.... the solution is to simply remove all those other CMakeLists and cmakes and all that junk, including plist :)

Precompiled Header with Constants issue

I have a few constants files "Constants.h" in my project that I am including in the Prefix.pch file to be available to all the classes in my project. They just contain a bunch of #define statements.
My classes don't recognize these constants (no autocomplete) and Xcode gives me "Undeclared Identifier" errors every time I use them. However when I run the project everything works fine (set to ignore errors).
Is there any way I can get rid of these warnings? #pragma ignore them in the prefix file or something? I've tried many options, including setting "precompile prefix header" to NO in build settings.
Any ideas?
EDIT:
I have tried deleting derived data and cleaning / deleting build folder to no avail.
It might be worth noting that I have 3 targets in my project, and another project within this project.
Also, some of the #imports import normal classes. Like a category extension on UIFont and an Analytics class. Could this affect it?
To fix this, I had to change the 'Precompile Prefix Header' flag to NO in my target's Build Settings. By doing this you'll lose any build performance achieved by having a cached compiled header file, but in my case, my Prefix Header is pretty small so I wont see a hit in the time it takes to build.
Try deleting the project derived data. Xcode sometimes needs to re-index your project to remove "errors" such as this.
Organizer > Projects > Your Project
Click on the "Delete" button to the right of the Derived Data row.
Immediately quit Xcode, and then reopen.
I had the PCH file importing .h file with a lot of macros (specifically, I use the MJGAvailability header that warns when I use features that are newer than my deployment target).
Replacing:
#import "MJGAvailability.h"
with
#include "MJGAvailability.h"
solved this issue for me.
I had a preprocessor macro in one of my targets that I moved from 'preprocessor macros' to 'preprocessor macros not used in precompiled headers' and that solved the problem.

Box2D compile errors

I've added Box2D to a Cocos2D project I'm working on.
I've followed several guides as to how to do this (all of which seem to differ!).
However, none seem to work.
I'm getting these types of errors:
error: Box2D/Collision/b2BroadPhase.h: No such file or directory
I assumed I'd got the Header Search Paths wrong but have tried all sorts of variants with no luck.
Any suggestions?
The easiest way to use Box2d with your project is to follow these lines:
Copy the Box2d files into a subfolder of your project.
Import these files into your project via Xcode.
After in the "Project navigator", select your target and open the “Build Settings” tab.
Set the "Always Search User Paths" to YES.
Then search for the "User Header Search Path" and add this "${PROJECT_DIR}" (think to check the “recursive path“).
That's all!
You just have to be careful when you want to use Box2d. Think to change the extension of your files from .m to .mm to warn the compiler that the class must be compile as Objective-C++ instead of Objective-C.
I have found a good tutorial here (with Xcode 3.2, but the idea is here). I hope it'll help you.
Alternatively ... After a lot of trouble trying to include box2d in my project, I instead used box2d as a static library - takes a minute to setup, but it's much easier to maintain / add to multiple projects. Step by step guide here:
http://red-glasses.com/index.php/tutorials/box2d-for-ios-made-easy-make-it-a-static-library/

duplicate symbol _OBJC_METACLASS_$_ClassName

I am trying to run my cocos2d application and facing this error, as I have recently upgraded my sdk to 4.2 and my cocos2d to 0.99.5.
I tried to clean my project even change the Target ios Deployment but error remains the same. Also rename the className aswell in order to avoid duplication from Library classes names of cocos2d.
ld: duplicate symbol _OBJC_METACLASS_$_MenuSceneNew in
/Users/umaidsaleem/Desktop/functionalityTest/build/Debug-iphonesimulator/libcocos2d
libraries.a(MenuScene.o) and
/Users/umaidsaleem/Desktop/functionalityTest/build/functionalityTest.build/Debug-iphonesimulator/functionalityTest.build/Objects-normal/i386/MenuScene.o
Another rather simple thing to check is that you did not accidentally #import a .m file instead of a .h header file.
Happened to me.
You are linking the file MenuScene.m twice. You apparently have it in a static library and also in your main application.
Another reason for this, for those out there who did the same as I just did, might be that you re-created a managed object class. By doing that and choosing another group in the project structure, you accidentally create another reference to the same files.
I ended up with two references for header and implementation in both the root of the project and in my model group. Removing the topmost references to .h and .m files got rid of the linking failure.
Sometimes Core Data inserts AnyProjectNameModel.xcdatamodeld to the Compile Sources of the Build Phases. Check it and delete it and everything is run again...
The error message just indicates the generated ManagedObjects...
The correct place for the AnyProjectNameModel.xcdatamodeld is the Copy Bundle resources in the Build Phases.
Check the Compile Sources of your target and see if a class.m file is included twice
A stupid mistake that I made was that I named my #implementation the same as my superclass.
In the .h
#interface Subclass : Superclass
#end
In the .m
#import "Subclass.h"
#implementation Superclass
#end
None of the regular suggestions from google seemed to help, so if someone is as crazy or tired as I am (maybe a healthy mix of both), make sure you haven't duplicated an #implementation!
In my case this was happening because of Xcode automatically generating my NSManagedObject class, which then clashed with my manually created NSManagedObject class. In this case you can set "Codegen" to "Manual/None" in the Data Model Inspector for your newly created Entity.
Another thing to check for the double linking - its possible to have the same file in two different places in the file list on the left. Then the compiler compiles and links it twice.
This happens when playing with organizing your file hierarchy, for example.
You don't have to be making a library or anything fancy - just drag a .m in to two different locations in the project tree.
Remember to only remove the reference to one of them, no file trashing is needed.
To me, removing -all_load from 'Other Linker Flags' fixed the problem.
I have also had this particular error occur when a file that has not been added to the project, is referenced somewhere in the project. The two cases where I have experienced this are where I have deleted/removed files from the project without removing references to them, and when working cooperatively on a project where a teammate added the reference but I have not added the file to my version of the project.
I know the OP has resolved their problem, but I felt this might help someone else who reads this question while looking for help.
I have figured out the solution myself, sorry for posting little delayed. All assistance are much appreciated the but problem arises when I add new CCLayer derived class and checkmark cocos2d 0.99.5 static library which was wrong. Then I re-Ad my class without checking and clean my targets and then build and go. Problem solved now.
I had a project with 2 targets. A target named Component and the second named Sample. Sample was using component as a link library.
Then Component was using a pod named MyPod (installed with cocoapod).
The Podfile was written like this :
def shared_pods
pod 'MyPod'
end
target 'Component' do
shared_pods
end
target 'Sample' do
shared_pods
end
Both targets was referencing the shared pod list. When building Component target, no problem appears, but when building sample i get a duplicate symbol _OBJC_METACLASS_$_ClassName.
I have changed the Podfile to :
def shared_pods
# empty
end
target 'Component' do
pod 'MyPod'
shared_pods
end
target 'Sample' do
shared_pods
end
And that solve the problem.
3 hours spent, hope to save somebody time.
XCode Beta crashed for me while deleting a reference to a class. This caused the problem described in the answer, the fix was different again.
In my Target's Build Phase, under "Compile Sources", the item giving me grief was red. I couldn't remove it with the minus button, but typing "skip" in the compiler flags caused the red class to disappear after reloading the project. I'm assuming you could type anything in there.
It took me two hours to find the solution to my prob, I put it in here for another option to those having this problem, although it is probably not going to be a common one.
None of the Answers worked for me, so what I did was remove the files from the project and choose only Remove References.
Then I added back the same files and it worked.
That fixed my error. Maybe XCode got lost references stored somewhere since the project is multi-collaboration.
Hope that helps someone.
Another possibility for error like this is when there is a class name collision. Either 2 classes with the same name within your project, or class from your project clashing with one defined in some of dependency libraries.
Remove target from right panel and again add target. This will remove any duplicate references.
It may happen if 2 programmer add the same target and commit the project file.
In my case I was using a binary library includes the same class name I was using outside,
So I changed my class name and It's working fine :)
In my case, I had added the libxxxx.a to Link Binary with Libraries section in the subProjects as well as in the mainProject. Hence there were duplicate symbols. Removing from subProjects fixed it.