Cocoapods how to set build setting based on configuration in the podspec - ios

Im trying to set a build configuration setting on my cocoapod im working on but I can only do it in a really inconvenient way, im trying to see if there is a better way doing it via the podspec file. Currently I have this in my example project pod file:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'MySDK'
target.build_configurations.each do |config|
if config.name == 'Test'
config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = 'TEST'
end
end
end
end
end
which gives me what I want, which looks like this:
I've tried going like this (after removing the previous solution above from the pod file) inside my podspec file, a lot of SO answers say this should work but it doesnt seem to
s.pod_target_xcconfig = {
'SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Test]' => 'TEST'
}
it lands up looking like this:
Can anyone help me achieve this in my podspec file as apposed to the 3rd parties pod file?

This should work:
s.pod_target_xcconfig = {
'SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Test][sdk=*][arch=*]' => 'TEST'
}

Related

Script to modify .xcconfig file generated by Cocoapods

How can I modify the OTHER_LDFLAGS field in the .xcconfig generated at pod install step?
End goal: Only weakly link certain Pods, so they can be loaded with dlopen at runtime.
I noticed in the Pod-Target.debug.xcconfig generated at pod install, it has this: OTHER_LDFLAGS = $(inherited) -framework "AFNetworking", if I change that to -weak_framework, it does what I want to do.
This Cocoapods issue talks about doing it through a post_install hook, however config.build_settings['OTHER_LDFLAGS'] doesn't write to that file.
PS: I know that the use of dlopen is not recommended, however I'm working with conflicting hardware libraries where I cannot have two loaded at the same time.
Add this code to your Podfile and run pod install again
post_install do |installer|
workDir = Dir.pwd
xcconfigFilename = "#{workDir}/Pods/Target Support Files/Pods-Target/Pod-Target.debug.xcconfig"
xcconfig = File.read(xcconfigFilename)
newXcconfig = xcconfig.gsub(/-framework "AFNetworking"/, "-weak_framework \"AFNetworking\"")
File.open(xcconfigFilename, "w") { |file| file << newXcconfig }
end
A little modification of answer by VoidLess which I think might be useful:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
xcconfig_path = config.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)
xcconfig_mod = xcconfig.gsub(/-framework "YourFramework"/, "-weak_framework \"YourFramework\"")
File.open(xcconfig_path, "w") { |file| file << xcconfig_mod }
end
end
end

How to exclude Pods from Code Coverage in Xcode

