UNPKG

6.28 kBPlain TextView Raw
1# This is a function which is used inside your Podfile.
2#
3# It uses `react-native config` to grab a list of dependencies, and pulls out
4# all of the ones which declare themselves to be iOS/macOS dependencies (by
5# virtue of having a Podspec) and automatically imports those into your current
6# target.
7#
8# See the `IOSNativeModulesConfig` interface in `cli-types/src/ios.ts` to
9# understand what the input data should look like. Be sure to update that file
10# in lock-step with additional data being used here.
11
12require 'pathname'
13require 'cocoapods'
14
15def use_native_modules!(config = nil)
16 if (config.is_a? String)
17 Pod::UI.warn("Passing custom root to use_native_modules! is deprecated.",
18 [
19 "CLI detects root of the project automatically. The \"#{config}\" argument was ignored.",
20 ]);
21 config = nil;
22 end
23
24 # Resolving the path the RN CLI. The `@react-native-community/cli` module may not be there for certain package managers, so we fall back to resolving it through `react-native` package, that's always present in RN projects
25 cli_resolve_script = "try {console.log(require('@react-native-community/cli').bin);} catch (e) {console.log(require('react-native/cli').bin);}"
26 cli_bin = Pod::Executable.execute_command("node", ["-e", cli_resolve_script], true).strip
27
28 if (!config)
29 json = []
30
31 IO.popen(["node", cli_bin, "config"]) do |data|
32 while line = data.gets
33 json << line
34 end
35 end
36
37 config = JSON.parse(json.join("\n"))
38 end
39
40 project_root = Pathname.new(config["project"]["ios"]["sourceDir"])
41
42 packages = config["dependencies"]
43 found_pods = []
44
45 packages.each do |package_name, package|
46 next unless package_config = package["platforms"]["ios"]
47
48 podspec_path = package_config["podspecPath"]
49 configurations = package_config["configurations"]
50
51 # Add a warning to the queue and continue to the next dependency if the podspec_path is nil/empty
52 if podspec_path.nil? || podspec_path.empty?
53 Pod::UI.warn("use_native_modules! skipped the react-native dependency '#{package["name"]}'. No podspec file was found.",
54 [
55 "Check to see if there is an updated version that contains the necessary podspec file",
56 "Contact the library maintainers or send them a PR to add a podspec. The react-native-webview podspec is a good example of a package.json driven podspec. See https://github.com/react-native-community/react-native-webview/blob/master/react-native-webview.podspec",
57 "If necessary, you can disable autolinking for the dependency and link it manually. See https://github.com/react-native-community/cli/blob/master/docs/autolinking.md#how-can-i-disable-autolinking-for-unsupported-library"
58 ])
59 end
60 next if podspec_path.nil? || podspec_path.empty?
61
62 spec = Pod::Specification.from_file(podspec_path)
63
64 # Skip pods that do not support the platform of the current target.
65 if platform = current_target_definition.platform
66 next unless spec.supported_on_platform?(platform.name)
67 else
68 # TODO: In a future RN version we should update the Podfile template and
69 # enable this assertion.
70 #
71 # raise Pod::Informative, "Cannot invoke `use_native_modules!` before defining the supported `platform`"
72 end
73
74 # We want to do a look up inside the current CocoaPods target
75 # to see if it's already included, this:
76 # 1. Gives you the chance to define it beforehand
77 # 2. Ensures CocoaPods won't explode if it's included twice
78 #
79 this_target = current_target_definition
80 existing_deps = current_target_definition.dependencies
81
82 # Skip dependencies that the user already activated themselves.
83 next if existing_deps.find do |existing_dep|
84 existing_dep.name.split('/').first == spec.name
85 end
86
87 podspec_dir_path = Pathname.new(File.dirname(podspec_path))
88
89 relative_path = podspec_dir_path.relative_path_from project_root
90 pod spec.name, :path => relative_path.to_path, :configurations => configurations
91 if package_config["scriptPhases"] && !this_target.abstract?
92 # Can be either an object, or an array of objects
93 Array(package_config["scriptPhases"]).each do |phase|
94 # see https://www.rubydoc.info/gems/cocoapods-core/Pod/Podfile/DSL#script_phase-instance_method
95 # for the full object keys
96 Pod::UI.puts "Adding a custom script phase for Pod #{spec.name}: #{phase["name"] || 'No name specified.'}"
97
98 # Support passing in a path relative to the root of the package
99 if phase["path"]
100 phase["script"] = File.read(File.expand_path(phase["path"], package["root"]))
101 phase.delete("path")
102 end
103
104 # Support converting the execution position into a symbol
105 if phase["execution_position"]
106 phase["execution_position"] = phase["execution_position"].to_sym
107 end
108
109 phase = Hash[phase.map { |k, v| [k.to_sym, v] }]
110 script_phase phase
111 end
112 end
113
114 found_pods.push spec
115 end
116
117 if found_pods.size > 0
118 pods = found_pods.map { |p| p.name }.sort.to_sentence
119 Pod::UI.puts "Auto-linking React Native #{"module".pluralize(found_pods.size)} for target `#{current_target_definition.name}`: #{pods}"
120 end
121
122 absolute_react_native_path = Pathname.new(config["reactNativePath"])
123
124 { :reactNativePath => absolute_react_native_path.relative_path_from(project_root).to_s }
125end
126
127# You can run the tests for this file by running:
128# $ yarn jest packages/platform-ios/src/config/__tests__/native_modules.test.ts
129if $0 == __FILE__
130 require "json"
131 runInput = JSON.parse(ARGF.read)
132
133 unless runInput["captureStdout"]
134 Pod::Config.instance.silent = true
135 end
136
137 return_values = []
138
139 podfile = Pod::Podfile.new do
140 if runInput["podsActivatedByUser"]
141 runInput["podsActivatedByUser"].each do |name|
142 pod(name)
143 end
144 end
145 target 'iOS Target' do
146 platform :ios
147 return_values[0] = use_native_modules!(runInput["dependencyConfig"])
148 end
149 target 'macOS Target' do
150 platform :osx
151 return_values[1] = use_native_modules!(runInput["dependencyConfig"])
152 end
153 end
154
155 unless runInput["captureStdout"]
156 puts podfile.to_hash.merge({ "return_values": return_values }).to_json
157 end
158end