I've been tasked to work on a project that has some confusing attributes.
The project is of the nature that it won't compile for the iPhone Simulator And the iPhone Device with the same compile settings. I think it has to do with needing to be specifically compiled for x86 or arm6/7 depending on the target platform.
So the project's build settings, when viewed in Xcode's Build Settings view doesn't enable me to set specific compiler flags per specific files. However, the previous developer that worked on this project has somehow declared the line:
CE7FEB5710F09234004DE356 /* MyFile.m in Sources */ = {isa = PBXBuildFile; fileRef = CE7FEB5510F09234004DE356 /* MyFile.m */; settings = {COMPILER_FLAGS = "-fasm-blocks -marm -mfpu=neon"; }; };
Is there any way to do this without editing the project file by hand? I know that editing the project file can result in breaking it completely, so I'd rather not do that, as I obviously don't know as much as the previous developer.
So to clarify, the question is:
The build fails when compiling for simulator unless I remove the -fasm-blocks flag. The build fails when compiling for device unless I add the -fasm-blocks flag. Is there a way to set this flag per file without editing the project file by hand?
This blog post by Joshua Nozzi explains how to do this in Xcode 4, where he says:
... select your project in the Project Navigator, select the relevant target (you may have only one), then select the Build Phases tab. Expand the Compile Sources phase and viola! A Compiler Flags column lets you set each file’s flags for that target.
You can define additional compiler flags for individual source files as follows:
first select the target you are going to build
right click on the source file
select "Get Info"
click on the "Build" tab
define your additional compiler flags
However it sounds like a better solution in your case is just to duplicate the target and have two targets - one for an actual device and one for the simulator. Inherit common build settings from the project level and just tweak the per-target build settings as necessary.
Call GetInfo for the specific file, you can set the Build settings there for this file. See also the XCode Project Management Guide about this.
Related
I added CoreData to my app MY_APP:
I defined the data model by creating a xcdatamodeld file containing
a single entity XXX with a few attributes.
Using Xcode/Editor/Create NSManagedSubclass, Xcode created 2 files, XXX+CoreDataClass.swift and XXX+CoreDataProperties.swift.
I wrote a little code to test storage and fetch back from core data, and everything works fine.
The problem:
At the beginning of the build phase, I get 3 warnings:
warning: The Swift file "/Users/reiner/Library/Developer/Xcode/DerivedData/
MY_APP/Build/Intermediates.noindex/MY_APP.build/Debug-iphonesimulator/
MY_APP.build/DerivedSources/CoreDataGenerated/MY_APP/XXX+CoreDataClass.swift"
cannot be processed by a Copy Bundle Resources build phase (in target ‚MY_APP‘)
warning: The Swift file "/Users/reiner/Library/Developer/Xcode/DerivedData/
MY_APP/Build/Intermediates.noindex/MY_APP.build/Debug-iphonesimulator/
MY_APP.build/DerivedSources/CoreDataGenerated/MY_APP/XXX+CoreDataProperties.swift"
cannot be processed by a Copy Bundle Resources build phase (in target 'MY_APP')
warning: The Swift file "/Users/reiner/Library/Developer/Xcode/DerivedData/
MY_APP/Build/Intermediates.noindex/MY_APP.build/Debug-iphonesimulator/
MY_APP.build/DerivedSources/CoreDataGenerated/MY_APP/MY_APP+CoreDataModel.swift"
cannot be processed by a Copy Bundle Resources build phase (in target 'MY_APP')
These 3 files are not listed under MY_APP target/Build Phases/Copy Bundle Resources.
My questions:
Is anything wrong with my build setup, i.e. what is the reason for these warnings, and how can I avoid it?
Remark: This question relates to a different framework (core data), but is similar to this one, which does not have an answer yet.
EDIT:
My project has 2 targets, for iOS and for watchOS. Until now, core data was used only on iOS.
I tried now to enable it also for watchOS, but I got an error, because the .xcdatamodeld was not yet in Build Phases / Copy Bundle Resources.
As soon as I added it there, core data was executed correctly on the watch.
BUT: I got the same 3 warnings mentioned above, this time additionally for the watch extension target (altogether 6 warnings).
Maybe this a useful hint.
EDIT:
I contacted Apple, and they provided a solution:
When an Xcode project „xxx“ is created with the coreData option on, a core data model file „xxx.xcdatamodeld“ is created and added to the target Build Phases Compile Sources.
Say, one adds there an entity „Entity“ with an attribute „attribute“.
If one selects in the Xcode project navigator this model file and opens the file inspector, there is an entry „Code Generation“ which is set to Swift by default. This creates the 2 files Entity+CoreDataClass.swift and Entity+CoreDataProperties.swift automatically, but they are not shown in the project navigator.
Building the project succeeds, and one can use a property Entity.attribute as usual in the code.
However:
If one selects the xcdatamodeld file in the Xcode navigator, the Xcode Editor menu has an entry „Create NSManagedObject Subclass…“. If one selects this entry and there the xxx data model, the 2 files Entity+CoreDataClass.swift and Entity+CoreDataProperties.swift are created again and shown in the project navigator, and added by default to the target.
This means that these files are added twice, thus the warnings.
So the solution is not to use this editor command, and I don’t know what it is for…
EDIT 2:
My fault; I was looking at the wrong place:
Open the xcdatamodeld in the project navigator.
In the pane right of it, select an entity.
At the top right, open the inspector pane.
At the top right of it, select the data model inspector.
There is an entry „Codegen“ where one can select Manual/None.
If this option is selected, no code is automatically generated from xcdatamodeld, i.e., one can manually (by using the editor command) create NSManagedObject subclasses that can be added to the target Compile Sources section, as required.
Previous answer:
There are apparently 2 ways to use CoreData, either 1) by using only the PROJECT.xcdatamodeld file, which is then added to Compile Sources Build Phase, or 2) by creating a NSManagedObject subclass using Xcode’s Editor/Create NSManagedObject Subclass command.
If 1) is used, everything works fine, but one has no property access to the entity used.
If 2) is used, Xcode creates the 2 files ENTITY+CoreDataClass.swift and ENTITY+CoreDataProperties.swift. These 2 files are added to the Compile Sources Build Phase, but PROJECT.xcdatamodeld must not. If one does anyway, one gets the build error „unexpected duplicate task“. But if one does not, the project builds without errors and warnings.
However, when run, the instruction
let entity = NSEntityDescription.entity(forEntityName: "MyEntity", in: managedContext)!
fails, because it does not find the data model.
A workaround is to add PROJECT.xcdatamodeld to target / Build Phases / Copy Bundle Resources. Then the code executes fine, but one will get the warnings that I described in my question.
For me what caused the issue was having the .xcdatamodeld file in the Copy Bundle Resources step within Build Phases for the target specified in the warning: in your case, MY_APP. I removed that file from the Copy Bundle Resources step and all the warnings went away.
An approach to dealing with an Xcode which seems to be getting more and more buggy with each release in recent years:
Quit and relaunch Xcode.
If that does not work, do a Show Package Contents on the .xcodeproj package and open the .pbxproj file in a text editor. Search the file for occurrences of XXX+CoreDataClass. The search the file for occurrences of some other .swift file which does not create this warning. Compare the two search results. It may be necessary to manually edit the .pbxproj file.
I have one functionality and it is depending on one static library. Actually, Apple is not allowing this static library because of few reasons. So, for now we have decided to add one Preprocessor macro and based on that functionality should be switch on/off.
I have switched my code to behave based on that Preprocessor macro. But I didn't find any to link or unlink the library based on preprocessor macro. I can not allow to link the library all times, as I have already told apple is not allowing it.
One solution that I already know : I can create the multiple target. But problem is that my app has already lots of targets. So, again to manage this I have to create one more target for each target those are already created.
Any help will be appreciated.
Edit:
I have created configuration like Francesco suggested. But One quick question I have let's say If I will remove the path of library from "Library Search Path" then that library will not be linked to app? Because that library is still in target of App.
Instead of targets you can create multiple configurations. And you can change the linker flags there.
I did this think for Sparkle framework (which is not allowed on App Store)
EDIT:
To create/manage the configurations click on the project in the sidebar. Then in the main window select again the project, not the targets, and select the "Info" tab.
Together with Deployment Target selection and Languages you will find a Configuration section.
You can add or remove configurations from there.
Then to launch it you have to go to Product -> Scheme -> Edit Scheme -> Build Configurations.
You can duplicate an existing scheme and choose the correct configuration from there.
You can remove the static library from the list of linked items by setting a (somewhat undocumented) Xcode build setting:
EXCLUDED_SOURCE_FILE_NAMES = libUnwanted.a
You can do this in an .xcconfig file or in the normal target build settings UI (by adding a custom build setting). If you for example set this in the "Release" configuration Xcode will include the library in the "Debug" build but omit if for the release build.
EXCLUDED_SOURCE_FILE_NAMES works with all kinds of files that can be added to a target: source files, resources, libraries, ...
Here's how to do this step by step:
Open the target build settings by clicking on the blue project icon in the Project Navigator and select the Build Settings tab.
Click the plus icon to add a "User-Defined Setting"
Name the setting "EXCLUDED_SOURCE_FILE_NAMES"
Expand the Configurations for the setting and set the "Release" value to the name of your unwanted library.
Credit of this answer goes to Nikolai Ruhe & Francesco
I have combined the answer of both and I got the solution.
Here are the steps that I followed.
Created new configuration. ( To know how to create configuration see
the answer of Francesco)
Added flag EXCLUDED_SOURCE_FILE_NAMES in user-defined setting of Build settings. (For steps see the answer of Nikolai Ruhe). And in this flag I have added the name of my static library under the my custom configuration.
Here is a good tutorial that will definitely help you : Remove tesflight from Distriubtion
I have a bit of a problem with setting different configuration for my project. I have two versions of the same static library. One has logging enabled, the other doesn't.
I am using two different xcconfig files for Debug vs. Release. In these files I specify the library and header search paths for the two variants of the static lib. So far so good.
However, in my build settings I can't see a way to conditionally link the actual library. I.e use the debug variant for Debug and the release for Release.
Any ideas?
You need to link the library using the "Other Linker Flags" build setting, rather than the standard "Link Binary With Libraries" UI. The build setting can be changed depending on the configuration:
Click the triangle and you can give different values for Debug/Release. You will need to use the -l flag. For example, for a filename of libMyLib.a use the flag -lMyLib. You may need to edit the "Library Search Paths" to search the appropriate location.
If the filenames for the debug and release version are the same and you don't want to change them, put them into their own lib/Debug and lib/Release directories respectively. Then edit the "Library Search Paths" build setting adding either "$SRCROOT/lib/Debug" or "$SRCROOT/lib/Release" for the appropriate configuration.
If something is not used in C++, it's not compiled at all. Is the same true for iPhone?
If I compile a program and there are unused classes or other stuff, will it be compiled or ignored?
It depends on your build settings.
Under your target build settings, then under "Linking" there is an option for "Dead Code Stripping". It defaults to yes for projects created with Xcode.
Here's a link to the build settings documentation from Apple (with an excerpt):
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html
DEAD_CODE_STRIPPING (Dead Code Stripping)
Description: Boolean value.
Specifies whether dead code is stripped from the binary.
Prerequisite: $GCC_DEBUGGING_SYMBOLS = full
Values:
YES: Dead code is stripped from
the binary when the prerequisite is met.
NO: Dead code is not stripped
from the binary.
Default value: NO Companions: “GCC_DEBUGGING_SYMBOLS
(Level of Debug Symbols).” Prerequisite for:
PRESERVE_DEAD_CODE_INITS_AND_TERMS
Note, the docs say the value defaults to NO, but Xcode project settings default the value to YES.
I believe that any resource that is added to a target will get compiled and/or copied to your application bundle at build time. To edit which files are built/copied, you can modify the settings in Xcode 4, by clicking on project, then your target. Under Build Phases, you can change the files as needed.
Here's a screenshot:
There is also a setting for Dead Code Stripping under Build Settings. Here's what that looks like:
It defaults to yes, but if you want to disable it for some reason, that's how you'd do so.
my iphone app builds fine in debug configuration, but when i change it to release, i get hundreds of errors, starting with "CoreServices/CoreServices.h: No such file or directory" in AudioFileComponent.h - part of the AudioToolbox framework.
i can't find where in the project/build settings is responsible for this.. thanks for any help.
I would recommend the following:
Open up your debug target's build settings by right-clicking on the target, hitting "Get Info", and selecting the Build tab.
Select All (Command-A) so the entire contents of the Build setting panel is selected, then copy it to the clipboard.
Paste the contents of the clipboard to an empty text document
Repeat steps 1-3 for the release target of the same project
From there you can use a diff utility or some other method to compare the contents of the two files, which will show you the settings that differ between the two configurations. Some of them will make sense (e.g., optimization settings) whereas others will not. Most likely there is a setting that differs between the two that will resolve your problem.
Another thing you can do is build one of your source files in debug mode, and in the Build Results window copy the contents of the command line to a text editor. Repeat for release mode. Then, replace each space in the command line with a newline (\r). From there you should be able to do a rough side-by-side evaluation of the differences between the two compile instructions, and may be able to figure out what's missing from that.
In general this helps you get a better feel for exactly what XCode is doing under the hood to build your project, which is a good strategy to practice no matter what tool you are using for development.
i think the problem was because i had the audiotoolbox package in the wrong place, it wasnt in system/library/frameworks like it should have been. (this doesnt explain why it built ok in debug though)