Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy deployment-target from root config.xml to platform-specific config.xml before usage in Podfile #1422

Open
expcapitaldev opened this issue Apr 18, 2024 · 6 comments
Labels
info-needed Further information is requested

Comments

@expcapitaldev
Copy link

expcapitaldev commented Apr 18, 2024

Issue
Currently, the deployment-target variable is not being copied from the root config.xml file to the platforms/ios/[App Name]/config.xml before it is accessed in the code. As a result, the script uses the default deployment target from the template (https://github.com/apache/cordova-ios/blob/rel/7.0.1/templates/project/__PROJECT_NAME__/config.xml) instead of the user-specified value in the root config.xml.
It is mean in Podfile we will have deployment-target from root config.xml only first successful prepare hook.
Reproduce is very easy: try to install any pod library with ios target version more than 11. -> you will have error

Expected Behavior
The deployment-target set in the root config.xml should be reflected in the platforms/ios/[App Name]/config.xml before any script or process accesses it.

Proposed Solution
Modify the lib/prepare.js file to ensure that deployment-target and possibly other preferences are copied from the root config.xml to the platforms/ios/[App Name]/config.xml early in the preparation process. This could potentially be implemented at line 250, before the preferences are required by subsequent processes in the script.

Additional Information
This change will ensure that the deployment target and other settings are correctly set according to the project's configuration before they are needed, preventing any default settings from causing conflicts or errors during build or runtime.

Workaround:

@breautek breautek added the info-needed Further information is requested label Apr 18, 2024
@breautek
Copy link
Contributor

This was an issue in cordova-ios 6.3 but I believe was patched in 7.0 (definitely in 7.1).

I have a google maps plugin that requires iOS 15 and I used to manually workaround this issue but it was corrected after I updated my projects to 7.1.

I used:

<platform name="ios">
  <preference name="deployment-target" value="15.0" />
</platform>

adding the plugin and then the platform works as expected, with the generated podfile properly containing 15.0 instead of the default 11.0. This also works if you add the platform first, or use the preference outside of the <platform name="ios"> block. Updating the preference and running cordova prepare ios also shows the changes reflected in both the platform's Podfile and config.xml.

The deployment-target set in the root config.xml should be reflected in the platforms/ios/[App Name]/config.xml before any script or process accesses it.

The expectation of "any script or process" is not quite right. The platform files (including config.xml and Podfile) gets updated during the prepare step, so if you're using an hook, script or process that runs before prepare (such as before_prepare hook) for example, that will run before the config.xml file is updated inside the platform project, and that would be desired behaviour because the hook is for manipulating things before cordova does things. after_prepare is a hook for after cordova manipulates things, etc.

I can not reproduce the issue using the current version of cordova-ios. Simply adding a plugin in which requires a higher deployment target of 11 is not enough to reproduce the issue. If you can provide a sample reproduction project, it may help us understanding the full scope of when the issue reproduces.

@expcapitaldev
Copy link
Author

breautek hi! thanks a lot for your activity here. FBSDKCoreKit https://github.com/CocoaPods/Specs/blob/master/Specs/9/b/5/FBSDKCoreKit/17.0.0/FBSDKCoreKit.podspec.json#L13 is required 12.0
you can try add in any your plugin and do clean build.

<podspec> <config> <source url="https://cdn.cocoapods.org/"/> </config> <pods use-frameworks="true"> <pod name="FBSDKCoreKit" spec="17.0.0"/> </pods> </podspec>
Can you share method or line in cordova-ios library which will be copy deployment-target value from config.xml to Podfile ? I see only https://github.com/apache/cordova-ios/blob/master/lib/Podfile.js#L40 which try to copy value but that value will be empty before installation first pod library

@breautek
Copy link
Contributor

breautek hi! thanks a lot for your activity here. FBSDKCoreKit https://github.com/CocoaPods/Specs/blob/master/Specs/9/b/5/FBSDKCoreKit/17.0.0/FBSDKCoreKit.podspec.json#L13 is required 12.0
you can try add in any your plugin and do clean build.

I still could not reproduce the issue. The config.xml gets copied into platform resources pretty early on in the prepare step. I don't quite remember exactly where it happens in the code. But here's what I did:

I've created a test plugin to wrap around the podspec, the test plugin is effectively just has an empty package.json and the plugin.xml as follows:

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
           id="test-plugin"
      version="5.0.1-dev">

    <name>test</name>
    <description>Cordova test Plugin</description>

    <platform name="ios">
        <podspec>
            <config>
                <source url="https://cdn.cocoapods.org/" />
            </config>
            <pods use-frameworks="true">
                <pod name="FBSDKCoreKit" spec="17.0.0"/>
            </pods>
        </podspec>
    </platform>
</plugin>

I npm pack the plugin which gives a .tgz file.

In a test cordova project, which was empty with no platforms or plugins installed with a base config.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>HelloCordova</name>
    <description>Sample Apache Cordova App</description>
    <author email="[email protected]" href="https://cordova.apache.org">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
</widget>

I added my test-plugin using a command like: cordova plugin add file:../test-plugin/test-plugin-1.0.0.tgz

The plugin gets added successfully. Not installed at this point because there are no platforms. Just added to the project.

Then I add the platform: cordova platform add ios which this installs cordova-ios 7.1.0

The platform is added successfully, but it does fail to completley install the test plugin because the default deployment target is 11.0, as expected since we didn't explicitly declare an alternate deployment-target preference yet.

So we modify our config.xml and add:

<preference name="deployment-target" value="12.0" />

and then run cordova prepare ios, which updates the Podfile and runs pod install, and the FBSDK is installed to the project as expected.

@expcapitaldev
Copy link
Author

I think expected if I do clean build and have inside my main config.xml <preference name="deployment-target" value="13.0" /> and do cordova prepare ios platform shoould be successfully added and prepared with all Pod dependencies without any additional changes. And now my platform should be ready for cordova compile ios command. So, if current flow unexpected please close current issue but I think if my config.xml file has <preference name="deployment-target" value="13.0" /> all Pod dependecies should be installed with 13.0 version.

@breautek
Copy link
Contributor

but I think if my config.xml file has all Pod dependecies should be installed with 13.0 version.

I don't think deployment-target does all pod dependencies, but it maintains the app's Podfile and that is what I observed in the steps I've taken as detailed in #1422 (comment)

If you're still reproducing the issue then confirm that you're running the latest cordova CLI and platform version and share sample project that reproduces the issue that we can look at. If a sample reproduction project cannot be provided then I don't think there's anything we can do to move this forward.

@faugusztin
Copy link

faugusztin commented Oct 19, 2024

Reproduction case with order of steps where pod installation fails is at my repository with cordova-ios 7.1.1.

What triggers it is if we have config.xml and package.json configured with the plugin which requires increased deployment-target and then we run cordova prepare or cordova platform add ios

  • either of those two commands calls cordova-lib to download the platform if the platform doesn't exist in the platforms directory. Up until the platform is ready, any ConfigParser for config.xml grabs the project root config.xml.
  • after platform is created, there is a new config.xml inside platforms/ios/PROJECT_NAME/config.xml. This config.xml doesn't have the deployment-target set at this moment.
  • restore-util.js inside cordova-lib is called, which identifies the need to install plugins based on package.json
  • it then calls cordova-ios lib/Api.js addPlugin method
  • addPlugin then sees plugin requires pods, adds the required changes to Podfile, and then runs pod install --verbose, which fails, because Podfile iOS target is set to default value of 11.0, as platforms/ios/PROJECT_NAME/config.xml doesn't contain the deployment-target property.
  • this all happens before cordova-ios/lib/prepare.js is called, which then calls the updateConfigFile method inside the same file, which sets the deployment-target in config.xml. But this is too late for the Podfile generation and pod install commands executed withing the addPlugin method in previous step.

The reason for this order is in prepare.js. The order here is:

There are two solutions i can think of:

  • adding the platform should already merge the platform specific settings present in config.xml from the project root into the platform specific config.xml. That would be somewhere inside the lib/Api.js createPlatform method.
  • alternatively pod install commands shouldn't be executed within cordova-ios until lib/prepare,js upateConfigFile method is executed, as that is the moment when the config.xml file is actually up to date with settings from the project root config.xml.
  • within cordova-lib/prepare.js swap the order of prepare and plugin install, that is call platform prepare first, then add plugins (but this is both a change outside cordova-ios and also possibly a breaking change if someone relies on current order of calls)

Edit:
Here is Podfile and config.xml from platform folder before and after preparePlatforms call inside cordova-lib src/cordova/prepare.js:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
info-needed Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants