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

Flutter build IPA with --export-options-plist not working #113977

Open
gkustas opened this issue Oct 25, 2022 · 20 comments
Open

Flutter build IPA with --export-options-plist not working #113977

gkustas opened this issue Oct 25, 2022 · 20 comments
Labels
a: build Building flutter applications with the tool a: release Challenges faced when attempting to productionize an app P3 Issues that are less important to the Flutter project platform-ios iOS applications specifically team-ios Owned by iOS platform team tool Affects the "flutter" command-line tool. See also t: labels. triaged-ios Triaged by iOS platform team

Comments

@gkustas
Copy link

gkustas commented Oct 25, 2022

I have a white-label app that needs to be built from the command line. I am using "flutter build IPA" with an export options list to specify code signing specifics. It appears that the values are not getting passed to xcodebuild and the build fails because it doesn't find the provisioning profile.

error: No profiles for 'com.foundationtennis.app' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'com.foundationtennis.app'. Automatic signing is disabled and unable to generate a profile. To enable automatic signing, pass -allowProvisioningUpdates to xcodebuild. (in target 'Runner' from project 'Runner')

NOTE: if I open the XCode workspace and manually set the signing capabilities, flutter build IP works fine.

Steps to Reproduce

  1. Create ExportOptions.plist file like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>generateAppStoreInformation</key>
    <false/>
    <key>method</key>
    <string>app-store</string>
    <key>provisioningProfiles</key>
    <dict>
      <key>com.foundationtennis.app</key>
      <string>a38ecde3-53bc-4910-8068-604b01665598</string>
    </dict>
    <key>signingCertificate</key>
    <string>Apple Distribution</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>844NRE74R7</string>
    <key>uploadBitcode</key>
    <false/>
    <key>uploadSymbols</key>
    <true/>
  </dict>
</plist>
  1. Run flutter build IPA like so:
flutter build ios --release --verbose --export-options-plist=/Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/ExportOptions.plist
  1. See the output from the previous command below

Logs

see attached for verbose output

flutterbuildipa.log

@huycozy huycozy added the in triage Presently being triaged by the triage team label Oct 25, 2022
@huycozy
Copy link
Member

huycozy commented Oct 25, 2022

@gkustas
From your log, I see there is an error with CocoaPods:

Error output from CocoaPods:
           ↳
[        ]     Ignoring ffi-1.15.4 because its extensions are not built. Try: gem pristine ffi --version 1.15.4
               Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
               Ignoring ffi-1.15.4 because its extensions are not built. Try: gem pristine ffi --version 1.15.4

Please see this StackOverflow answer for more details: https://stackoverflow.com/questions/64698820/ignoring-ffi-1-13-1-because-its-extensions-are-not-built-try-gem-pristine-ffi

Also, the valid build command is:

flutter build ipa --export-options-plist=path/to/ExportOptions.plist

Please see this as reference.

@huycozy huycozy added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Oct 25, 2022
@gkustas
Copy link
Author

gkustas commented Oct 25, 2022

As I mentioned in my post, the "flutter build ipa" command worked after manually setting the capabilities in the code workspace. I have a build script that runs "flutter create", copies source files from another project, and edits other files. Then it tries to run "flutter build ipa". So, the Ruby warnings are not the problem. They exist even when the "flutter build ipa" works after manually editing the workspace.

Also - I entered the wrong command in my post. I tries "flutter build ios" later, but that didn't work either. Here is the command entered that produced the log I provided.

flutter build ipa --release --verbose --export-options-plist=/Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/ExportOptions.plist

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Oct 25, 2022
@gkustas
Copy link
Author

gkustas commented Oct 25, 2022

Also note: If you examine the verbose log output, and search for all occurrences of "xcodebuild" (the command that fails), you can see that it isn't using the export options:

[   +2 ms] executing: [/Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/Runner.xcodeproj/] /usr/bin/arch -arm64e xcrun xcodebuild -project /Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/Runner.xcodeproj -scheme Runner -configuration Release -destination generic/platform=iOS -showBuildSettings BUILD_DIR=/Users/george/Develop/flutter_builds/foundation_tennis_v4/build/ios
[        ] executing: [/Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/Runner.xcodeproj/] /usr/bin/arch -arm64e xcrun xcodebuild -project /Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/Runner.xcodeproj -scheme Runner -configuration Release -destination generic/platform=iOS -showBuildSettings BUILD_DIR=/Users/george/Develop/flutter_builds/foundation_tennis_v4/build/ios
[+2790 ms] Command line invocation:
               /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project /Users/george/Develop/flutter_builds/foundation_tennis_v4/ios/Runner.xcodeproj -scheme Runner -configuration Release -destination generic/platform=iOS -showBuildSettings BUILD_DIR=/Users/george/Develop/flutter_builds/foundation_tennis_v4/build/ios
[+4240 ms] Command line invocation:
               /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -configuration Release VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphoneos -destination generic/platform=iOS SCRIPT_OUTPUT_STREAM_FILE=/var/folders/kj/vs0tgb753b756rp3_r9frfb00000gn/T/flutter_tools.6IziGN/flutter_ios_build_temp_dirtRJ8rm/pipe_to_stdout -resultBundlePath /var/folders/kj/vs0tgb753b756rp3_r9frfb00000gn/T/flutter_tools.6IziGN/flutter_ios_build_temp_dirtRJ8rm/temporary_xcresult_bundle -resultBundleVersion 3 FLUTTER_SUPPRESS_ANALYTICS=true COMPILER_INDEX_STORE_ENABLE=NO -archivePath /Users/george/Develop/flutter_builds/foundation_tennis_v4/build/ios/archive/Runner archive

The last one is the one that fails with this error:

                             "issueType" : {
                               "_type" : {
                                 "_name" : "String"
                               },
                               "_value" : "Error"
                             },
                             "message" : {
                               "_type" : {
                                 "_name" : "String"
                               },
                               "_value" : "No profiles for 'com.foundationtennis.app' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'com.foundationtennis.app'. Automatic signing is disabled and unable to generate a profile. To enable automatic signing, pass -allowProvisioningUpdates to xcodebuild."
                             }

@huycozy
Copy link
Member

huycozy commented Oct 26, 2022

@gkustas Thanks for providing more info. Labeling the issue for further insights from the team.

@huycozy huycozy added platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels. will need additional triage This issue or PR needs attention during weekly triage a: build Building flutter applications with the tool and removed in triage Presently being triaged by the triage team labels Oct 26, 2022
@gkustas
Copy link
Author

gkustas commented Oct 26, 2022

After looking into this further, I know what is going on. I also have a proposal for the Flutter team that will allow me and others to create and build a Flutter application all from the command line. First, the explanation:

"flutter build ipa" uses xcodebuild twice. The first time it creates the archive bundle like this:

xcodebuild -workspace Runner.workspace <more parameters follow>

Then it exports the ipa from the archive like this:

xcodebuild -exportArchive -exportOptionsPlist <more parameters follow>

The problem is that the first time flutter calls xcodebuild, it expects that the workspace has already been configured for code signing. If you want to create and build entirely from the command line with no human intervention, you are out of luck. xcodebuild will fail with the error I posted above (No profiles for 'xxx' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'xxx').

MY PROPOSAL: flutter build ipa should accept additional code signing parameters and pass them on to xcodebuild. They match the build properties found in the code project file located in ios/Runner/Runner.xcodeproj/project.pbxprod

  • DEVELOPMENT_TEAM
  • CODE_SIGN_STYLE
  • PROVISIONING_PROFILE_SPECIFIER

NOTE: These parameters are NOT documented in the xcodebuild -h help info, but they were added in XCode version 8. Read more about code signing changes in XCode here.

My solution to the problem was to install a node plugin called cordova-node-xcode and use it to edit the workspace project config file located in ios/Runner/Runner.xcodeproj/project.pbxprod. I added the build properties specified above. I called "flutter build ipa", and everything was built and exported properly. I've included my nodejs code below in case anyone wants to use it. NOTE: the code also demonstrates how to obtain the code signing properties by extracting them from the actual mobile provision files.

async function buildIt(brand) {
	return new Promise(async (resolve) => {
		try {
			var brandTargetFolder = `${TARGET_FOLDER}/${brand}`
			var brandSourceFolder = `${BRANDS_FOLDER}/${brand}`
			// *** IOS first...
			if (argv.platform == "ios" || argv.platform == "all") {
				// get the provisioning profile(s). We'll export both distribution and debug
				var provProfiles = fs.readdirSync(`${brandSourceFolder}`).filter(function (file) {
					return file.toLowerCase().endsWith(".mobileprovision")
				})
				var profileName
				var profileUUID
				var teamID
				var teamName				
				provProfiles.forEach(f => {
					var fileName = f.split(".")[0]
					var profilePlistData = execSync(`openssl smime -inform der -verify -noverify -in "${brandSourceFolder}/${f}"`, { "cwd": `${brandTargetFolder}/ios` })
					var profile = plist.parse(profilePlistData)
					if (profile["Entitlements"]["aps-environment"] == "production") {
						profileUUID = profile["UUID"]
						profileName = profile["Name"]
						teamID = profile["TeamIdentifier"][0]
						teamName = profile["TeamName"]
						// make sure the mobile provision is installed
						var profilePath = `${HOME}/Library/MobileDevice/Provisioning Profiles/${profileUUID}.mobileprovision`
						if (!fs.existsSync(profilePath)) {
							console.log("installing mobile provision file: " + f)
							fs.copySync(`${brandSourceFolder}/${f}`, profilePath)
						}
					}
					else {
						console.log(warning(`Found debug mobile profile '${profile["UUID"]}', but only building distribution archives.`))
					}
				})
				if (null == profileUUID) {
					console.log(error("Production mobile provisioning profile not found in " + brandSourceFolder))
					resolve(1)
					return
				}
				else {
					console.log(`creating export options list...`)
					var exportOptions = plist.parse(fs.readFileSync(`${TOOLS_FOLDER}/ExportOptions.plist`))
					var profileObject = new Object()
					profileObject[_config.package] = profileUUID
					exportOptions.provisioningProfiles = profileObject
					plist.writeFileSync(`${brandTargetFolder}/ios/ExportOptions.plist`, exportOptions)
					//edit xcode project to include signing capabilities
					console.log(`editing xcode project file to include provisioning profile ${profileName}(${profileUUID})`)
					var projectPath = `${brandTargetFolder}/ios/Runner.xcodeproj/project.pbxproj`
					fs.appendFileSync(projectPath, '\n')
					var pbxProj = xcode.project(projectPath)
					pbxProj.parse(error => {
						if (!error) {
							pbxProj.addBuildProperty('DEVELOPMENT_TEAM', teamID)
							pbxProj.addBuildProperty('CODE_SIGN_IDENTITY', "\"iPhone Distribution\"")
							pbxProj.addBuildProperty('CODE_SIGN_STYLE', "Manual")
							pbxProj.addBuildProperty('PROVISIONING_PROFILE_SPECIFIER', profileName)
							fs.writeFileSync(projectPath, pbxProj.writeSync())
						} else {
							console.log(error)
						}
					})

					// build the IPA 
					await shell(`flutter build ipa --release  --export-options-plist "${brandTargetFolder}/ios/ExportOptions.plist"`, {"cwd" : brandTargetFolder})
					
				}
			}
	})	
}

@jmagman
Copy link
Member

jmagman commented Oct 27, 2022

Most of the iOS Flutter commands assume that you have either set up code signing in the Xcode project, or it will drop back to flutter config ios-signing-cert. You can work around this by setting environment variables with the FLUTTER_XCODE_* prefix, like FLUTTER_XCODE_DEVELOPMENT_TEAM #43553. Those variables will be passed into the xcodebuild invocations--we use this in our own CI system.

This is similar to #106612 but not quite the same, it should all build with --export-options-plist.

flutter build ipa should accept additional code signing parameters and pass them on to xcodebuild

This is probably the right solution to both issues.

@jmagman jmagman added the a: release Challenges faced when attempting to productionize an app label Oct 27, 2022
@jmagman jmagman added this to To do in Improved iOS App Releases via automation Oct 27, 2022
@gkustas
Copy link
Author

gkustas commented Oct 27, 2022

Thank you @jmagman! I wish I knew this before I jumped through all of those hoops, but I guess I didn't scour the existing issues very well. :-)

This is a much better solution than my proposal.

@jmagman
Copy link
Member

jmagman commented Oct 27, 2022

We're working on making the iOS release process less painful, and require less Xcode spelunking. Thanks for your investigation!

@Hixie Hixie removed the will need additional triage This issue or PR needs attention during weekly triage label Nov 1, 2022
@mvacha
Copy link

mvacha commented Nov 15, 2022

We have just spent days with @petrnymsa trying to get ipa signing to work propertly in our CI/CD pipeline. Our pipeline works similarly to the flutter build ipa command, and this is what we have learned:

As @gkustas correctly says, everytime xcodebuild is called, it tries to do codesigning:

"flutter build ipa" uses xcodebuild twice. The first time it creates the archive bundle like this:
xcodebuild -workspace Runner.workspace <more parameters follow>
Then it exports the ipa from the archive like this:
xcodebuild -exportArchive -exportOptionsPlist <more parameters follow>
The problem is that the first time flutter calls xcodebuild, it expects that the workspace has already been configured for code signing.

So either the codesigning on the specified project/target, or explicit code-signing parameters (CODE_SIGN_STYLE, PROVISIONING_PROFILE_SPECIFIER, etc.) must be properly configured, otherwise it fails. As it does for the OP.

The specified -exportOptionsPlist parameter is only accepted by xcodebuild -exportArchive command, and it only affects generation (and codesigning) of the final .ipa file (https://www.matrixprojects.net/p/xcodebuild-export-options-plist/).

The workaround we have found is to explicitly disable signing of the .xcarchive file when -exportOptionsPlist is used:

xcodebuild -workspace Runner.workspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>

The only signing that happens in the build process is then in the final step when .ipa file is created using xcodebuild -exportArchive -exportOptionsPlist ....

@gkustas
Copy link
Author

gkustas commented Nov 15, 2022

The solution to this problem was resolved here: #43553

Thanks to @jmagman who mentioned it earlier in this thread. It makes everything easier - just set the environment variables FLUTTER_XCODE_ * (eg. FLUTTER_XCODE_DEVELOPMENT_TEAM) in your shell before calling flutter build ipa.

@jmagman
Copy link
Member

jmagman commented Nov 15, 2022

The workaround we have found is to explicitly disable signing of the .xcarchive file when -exportOptionsPlist is used:

xcodebuild -workspace Runner.workspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>

The only signing that happens in the build process is then in the final step when .ipa file is created using xcodebuild -exportArchive -exportOptionsPlist ....

Oh interesting that building the xcarchive with no codesigning and then re-codesigning during -exportArchive works, I wouldn't have thought so...

@mvacha
Copy link

mvacha commented Nov 17, 2022

The solution to this problem was resolved here: #43553

Thanks to @jmagman who mentioned it earlier in this thread. It makes everything easier - just set the environment variables FLUTTER_XCODE_ * (eg. FLUTTER_XCODE_DEVELOPMENT_TEAM) in your shell before calling flutter build ipa.

I agree that this is an absolute fool-proof way to do that, but it is more of a workaround than a solution of the root cause.

Oh interesting that building the xcarchive with no codesigning and then re-codesigning during -exportArchive works, I wouldn't have thought so...

A friend pointed out to me that .ipa files can be resigned - e.g. you can have a pipeline that builds .ipa signed with App Distribution certificate and resign it as Ad-Hoc to avoid building the app twice. So the idea was that all previous signing during build must be irrelevant for the final .ipa and it really is.

@jmagman
Copy link
Member

jmagman commented Nov 18, 2022

Thanks for the tip, that simplifies things.

@simranjeet09

This comment was marked as duplicate.

@Veeeeksi
Copy link

I have used similar approach where I make unsigned archive first via command line and then use fastlane "build_app" method to sign the archive.

@flutter-triage-bot flutter-triage-bot bot added the triaged-ios Triaged by iOS platform team label Jul 8, 2023
@stuartmorgan stuartmorgan added the P2 Important issues not at the top of the work list label Aug 28, 2023
@Aiden0801
Copy link

I was able to successfully export ipa file using manuual sign.
Here is the code I used to build...

      # Build and sign the ipa using a single flutter command
      - name: Building IPA
        run: |
          flutter build ios --release --no-codesign
          xcodebuild -workspace ios/Runner.xcworkspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO -scheme Runner -configuration Release -destination "generic/platform=iOS" archive -archivePath build/ios/Runner.xcarchive
          xcodebuild -exportArchive -archivePath build/ios/Runner.xcarchive -exportOptionsPlist ios/ExportOptions.plist -exportPath build/ios/ipa/Runner.ipa

Anyway I could not find a way to export using flutter build ipa.
Any thoughts on this?

@simranjeet09
Copy link

simranjeet09 commented Sep 18, 2023

Try this

  1. Open xcode and uncheck automatically manage provision profile

  2. Create a file called ExportOptions.plist

  3. Mention associated provisioning profiles in this file

  4. Run

flutter build ipa --release --export-options-plist=ios/ExportOptions.plist

ExportOptions.plist should look like this


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>compileBitcode</key>
    <true/>
    <key>method</key>
    <string>app-store</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>BUNDLE NAME HEREr</key>
        <string>PROVISIONING PROFILE NAME</string>
    </dict>
    <key>signingCertificate</key>
    <string>iOS Distribution</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>TEAM ID HERE</string>
    <key>thinning</key>
    <string>&lt;none&gt;</string>
</dict>
</plist>


@kent-williams
Copy link

For anyone still getting this in their GitHub actions Error (Xcode): No profiles for 'your.bundle.id' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'your.bundle.id', after following the instructions above.
You must save the provisioning profile settings in your xcode project settings project.pbxproj.

@jmagman jmagman added P3 Issues that are less important to the Flutter project and removed P2 Important issues not at the top of the work list labels Feb 10, 2024
@abhishekbedi1432
Copy link

abhishekbedi1432 commented May 4, 2024

I recently was able to fix this by

  1. Using fastlane match to setup the code signing by downloading the profiles starting with keyword match
  2. Using update_code_signing command to update the provisioning profile (again the profile names start with match)
  3. Using 'flutter build ipa --export-options-plist=/path/to/plist' . Here the plist also has a dictionary node specifying bundle id and profile name. The plist also had entitlement node info.

This way, i created the ipa in one shot!

However, i am still figuring out how to include xcode live widget extension also.

@fingerart
Copy link

fingerart commented May 14, 2024

According to @jmagman #113977 (comment) I successfully built the ipa
Prerequisites:

  1. Prepare the profile file in ~/Library/MobileDevice/Provisioning Profiles
  2. Import the p12 certificate into the keychain

Add these to environment variables (https://help.apple.com/xcode/mac/current/#/itcaec37c2a6)

FLUTTER_XCODE_DEVELOPMENT_TEAM: your_dev_tem_id
FLUTTER_XCODE_PROVISIONING_PROFILE_SPECIFIER: prfile name or uuid
FLUTTER_XCODE_CODE_SIGN_IDENTITY: Certificate name or type(Apple Distribution)

Build commands:
flutter build ipa --export-options-plist=path/to/ExportOptions.plist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: build Building flutter applications with the tool a: release Challenges faced when attempting to productionize an app P3 Issues that are less important to the Flutter project platform-ios iOS applications specifically team-ios Owned by iOS platform team tool Affects the "flutter" command-line tool. See also t: labels. triaged-ios Triaged by iOS platform team
Projects
Development

No branches or pull requests