Cocoapods optimization level for schemes - ios

Looking at the project file for Cocoapods Pods.xcodeproj it looks like every single scheme for every library (except for Debug scheme) has an optimization level of Fastest, Smallest.
Is there a quick and easy way to change the Podfile or some other configuration of Cocoapods so that the optimization level is None for specific schemes when I use pod install?

I use post_install hook in Podfile. Like this:
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
if config.name.include?("Debug")
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Onone'
end
end
end
EDIT
GCC_OPTIMIZATION_LEVEL is ignored for Swift Pods. If you're using Swift Pods you also need to set SWIFT_OPTIMIZATION_LEVEL.

To anybody seeing this using cocoapods 0.38.0 or later:
Use "pods_project" instead of "project"
The previous answers use the word "project" (installer.project.build_configurations.each)
Project was deprecated and replaced with pods_project.
https://github.com/CocoaPods/CocoaPods/issues/3747
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
if config.name.include?("Debug")
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
end
end
end

If you also want the DEBUG macro added for debugging with assertions enabled, you can use the following script:
post_install do |installer|
installer.project.build_configurations.each do |config|
if config.name.include?("Debug")
# Set optimization level for project
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
# Add DEBUG to custom configurations containing 'Debug'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
if !config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'].include? 'DEBUG=1'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'DEBUG=1'
end
end
end
installer.project.targets.each do |target|
target.build_configurations.each do |config|
if config.name.include?("Debug")
# Set optimization level for target
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
# Add DEBUG to custom configurations containing 'Debug'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
if !config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'].include? 'DEBUG=1'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'DEBUG=1'
end
# Enable assertions for target
config.build_settings['ENABLE_NS_ASSERTIONS'] = 'YES'
config.build_settings['OTHER_CFLAGS'] ||= ['$(inherited)']
if config.build_settings['OTHER_CFLAGS'].include? '-DNS_BLOCK_ASSERTIONS=1'
config.build_settings['OTHER_CFLAGS'].delete('-DNS_BLOCK_ASSERTIONS=1')
end
end
end
end
end

Instead of post_install you can add following line to Podfile:
project 'ProjectName', 'DebugConfigurationName' => :debug

Related

Expo - React Native Build Failed (Starting from Xcode 14, resource bundles are signed by default....)

I'm trying to update an application built with expo + react native and I encounter the last problem.
expo.dev
Visual Code terminal
🍎 iOS build failed:
Starting from Xcode 14, resource bundles are signed by default, which requires
setting the development team for each resource bundle target.
To resolve this issue, downgrade to an older Xcode version using the "image" field in
eas.json, or turn off signing resource bundles in your Podfile:
https://expo.fyi/r/disable-bundle-resource-signing
Learn more: https://docs.expo.dev/build-reference/infrastructure/#ios-build-server-
configurations
I tried to solve this problem by cleaning cache and reinstalling all pods.
I went to the permissions in xcode, I tried logging in with an apple developer account but still the same.
I tried to see the changes in this link https://expo.fyi/r/disable-bundle-resource-signing but it is very different from mine, I made the changes but all app is broken when i try to build.
Expo Version: 43.00
cocoapods: "1.11.2"
eas cli version: ">= 0.38.1"
xCode Version: 13.2.1
Podfile
require File.join(File.dirname(`node --print
"require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-
native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('#react-native-
community/cli-platform-ios/package.json')"`), "native_modules")
platform :ios, '12.0'
require 'json'
podfile_properties = JSON.parse(File.read('./Podfile.properties.json')) rescue {}
target 'appName' do
use_expo_modules!
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes'
)
# Uncomment to opt-in to using Flipper
#
# if !ENV['CI']
# use_flipper!('Flipper' => '0.75.1', 'Flipper-Folly' => '2.5.3', 'Flipper-RSocket'
=> '1.3.1')
# end
post_install do |installer|
react_native_post_install(installer)
# Workaround `Cycle inside FBReactNativeSpec` error for react-native 0.64
# Reference: https://github.com/software-mansion/react-native-screens/issues/842#issuecomment-812543933
installer.pods_project.targets.each do |target|
if (target.name&.eql?('FBReactNativeSpec'))
target.build_phases.each do |build_phase|
if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs'))
target.build_phases.move(build_phase, 0)
end
end
end
end
end
end
How can i solve this problem in may case?
To solve the problem, follow these steps:
In terminal:
cd ios
pod deintegrate
After changing the code from Podfile with this one.
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react- native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('#react-native-community/cli-platform-ios/package.json')"`), "native_modules")
platform :ios, '12.0'
require 'json'
podfile_properties = JSON.parse(File.read('./Podfile.properties.json'))
rescue {}
target 'YOUR APP NAME' do
use_expo_modules!
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes'
)
# Uncomment to opt-in to using Flipper
#
# if !ENV['CI']
# use_flipper!('Flipper' => '0.75.1', 'Flipper-Folly' => '2.5.3',
'Flipper-RSocket' => '1.3.1')
# end
post_install do |installer|
react_native_post_install(installer)
# __apply_Xcode_12_5_M1_post_install_workaround(installer)
# This is necessary for Xcode 14, because it signs resource bundles by default
# when building for devices.
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end
end
After run on terminal:
pod install
pod update
cd ..
These changes worked for me and allowed me to adapt the application
This is just a workaround, not a fix. In fact, you may have multiple targets with different team IDs.
This post_install script in podfile fixed it. As it seems, setting the own developer team is necessary. Replace Your Team ID with the TeamID of your project.
Adding to what #Pruteanu Alexandru answer
cd ios
pod deintegrate
After changing/adding the code from/to Podfile with this one.
post_install do |installer|
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings["DEVELOPMENT_TEAM"] = "Your Team ID"
end
end
end
end
Your PodFile might look like this:
post_install do |installer|
react_native_post_install(installer)
# Workaround `Cycle inside FBReactNativeSpec` error for react-native 0.64
# Reference: https://github.com/software-mansion/react-native-screens/issues/842#issuecomment-812543933
installer.pods_project.targets.each do |target|
if (target.name&.eql?('FBReactNativeSpec'))
target.build_phases.each do |build_phase|
if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs'))
target.build_phases.move(build_phase, 0)
end
end
end
end
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings["DEVELOPMENT_TEAM"] = "YOUR TEAM ID"
end
end
end
end
After run this on terminal:
pod install
pod update
cd ..

