2015-05-14 12 views
21

Mój projekt wykorzystuje pliki CocoaPods oraz niestandardowe pliki xcconfig. Do tej pory nie spowodowało to żadnych problemów: Właśnie musiałem uzyskać #include konfigurację wygenerowaną przez CocoaPods na końcu mojej niestandardowej konfiguracji.W jaki sposób mogę zmodyfikować OTHER_LDFLAGS za pomocą haka poinstalacyjnego CocoaPods?

Jednak napotkam problem, w którym trzeba warunkowo określić OTHER_LDFLAGS na podstawie , ale nie mogę dowiedzieć się, jak to zrobić.

Na początek Próbowałem po prostu rejestrowania OTHER_LDFLAGS takiego, ale flagi nie są faktycznie zalogowany:

post_install do |installer_representation| 
    installer_representation.project.targets.each do |target| 
    target.build_configurations.each do |config|  

     name = target.name 
     puts "Target Found: #{name}" 

     flags = config.build_settings['OTHER_LDFLAGS'] 
     puts "OTHER_LDFLAGS Found: #{flags}" 
    end 
    end 
end 

Wyjście wygląda następująco:

Target Found: Pods-ProjectName-DependencyName1 
OTHER_LDFLAGS Found: # nothing here...? 
Target Found: Pods-ProjectName-DependencyName2  
OTHER_LDFLAGS Found: # again nothing... 
# etc... 
Target Found: Pods-ProjectName # Cool, this is the main target pod 
OTHER_LDFLAGS Found: # ... 

Jak można Naprawdę modyfikuję OTHER_LDFLAGS za pomocą haka poinstalacyjnego CocoaPods?

+1

Co chcesz dokładnie zrobić? Jeśli chcesz zmienić OTHER_LDFLAGS, możesz to zrobić bezpośrednio w specyfikacji stringu. – Loegic

+0

W końcu nie wydaje mi się, żeby to pytanie miało sens. Jak mówi @Loegic: strąki mogą rozpocząć deklarowanie OTHER_LDFLAGS w swoich podspeckach. Nie chcesz się bawić z celami IMO. – hfossli

+0

@Loegic, mam nieszczęśliwą sytuację, w której muszę użyć statycznego frameworku innej firmy, który nie ma CocoaPod i jest zbyt duży, by działał dobrze jako strąk (8 GB ...: /). Napisałem skrypty, aby to zrobić, ale wymaga to również dodania do OTHER_LDFLAGS. Nie możesz przesłonić OTHER_LDFLAGS w ustawieniach budowania celu, inaczej CocoaPods xcconfigs zostanie zignorowany. Nie możesz tego zrobić w niestandardowym xcconfig, lub jedna lub inne flagi konfiguracji (w zależności od tego, w jaki sposób dołączasz pod xcconfig) zostaną nadpisane. Tak, pomyślałem, aby użyć haka instalacyjnego. –

Odpowiedz

22

Natknąłem się na ten sam problem. Najpierw próbował modyfikować OTHER_LDFLAGS z oczywistym:

post_install do |installer| 
    installer.pods_project.targets.each do |target| 
     if target.name == "Pods-SomeTarget" 
      puts "Updating #{target.name} OTHER_LDFLAGS" 
      target.build_configurations.each do |config| 
       config.build_settings['OTHER_LDFLAGS'] ||= ['$(inherited)'] 
       config.build_settings['OTHER_LDFLAGS'] << '-l"AFNetworking"' 
      end 
     end 
    end 
end 

ale to nie działa. Odpowiedni xcconfig nie otrzymał zmiany. W końcu znalazłem obejście, który działa dobrze - najpierw przeczytać odpowiednią zawartość pliku xcconfig w haku post_intall, modyfikować i zapisywać je z powrotem:

v1.0

