Cocoapods: post_install hook can't add preprocessor macros to the Xcode project?

Created on 1 Dec 2015  路  11Comments  路  Source: CocoaPods/CocoaPods

I have a project ,named Sunset and I had have added an Adhoc configuration to it. I want to add a preprocessor macro ADHOC ,like DEBUG .So I use the following code :

post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
    puts target.name
    puts target.product_name
        target.build_configurations.each do |config|
           puts config.name
           puts config.inspect
           if config.name == "AdHoc"
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] <<  "ADHOC"
           elsif config.name == "Debug"
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] <<  "_DEBUG"
           elsif config.name == "Release"
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] <<  "RELEASE"
       end
           puts config.build_settings

    end
end
end

This code does add those macros ,_DEBUG,ADHOC,RELEASE to the targets under pods which was generated by pod,like Pods-Sunset and AFNetworking,check the picture below.But nothing was added to the Sunset Project and the Sunset target.So ,this code is not working

    NSInteger option = 1;
 #ifdef ADHOC
   option = 3;
 #endif

So, can pod add those macros to the Sunset target.

I use cocoapods 0.38.2 ,Xcode 7.1.1.

1 pic_hd
2 pic_hd

Most helpful comment

So you have to save the app project, in my case:

post_install do |installer|
  app_project = Xcodeproj::Project.open(Dir.glob("*.xcodeproj")[0])
  app_project.native_targets.each do |target|
    if target.name == 'TargetName'
      target.build_configurations.each do |config|
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'SMTH=1']
        app_project.save
      end
    end
  end
end

All 11 comments

Right, you're only modifying the Pods project, not your own app project.

@segiddins Are there any ways can modify my own app project by using post_install?

Sure! app_project = Xcodeproj::Project.open('app.xcodeproj'); app_project.native_targets.each do { ... }

@segiddins, I'm trying your Xcodeproj::Project.open('app.xcodeproj') idea and running into a curious issue.

I use a post_install hook to set CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES to YES.

Here's my post_install hook:

post_install do |installer|

  files = Dir.glob("*.xcodeproj")
  proj_file = files[0]

  app_project = Xcodeproj::Project.open(proj_file);

  #Set allow non modular includes on app target to 'yes'
  app_project.native_targets.each do |target|

      puts 'native_targets: ' + target.inspect

      target.build_configurations.each do |config|

        puts 'config: ' + config.inspect
        config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
        puts 'build_settings: ' + config.build_settings.inspect
      end

  end

  #Do same on pod project target
  installer.pods_project.build_configuration_list.build_configurations.each do |configuration|
    configuration.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
  end

end

When I log the build_configuration, I can see that the property has been set:

#puts 'build_settings: ' + config.build_settings.inspect
build_settings: {
    "ALWAYS_SEARCH_USER_PATHS"=>"YES", 
    "ARCHS"=>"$(ARCHS_STANDARD)", 
    "ASSETCATALOG_COMPILER_APPICON_NAME"=>"AppIcon", 
    "BUNDLE_LOADER"=>"", 
    "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"=>"YES", 
    "CLANG_CXX_LANGUAGE_STANDARD"=>"compiler-default", 
    "CLANG_CXX_LIBRARY"=>"compiler-default", 
    "CLANG_ENABLE_MODULES"=>"YES", 
    "CLANG_ENABLE_OBJC_ARC"=>"YES", 
    "CLANG_WARN__DUPLICATE_METHOD_MATCH"=>"YES", 
    "CLANG_WARN_BOOL_CONVERSION"=>"YES", 
    "CLANG_WARN_CONSTANT_CONVERSION"=>"YES", 
    "CLANG_WARN_ENUM_CONVERSION"=>"YES", 
    "CLANG_WARN_INT_CONVERSION"=>"YES", 
    "CODE_SIGN_IDENTITY"=>"iPhone Developer", 
    "CODE_SIGN_IDENTITY[sdk=iphoneos*]"=>"iPhone Developer", 
    "COPY_PHASE_STRIP"=>"NO", 
    "DEAD_CODE_STRIPPING"=>"NO", 
    "DEBUG_INFORMATION_FORMAT"=>"dwarf-with-dsym", 
    "DEFINES_MODULE"=>"YES", 
    "ENABLE_BITCODE"=>"NO", 
    "ENABLE_TESTABILITY"=>"NO", 
    "GCC_C_LANGUAGE_STANDARD"=>"compiler-default", 
    "GCC_DYNAMIC_NO_PIC"=>"NO", 
    "GCC_INPUT_FILETYPE"=>"automatic", 
    "GCC_OPTIMIZATION_LEVEL"=>"0", 
    "GCC_PRECOMPILE_PREFIX_HEADER"=>"YES", 
    "GCC_PREFIX_HEADER"=>"****_Prefix.pch", 
    "GCC_SYMBOLS_PRIVATE_EXTERN"=>"NO", 
    "GCC_WARN_64_TO_32_BIT_CONVERSION"=>"YES", 
    "GCC_WARN_UNDECLARED_SELECTOR"=>"YES", 
    "GCC_WARN_UNUSED_FUNCTION"=>"YES", 
    "INFOPLIST_FILE"=>"Info.plist", 
    "IPHONEOS_DEPLOYMENT_TARGET"=>"9.0", 
    "LD_RUNPATH_SEARCH_PATHS"=>"$(inherited) @executable_path/Frameworks", 
    "MODULE_NAME"=>"", 
    "ONLY_ACTIVE_ARCH"=>"YES", 
    "OTHER_CFLAGS"=>"$(inherited)", 
    "OTHER_LDFLAGS"=>"$(inherited)", 
    "PRODUCT_NAME"=>"****", 
    "PROVISIONING_PROFILE"=>"", 
    "SDKROOT"=>"iphoneos", 
    "STRIP_INSTALLED_PRODUCT"=>"NO", 
    "SWIFT_OBJC_BRIDGING_HEADER"=>"", 
    "SWIFT_OPTIMIZATION_LEVEL"=>"-Onone", 
    "TARGETED_DEVICE_FAMILY"=>"1,2", 
    "TEST_HOST"=>"$(BUNDLE_LOADER)", 
    "USE_HEADERMAP"=>"YES", 
    "USER_HEADER_SEARCH_PATHS"=>"\"${PROJECT_DIR}/Pods\"/**", 
    "VALID_ARCHS"=>"armv7 armv7s arm64 i386", 
    "GCC_PREPROCESSOR_DEFINITIONS"=>[
        "$(inherited)", 
        "COCOAPODS=1", 
        "DEBUG=1"
    ],
    "HEADER_SEARCH_PATHS"=>[
        "$(inherited)", 
        "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", "/usr/include/libxml2/**"
    ], 
    "LIBRARY_SEARCH_PATHS"=>[
        "$(inherited)", 
        "$(SRCRoot)/Resources/libraries"
    ], 
    "FRAMEWORK_SEARCH_PATHS"=>[
        "$(inherited)", 
        "/Users/****/Sites/xcode_workspace/eo/eo-client/eo-****", 
        "$(PROJECT_DIR)"
    ],      
}

So, the property has been set! Hooray! However, it seems Xcode doesn't agree:

screen shot 2016-01-25 at 4 04 57 pm

I'm not sure why this property would be overridden. Nothing else in my project appears to be writing the property. I've tested on both my project in progress and a brand new project. If I set the value directly in Xcode, of course it works. But I'm trying to make a pod that contains a lot of functionality and ideally the pod would set this value when installed. Maybe that's not a good idea? Regardless, this script should work, and even indicates that it IS working...

Any ideas?

@ExoticObjects sorry, but that sort of question belongs more on Stack Overflow since its not a bug in CocoaPods itself, but rather about writing a post-install hook. Upon a glance though, you're never saving the project.

Well that would do it! Thanks, as before, for the help! Confusion arose because when setting the property in the pods project, you don't need to invoke the save method. But on the app project, you do...

how to save

@songjianboy try something like:

post_install do |pi|
    pi.aggregate_targets.first.user_project.save

save should be available as method on any project ;)

So you have to save the app project, in my case:

post_install do |installer|
  app_project = Xcodeproj::Project.open(Dir.glob("*.xcodeproj")[0])
  app_project.native_targets.each do |target|
    if target.name == 'TargetName'
      target.build_configurations.each do |config|
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'SMTH=1']
        app_project.save
      end
    end
  end
end

I use @younke 's method, but the use project was reverted.
I use post install hook to change the [CP] Copy Pod Resource phase

post_install do |installer|
    app_project = installer.aggregate_targets.first.user_project
    main_target = app_project.targets.first
    build_phases = main_target.build_phases.grep(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
    phase = build_phases[1]
    phase.input_paths.clear
    phase.shell_script = ""
    app_project.save
end

I can see the proj file was modified as I expected and then it gets reverted. So is it work in nowadays (Oct 2018)?

thanks for @younke , it helps me!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

intelliot picture intelliot  路  3Comments

hmistry picture hmistry  路  3Comments

gerchicov-bp picture gerchicov-bp  路  3Comments

pallaviMN picture pallaviMN  路  3Comments

pronebird picture pronebird  路  3Comments