Is there a way to exclude Pods from Code Coverage?
I would like to see Code Coverage only for the code I've written.
Not that it should matter, but I'm using Xcode 8.
These steps will help:
1. add these lines to Podfile
# Disable Code Coverage for Pods projects
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_CODE_COVERAGE'] = 'NO'
end
end
end
2. run pod install
Now you won't see pods in test coverage.
Note: It only excludes Objective-c pods but not Swift
XCode 10 Update
In Xcode 10 you can set which targets you want to enable code coverage for in
Edit Schemes > Test > Options
Just select 'Gather coverage for some targets' and add your main project.
To disable coverage for swift code you can use a wrapper for SWIFT_EXEC (I verified this so far with Xcode 9.3). Hence the complete solution (incl. Swift) would be the following:
Append to your Podfile (and invoke pod install after that):
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |configuration|
configuration.build_settings['CLANG_ENABLE_CODE_COVERAGE'] = 'NO'
configuration.build_settings['SWIFT_EXEC'] = '$(SRCROOT)/SWIFT_EXEC-no-coverage'
end
end
end
Place the following script (name it SWIFT_EXEC-no-coverage) at the root of your source tree (chmod +x as necessary):
#! /usr/bin/perl -w
use strict;
use Getopt::Long qw(:config pass_through);
my $profile_coverage_mapping;
GetOptions("profile-coverage-mapping" => \$profile_coverage_mapping);
exec(
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc",
#ARGV);
Here's a link to the corresponding gist: https://gist.github.com/grigorye/f6dfaa9f7bd9dbb192fe25a6cdb419d4
Click on your Pods project in the Project Navigator on the left
On the right hand side, open project and target list if it's not already open; then click on the Pods project name (NOT the targets).
Click Build Settings.
In the search bar, search for "CLANG_ENABLE_CODE_COVERAGE".
Change "Enable Code Coverage Support" to NO.
Re-run test.
If you are developing a pod and want to have code coverage just for yours:
# Disable Code Coverage for Pods projects except MyPod
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == 'MyPod'
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_CODE_COVERAGE'] = 'YES'
end
else
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_CODE_COVERAGE'] = 'NO'
end
end
end
end
Based on answer of #Tung Fam adding exclusion list for some pods
# Disable Code Coverage for projects listed in excluded_pods
excluded_pods = ['Pod1', 'Pod2', 'Pod3']
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
next if !excluded_pods.include?(target.name)
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_CODE_COVERAGE'] = 'NO'
end
end
end

How to use OTHER_SWIFT_FLAGS in a Pod

Has anybody tried to use build configuration flags in a Swift based Pod? I am trying to use a post_install hook to add "OTHER_SWIFT_FLAGS" to a private Swift pod that I'm working on. Basically, I want to be able to do something like #if DEV #elseif QA #else #endif to change endpoints based on the target that I'm using. The project I'm integrating the pod with also uses DEV & QA flags which work fine with corresponding DEV & QA targets.
Here is a post_install hook that I came up using help from other similar posts:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'Pods-Test-QA'
puts "Found #{target.name}. Adding Swift Flag..."
target.build_configurations.each do |config|
puts "Configuration: #{config}"
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['$(inherited)']
config.build_settings['OTHER_SWIFT_FLAGS'] << '-DQA'
puts "#{config.build_settings['OTHER_SWIFT_FLAGS'].inspect}"
end
end
if target.name == 'Pods-Test-DEV'
puts "Found #{target.name}. Adding Swift Flag..."
target.build_configurations.each do |config|
puts "Configuration: #{config}"
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['$(inherited)']
config.build_settings['OTHER_SWIFT_FLAGS'] << '-DDEV'
puts "#{config.build_settings['OTHER_SWIFT_FLAGS'].inspect}"
end
end
end
end
After running pod install the post_install successfully adds the flags as shown in the image below for Pods-Test-QA & Pods-Test-DEV.
However, when I run the project using QA or DEV targets and use the following flags it always hits PROD:
#if DEV
print("DEV ENVIRONMENT")
#elseif QA
print("QA ENVIRONMENT")
#else
print("PROD ENVIRONMENT")
#endif
Is there something I'm missing?
Also, for some reason Pods-Test-QA.debug.xcconfig & DEV don't seem to be updated with the flags I've added. Does anyone have any idea why it's not updating in the .xcconfig files?
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
Any help would be appreciated. Thanks in advance.
Using:
cocoapods (1.0.1)
Xcode 7.3.1
If you develop your own pod and would like to add some flags depending on the configuration you can do so by mentioning it in your podspec file.
My goal was to add 'BETA' flag to my pod if parent's project active configuration contains 'BETA' in its name without post-install hooks.
s.pod_target_xcconfig = {
'OTHER_SWIFT_FLAGS[config=*Beta*]' => '-DBETA',
}
Podspec not only allows to do add custom flags but gives an opportunity to use wildcards.
The result: if my parent project uses 'Extra Early Beta' configuration then the following fork in pod's sources goes to 'BETA'
#if BETA
// Beta related code
#else
// Code I don't need in beta.
#endif

How to add a folder reference in my the Pod project in post install?

So, I am trying to add a folder reference in a target that was created by cocoapods.
I found this solution, but it is not working for me. https://github.com/CocoaPods/CocoaPods/issues/3521
I am on cocoapods 0.39. And I only changed the projects to pods_project since that was deprecated.
Also how do you enable logging when running pod update. I tried pod update --verbose, but my puts is not being displayed. :/
=========== UPDATED ===========
post_install do |installer|
puts "printing tests"
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if target.name == "TargetWhereToAddTheFolderOrFileReference"
source_files = target.source_build_phase.files
folderReference = installer.project.add_file_reference("/AbsolutePath/To/FileOrFolder", installer.project.pod_group("PodGroupWhereToAddTheFileOrFolder"), true)
target.source_build_phase.add_file_reference(btsdata, true)
end
end
end
end
post_install do |installer|
// another post install script is here.
end
I've attached the script that is failing plus there was another post_install script below it. That puts "printing tests" is not being called as well....
=========== UPDATED ENDS ===========
Oh, I think the script will only execute the last post_install and not
both. Can you put the code inside the first post_install into the last one?

Cocoapods: turning MagicalRecord logging off

Turning MagicalRecord logging off requires a #define to be made before it is first included in the project, but in the case of a project managed by Cocoapods I have no access to add a #define in the Pods project. How do I turn logging off completely in this scenario?
Took me a few hours to figure out a way to do it, posting here in the hope it will help others.
EDIT: this is not a duplicate as it discusses turning logging off under Cocoapods
You can use a post_install hook to modify pretty much any build setting. Just add this code to your Podfile:
post_install do |installer|
target = installer.project.targets.find{|t| t.to_s == "Pods-MagicalRecord"}
target.build_configurations.each do |config|
s = config.build_settings['GCC_PREPROCESSOR_DEFINITIONS']
s = [ '$(inherited)' ] if s == nil;
s.push('MR_ENABLE_ACTIVE_RECORD_LOGGING=0') if config.to_s == "Debug";
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = s
end
end
Note that this will only disable logging in the debug configuration - logging is disabled by default in the release configuration.
In my case, I was building a library that depended on MagicalRecord. I didn't want my users to have to add a post_install in their Podfile to silence the noisy logging, so I added it to my podspec instead.
s.prefix_header_contents = '#define MR_ENABLE_ACTIVE_RECORD_LOGGING 0'
This automatically adds this #define statement to Pods-prefix.pch, which silences MagicalRecord logging in projects that use my pod.
I updated ank's answer for those using the new cocoapods version alongside MagicalRecord 2.3.0:
post_install do |installer|
target = installer.pods_project.targets.find{|t| t.to_s == "MagicalRecord"}
target.build_configurations.each do |config|
s = config.build_settings['GCC_PREPROCESSOR_DEFINITIONS']
s = [ '$(inherited)' ] if s == nil;
s.push('MR_LOGGING_DISABLED=1') if config.to_s == "Debug";
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = s
end
end
Changes:
project renamed to pods_project
Target Pods-MagicalRecord renamed to MagicalRecord
Macro MR_ENABLE_ACTIVE_RECORD_LOGGING renamed to MR_LOGGING_DISABLED and value changed from 0 to 1
You can switch off logging in Pod project!
Simply add Preprocessor Macros:
Just go into "Pods" (!!!) project.
Then find out Pods-MagicalRecord target.
Choose "Build Settings" tab
Find "Apple LLVM 6.1 Preprocessing" -> "Processor Macros"
Rollout "Processor Macros" and add to "Debug" schema: "MR_ENABLE_ACTIVE_RECORD_LOGGING=0"
It`s all!
For the development branch (version 2.3.0 and higher) of Magical Record logging seems to still not work correctly. When imported like this:
pod 'MagicalRecord', :git => 'https://github.com/magicalpanda/MagicalRecord', :branch => 'develop'
I have no logging output on my Xcode console. But I altered the post_install script of the Cocoapod. The following should enable logging:
https://gist.github.com/Blackjacx/e5f3d62d611ce435775e
With that buildsetting included in GCC_PREPROCESSOR_DEFINITIONS logging of Magical Record can be controlled in 2.3.0++ by using [MagicalRecord setLoggingLevel:]

Resources