post_install do |installer| 
    installer.pods_project.targets.each do |target| 
     if target.name == "Pods-SomeTarget" 
      puts "Updating #{target.name} OTHER_LDFLAGS" 
      target.build_configurations.each do |config| 
       xcconfig_path = config.base_configuration_reference.real_path 
       xcconfig = File.read(xcconfig_path) 
       new_xcconfig = xcconfig.sub('OTHER_LDFLAGS = $(inherited)', 'OTHER_LDFLAGS = $(inherited) -l"AFNetworking"') 
       File.open(xcconfig_path, "w") { |file| file << new_xcconfig } 
      end 
     end 
    end 
end 

EDIT: Poprawa ponad the v1.0. Zamiast bezpośrednio pracować z treścią xcconfig String, przeczytaj xccconfig w pliku konfiguracyjnym build_configuration Hash, zmodyfikuj skrót, a następnie opróżnij go na xcconfig.

v1.5

post_install do |installer| 
    installer.pods_project.targets.each do |target| 
     if target.name == "Pods-SomeTarget" 
      puts "Updating #{target.name} OTHER_LDFLAGS" 
      target.build_configurations.each do |config| 
       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 OTHER_LDFLAGS 
       build_settings['OTHER_LDFLAGS'] << '-l"AFNetworking"' 

       # write build_settings dictionary to xcconfig 
       build_settings.each do |key,value| 
        File.open(xcconfig_path, "a") {|file| file.puts key = value} 
       end 
      end 
     end 
    end 
end 
+0

+1: To wygląda obiecująco! :) Mam zamiar dać to odejść i upewnić się, że działa zgodnie z przeznaczeniem. Jeśli tak, dam ci wygraną. –

+0

@ JRG-Developer Czy to działa dla ciebie? – mrvincenzo

+0

"v1.5" działał niesamowicie. Jedyną zmianą, którą musiałem wprowadzić, było 'file = File.open (xcconfig_path," w ")' (używając write zamiast append). Dzięki! –

0

Nie mogłem wymyślić dobrego sposobu modyfikacji xcconfig. Mogę je wyświetlać, a nawet zmieniać je po instalacji, ale moje zmiany nie zostaną zapisane na strądzie xcconfig.

To co mogę używać, aby zmodyfikować plik xcconfig:

post_install do |installer| 
    installer.libraries.each do |lib| 
     if lib.name != "Pods-lib" 
      next 
     end 
     target = lib.library 
     target.xcconfigs.each do |key, value| 
      config_file_path = target.xcconfig_path(key) 
      File.open("config.tmp", "w") do |io| 
       io << File.read(config_file_path).gsub(/-l"c\+\+"/, '').gsub(/-l"icucore"/,'') 
      end 

      FileUtils.mv("config.tmp", config_file_path) 
     end 
    end 
end 

Sposób modyfikowania OTHER_LD_FLAGS na stanowisku zainstalować skrypt bezpośrednio jest następujący. Ale ponieważ nie zapisano ich w pliku xcconfig, musiałem odwołać się do hacky powyżej. Jeśli potrafisz wymyślić, jak zapisać te zmiany w pliku, byłoby to niesamowite.

post_install do |installer| 
    libs_to_remove = ['c++', 'icucore'] 
    installer.libraries.each do |lib| 
     if lib.name != "Pods-lib" 
      next 
     end 
     target = lib.library 
     target.xcconfigs.each do |key, value| 
      other_ld = value.other_linker_flags 
      libs = other_ld[:libraries] 
      libs.subtract(libs_to_remove) 
      value.other_linker_flags[:libraries] = libs 
     end 
    end 
end 
2

Oto przypadek użycia dla v1.0: natknąłem tego wątku, ponieważ mamy wiele aplikacji, które wszystkie mają indywidualne xcconfigs i podzielają wspólne pliki xcconfig. Używanie strąków zaczęło się rozpadać, gdy dodaliśmy rozszerzenie aplikacji jako cel i nie możemy już dzielić dziedziczenia poziomu projektu dla aktywnej konfiguracji (jak debugowanie). Sooooo używając v1.0 z góry można ponownie wymienić elementy, takie jak poziom pod OTHER_LDFLAGS do PODS_OTHER_LDFLAGS a następnie bezpiecznie #include je do swoich xcconfigs (bez depcząc innych wartości) połączyć je ze zdrowym, aplikacji, ustawień docelowe ala:

OTHER_LDFLAGS = $(inherited) $(PODS_OTHER_LDFLAGS) $(COMMON_OTHER_LDFLAGS) 

tak więc, w moim strąków złożyć mamy sekcję takiego wewnątrz pętli jak v1.0:

puts "Updating #{target.name} adapting settings like OTHER_LDFLAGS for merging at target level" 
    xcconfig_path = config.base_configuration_reference.real_path 
    xcconfig = File.read(xcconfig_path) 
    xcconfig = xcconfig.sub('OTHER_LDFLAGS = $(inherited)', 'PODS_OTHER_LDFLAGS = ') 
    xcconfig = xcconfig.sub('OTHER_CFLAGS = $(inherited)', 'PODS_OTHER_CFLAGS = ') 
    xcconfig = xcconfig.sub('GCC_PREPROCESSOR_DEFINITIONS = $(inherited)', 'PODS_GCC_PREPROCESSOR_DEFINITIONS = ') 
    xcconfig = xcconfig.sub('HEADER_SEARCH_PATHS = $(inherited)', 'PODS_HEADER_SEARCH_PATHS = ') 
    xcconfig = xcconfig.sub('LIBRARY_SEARCH_PATHS = $(inherited)', 'PODS_LIBRARY_SEARCH_PATHS = ') 
    File.open(xcconfig_path, "w") { |file| file << xcconfig } 

i xcconfig kleju, który jest ustawiony na poziomie ala docelowa:

#include "../../Pods/Target Support Files/Pods-Fusion/Pods-Fusion.release.xcconfig" 
#include "../../shared/main/config/release.xcconfig" 
#include "../../shared/main/config/allTargetsCommon.xcconfig" 
#include "Fusion.xcconfig" 
#include "../../shared/main/config/merge.xcconfig" 

wh ere różne ustawienia app/config/common/strąk są ściągane i merge.xcconfig ciągnie wszystko razem tak:

//merge up the pods, common base target and target configs 

GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(PODS_GCC_PREPROCESSOR_DEFINITIONS) $(TARGET_GCC_PREPROCESSOR_DEFINITIONS) $(APP_GCC_PREPROCESSOR_DEFINITIONS) 
HEADER_SEARCH_PATHS = $(inherited) $(PODS_HEADER_SEARCH_PATHS) 
OTHER_CFLAGS = $(inherited) $(PODS_OTHER_CFLAGS) $(TARGET_OTHER_CFLAGS) 
OTHER_LDFLAGS = $(inherited) $(PODS_OTHER_LDFLAGS) $(COMMON_OTHER_LDFLAGS) 
4

Na podstawie powyższych odpowiedzi i oficjalnych rubydocs z cocoapods i xcodeproj, wymyśliłem to rozwiązanie, które jest wyłącznie w oparciu o API dostarczanych przez wyżej wspomniane perełki:

post_install do |installer| 
    installer.aggregate_targets.each do |aggregate_target| 
     aggregate_target.xcconfigs.each do |config_name, config_file| 
      config_file.attributes['OTHER_LDFLAGS'] << '-l"AFNetworking"' 

      xcconfig_path = aggregate_target.xcconfig_path(config_name) 
      config_file.save_as(xcconfig_path) 
     end 
    end 
end 

To skutecznie dodaje flagę łącznikową -l"AFNetworking" do dowolnego pliku xcconfig jakiejkolwiek łącznej docelowej („Pod -...”).

Testowane z 1.2.0 i 1.3.0 cocoapods na Xcode8.3.3 i Xcode9 Beta 4.