How can I define preprocessor flags in iOS project and use it in Swift code?

My Problem: I defined the preprocessor flag for my Xcode project, but it doesn't work as I used it in my Swift code.
What I've Done: I defined multiple Targets for my Xcode project (and multiple schemes as well) and for each target created a custom build configuration file (.xcconfig file). For each Target, I override SWIFT_ACTIVE_COMPILATION_CONDITIONS flag in my .xcconfig file.
My ca805.debug.xcconfig file is like this:
#include "Pods/Target Support Files/Pods-Common-ca805/Pods-Common-ca805.debug.xcconfig"
#include "base.debug.xcconfig"
// other configs
SWIFT_ACTIVE_COMPILATION_CONDITIONS = CA805
And I assigned each build configuration to each Target in .xcodeproj file.
In Swift code I used this flag like below:
#if CA805
print("I'm using CA805 target specific code")
#else
print("I'm using common code")
#endif
And it printed I'm using common code.
Also, I've tried to add SWIFT_ACTIVE_COMPILATION_CONDITIONS flag using Podfile but it didn't work:
platform :ios, '12.0'
use_frameworks!
abstract_target 'Common' do
project 'Main', 'base.debug' => :debug, 'base.release' => :release
use_frameworks!
# Pods for all targets
# ...
# Define Targets
target 'Main'
target 'ca805'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name.start_with?('Pods-Common')
target.build_configurations.each do |config|
if !config.name.start_with?('base')
target_name = target.name.split('-')[2].upcase
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', "#{target_name}=1"]
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['$(inherited)', "-D#{target_name}"]
config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] ||= ['$(inherited)', "#{target_name}"]
end
end
end
end
end
I checked Active Compilation Conditions section in my Target's Build Settings tab and something overrides my flag and I don't know the reason.
Active Compilation Conditions section in my project
Finally, I found a workaround for this issue. I modified .xcconfig files:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name.start_with?('Pods-Common')
target.build_configurations.each do |config|
if !config.name.start_with?('base')
target_name = target.name.split('-')[2]
flag = target_name.upcase
puts "[Injecting flag:'#{flag}' to '#{target_name}.#{config.name.downcase}.xcconfig'"
xcconfig_path = config.base_configuration_reference.real_path
# read from xcconfig to build_settings dictionary
build_settings = Hash[*File.read(xcconfig_path).lines.map{|x| x.split(/\s*=\s*/, 2)}.flatten]
# modify FLAGS
build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = "$(inherited) #{flag}"
# write build_settings dictionary to xcconfig
File.open(xcconfig_path, 'w') {|file| file.puts ''}
build_settings.each do |key, value|
File.open(xcconfig_path, 'a') {|file| file.puts "#{key} = #{value}"}
end
end
end
end
end
end

Cocoapod : Redefining preprocess macro using post install hook

I want to update my pod to let users activating/desactivating a feature.
To do this I've added a Preprocessor macro in my podspec :
s.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'FEATURE=1' }
Now, for a user the right thing to do (of what I've understood) should be to use a post install hook in the podfile to change the definition of FEATURE
post_install do |installer_representation|
installer_representation.project.targets.each do |target|
if target.name == "Pods-MyPod"
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'FEATURE=0']
end
end
end
end
But it did not do anything at all ... FEATURE value is still 1
Am I doing something wrong ?
EDIT :
I did take a look at this answer, but it did not help.
In the end, I found a working version.
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == "Pods-MyPod"
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = ['COCOAPODS=1', 'FEATURE=0']
end
end
end
end

Add custom path to HEADER_SEARCH_PATHS using CocoaPods post install hook

I am trying to add $(PLATFORM_DIR)/Developer/Library/Frameworks path to Specta target Header search paths using post install hook. This obviously is not vital, but it really annoys me to added this path manually each time I do "pod update".
I got to the following script:
post_install do |installer_representation|
installer_representation.project.targets.each do |target|
if target.name == 'Specta'
target.build_configurations.each do |config|
headers = config.build_settings['HEADER_SEARCH_PATHS']
if headers
config.build_settings['HEADER_SEARCH_PATHS'] += ' $(PLATFORM_DIR)/Developer/Library/Frameworks'
end
end
end
end
end
I would be really happy if someone could point me to the right direction, because I am really stuck.
P.S. I already noticed that this path is already added by CocoaPods, but still I am highly interested in how this can be done, since this knowledge can be useful later. Thanks!
Define a method in your Podfile:
def append_header_search_path(target, path)
target.build_configurations.each do |config|
# Note that there's a space character after `$(inherited)`.
config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited) "
config.build_settings["HEADER_SEARCH_PATHS"] << path
end
end
Then call the method in the post_install:
installer.pods_project.targets.each do |target|
if target.name == "Specta"
append_header_search_path(target, "$(PLATFORM_DIR)/Developer/Library/Frameworks")
end
end

DEBUG preprocessor macro not defined for CocoaPods targets

I'm having issues with a pod called DCIntrospect-ARC which should only work in DEBUG mode. It checks if the DEBUG macro is defined before running. However, it is not defined in the CocoaPods target and even though I am running in debug mode in Xcode it fails to run because the DEBUG macro is not defined.
I can define the DEBUG macro in the podspec using
s.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) DEBUG=1' }
but this defined DEBUG for all build configurations and not only the DEBUG configuration.
Is this a CocoaPods issue? Shouldn't the DEBUG macro generally be defined for Pods?
Can I work around this in the Podspec file and declare the DEBUG macro in the Debug build configuration only?
you can use the post_install hook in Podfile.
This hook allows you to make any last changes to the generated Xcode project before it is written to disk, or any other tasks you might want to perform.
http://guides.cocoapods.org/syntax/podfile.html#post_install
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name != 'Release'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'DEBUG=1']
end
end
end
end
Thanks to John I completed my custom Podfile script, which also changes the optimization level to zero and enables assertions.
I've got multiple debug configurations (for ACC and PROD), so I needed to update several properties for debugging purposes.
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
if config.name.include?("Debug")
# Set optimization level for project
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
# Add DEBUG to custom configurations containing 'Debug'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
if !config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'].include? 'DEBUG=1'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'DEBUG=1'
end
end
end
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name.include?("Debug")
# Set optimization level for target
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
# Add DEBUG to custom configurations containing 'Debug'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
if !config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'].include? 'DEBUG=1'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'DEBUG=1'
end
# Enable assertions for target
config.build_settings['ENABLE_NS_ASSERTIONS'] = 'YES'
config.build_settings['OTHER_CFLAGS'] ||= ['$(inherited)']
if config.build_settings['OTHER_CFLAGS'].include? '-DNS_BLOCK_ASSERTIONS=1'
config.build_settings['OTHER_CFLAGS'].delete('-DNS_BLOCK_ASSERTIONS=1')
end
end
end
end
end
The accepted answer as of now doesn't work for Swift Pods.
Here is a one-line change to that answer that appears to work for both.
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name != 'Release'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'DEBUG=1']
config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-DDEBUG']
end
end
end
end
I think the accepted answer is not so right for me. config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'DEBUG=1']
||= is used to assign a empty or nil variable, but if the config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] is not empty ?
The array cannot be modified at all. The value is ["POD_CONFIGURATION_PRODUCTION=1", "$(inherited)"] for me.
So I gave the complete anwser.
post_install do |installer_representation|
installer_representation.pods_project.build_configurations.each do |config|
if config.name == 'Release' || config.name == 'Production' || config.name == 'Release-InHouse'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= []
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] |= ['$(inherited)', 'NDEBUG=1']
end
end
end
||= [] make sure the variable is a valid array. and arrayA |= arrayB means arrayA + arrayB and rid the the repeated element, and then return to arrayA.
Even easier: just ensure you have the DEBUG=1 macro to your GCC_PREPROCESSOR_DEFINITIONS in your project in xCode for debug mode but not release mode. If you add it the the project level (not specific targets) it will be inherited by all targets (debug-test, custom targets, etc). This is set by default on new projects, and generally expected to be there. If you are missing it, that could have broad impact.
If it's still not working, ensure you also have $(inherited) in all your targets for GCC_PREPROCESSOR_DEFINITIONS. CocoaPods and DEBUG both count on that.

Resources