Skip to content

Create iOS IPA from command line #13065

Closed

Description

@passsy

Flutter doesn't allow me to build an .ipa which can be published to hockeyapp/fabric or the app store.

# creates an .app not an .ipa 
flutter build ios --release

Manual bundling is required:

xcodebuild -exportArchive -archivePath build/ios/iphoneos/Runner.app -exportPath build/ios/iphoneos/ -exportOptionsPlist ci/enterprise-options.plist

Flutter includes tools such as measuring the ipa size #4609, but I can't find a way to create an .ipa.

A followup issue for Generate a production-ready IPA from a single command is still missing

Activity

  1. eseidelGoogle commented on Nov 17, 2017

    @eseidelGoogle
    Contributor

    I don't know the details, but if it's really a simple as just one command we could certainly wrap that in flutter build ipa or similar. :) I had previously been under the impression that the XCode GUI had to be involved with .ipa generation (e.g. it wasn't possible from the command line). @cbracken or @xster would know more.

  2. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    platform-iosiOS applications specifically
    on Nov 17, 2017
  3. sethladd commented on Nov 17, 2017

    @sethladd
    Contributor
  4. passsy commented on Nov 17, 2017

    @passsy
    ContributorAuthor

    Also running xcodebuild -exportArchive currently fails with xcode8 and xcode9

    12:50:17 + xcodebuild -exportArchive -archivePath build/ios/iphoneos/Runner.app -exportPath build/ios/iphoneos/ -exportOptionsPlist ci/enterprise-options.plist
    12:50:17 2017-11-17 13:50:17.672 xcodebuild[55483:4933639] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path '/var/folders/nl/b7mbgsx16_g8zpdvhg37hm0h0000gn/T/Unnamed archive_2017-11-17_13-50-17.671.xcdistributionlogs'.
    12:50:17 error: exportArchive: exportOptionsPlist error for key 'method': expected one of {}, but found enterprise
    12:50:17 
    12:50:17 Error Domain=IDEFoundationErrorDomain Code=1 "exportOptionsPlist error for key 'method': expected one of {}, but found enterprise" UserInfo={NSLocalizedDescription=exportOptionsPlist error for key 'method': expected one of {}, but found enterprise}
    12:50:17 
    

    with enterprise-options.plist

    <?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>method</key>
    	<string>enterprise</string>
    	<key>teamID</key>
    	<string>OUR_ID</string>
    	<key>provisioningProfiles</key>
    	<dict>
    		<key>com.example.fluttertest</key>
    		<string>comExample Enterprise Wildcard Distribution</string>
    	</dict>
    </dict>
    </plist>
    
  5. xster commented on Nov 17, 2017

    @xster
    Member
  6. mit-mit commented on Jan 8, 2018

    @mit-mit
    Member

    @cbracken can you elaborate?

  7. cbracken commented on Jan 8, 2018

    @cbracken
    Member

    Thanks for filing this issue!

    Our currently supported iOS releasing process is described in Releasing for iOS and as noted, makes use of the Xcode UI. We don’t yet support a pure command-line mechanism for releasing to the App Store, and it’s not something we currently have prioritised but I’d certainly be more than happy to review pull requests.

  8. oemera commented on Jan 10, 2018

    @oemera

    @cbracken thanks for your response. The error also happens when archiving within the Xcode UI. Please look into my issue: #13070. Based on the reactions I guess there are a couple of others who have this issue and can't release their app with the new version of Xcode.

    If you have any questions please let me know.

  9. cbracken commented on Jan 10, 2018

    @cbracken
    Member

    Thanks for pointing to #13070, I'll take a look at that today.

  10. alibitek commented on Jan 10, 2018

    @alibitek
    Contributor

    xcodebuild: Deploy iOS app from Command Line
    A really good summary of xcodebuild command line capabilities.
    It even includes an example of how you can submit the .ipa to iTunes Connect from the command line.

  11. peace2knowledge commented on Jan 13, 2018

    @peace2knowledge

    change to project ios directory,excute following command:

    xcodebuild -workspace Runner.xcworkspace -scheme Runner -sdk iphoneos -configuration Release archive -archivePath $PWD/build/Runner.xcarchive
    xcodebuild -exportArchive -archivePath $PWD/build/Runner.xcarchive -exportOptionsPlist exportOptions.plist -exportPath $PWD/build/Runner.ipa

    exportOptions.plist is on ios directory.
    file content 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>enterprise</string>
        <key>provisioningProfiles</key>
        <dict>
            <key>com.company.appname</key>
            <string>provisioningProfiles name </string>
        </dict>
        <key>signingCertificate</key>
        <string>iOS Distribution</string>
        <key>signingStyle</key>
        <string>manual</string>
        <key>stripSwiftSymbols</key>
        <true/>
        <key>teamID</key>
        <string>xxxxxx</string>
        <key>thinning</key>
        <string>&lt;none&gt;</string>
    </dict>
    </plist>

    @oemera

  12. xster commented on Jan 27, 2018

    @xster
    Member

    This is theoretically possible. I got it to work using Fastlane (which really just invokes xcodebuild archive).

    We can document the flow more or possibly integrate Fastlane into flutter tools, though there are no immediate plans yet.

    In the meantime, you can flutter build ios --release --no-codesign first and then use build_ios_app(export_method: "app-store", ...) in Fastlane with whichever signing method you prefer.

  13. csga5000 commented on May 22, 2018

    @csga5000

    +1 on this. I think building iPa's would be great. During beta phase of apps I sometimes have to release new versions every couple days, and it takes forever when I have to test the app by running it on a device, then do flutter build --release, and then open xcode, and do product archive, and then in organizer upload to app store, and finally wait for apple to process my app.

    I think this could be streamlined to just: flutter build ipa --release and then open application loader and deliver my app, (and then still wait for apple to process the app). It's still a bit slow, but at least I don't have to wait forever for flutter to build my app so I can wait another forever for xcode to archive my app. Admittedly it may be so slow partially cause my mac (not my main machine) is a mac mini and runs like a slug.

    If you're not aware of application loader, you can open it through xcode XCode > Open Developer Tool > Application Loader, but you can also pin it to your task bar to open it without opening xcode (or install it separately, though that generally is very out of date).

  14. fuzzybinary commented on May 29, 2018

    @fuzzybinary
    Contributor

    I would also appreciate this since we want to build ipas for distrubution through CI.

    One (fairly crazy) issue I'm having with the current build system is that changing between flutter build ios --debug and flutter build ios --release actually modifies the Podfile.lock, and requires a fresh pod install, which is overriding a change I need to make in one of our Pods to avoid grpc/grpc#7406

    Also because of this, we have to run flutter build ios --release followed by xcodebuild archive followed by xcodebuild exportArchive to build an ipa. This causes the app to be built twice (kind of a waste of time).

    It seams like a lot of the build system could use refactoring. In general:

    • You should be able to generate ipas for a given flavor from the command line
    • flavors should be supported more directly from flutter cli (see buggy/messy deploy on iOS with multiple schemas/target #14648)
    • switching flavors shouldn't modify the Podfile.lock. This may require modifying Debug/Release.xcconfig to not rely as much on the Generated.xcconfig (or at least removing the location of the Flutter SDK from Generated and putting it in Debug/Release.xcconfig

    I'm actually more than willing to help with this with some direction from the flutter team on what they think the best approach would be.

  15. 74 remaining items

  16. szotp commented on Sep 8, 2020

    @szotp

    Would it be possible to only run "fastlane gym" and add a build step to the project that does the "flutter --config-only" stuff?

    @xster Pe-te was asking if it was possible to automate flutter build ios --config-only as a build step inside xcodeproj, so that the only thing needed is fastlane gym. But that's not possible because it would mean changing xcodeproj while you are building it.

  17. xster commented on Sep 9, 2020

    @xster
    Member

    Ah I misunderstood. You mean rather than in your CI script or in your Fastfile, whether you can recursively invoke flutter build ios --config-only inside Xcode itself with a build phase?

    (Not tested) I think that works if you invoked it early enough before the build Flutter phase or the compile sources phase but doesn't that defeat the point? In other words, the whole point is to tell Xcode what configuration to build and archive etc. If Xcode already knows, then it could just hardcode those values from Generated.xcconfig (which is more or less all flutter build ios --config-only does) in your .xcodeproj directly.

  18. Pe-te commented on Sep 10, 2020

    @Pe-te

    Thanks for all the clarifications, just as an addition why I asked:

    Right now I have in my buildscript:

    fastlane init_keychain
    flutter build (soon --config-only)
    fastlane build_my_app
    fastlane close_keychain

    So it would be nice to reduce it to "fastlane build_my_app" and do all the other stuff inside the Fastfile to have the fastlane error handling for everything. I know, I could call flutter through a fastlane sh() call, but that feels weird. 😉

    So the idea was to pack the --config-only also into the build phases, but I am not sure what it does exactly and how it affects the build process if you change stuff while it runs.

  19. jmagman commented on Sep 25, 2020

    @jmagman
    Member

    Can we track the --config-only flag in a different feature request issue? I only just saw this, and have a few concerns, but I don't want to further muddy this feature request.

    As for flutter build ipa and why it isn't just done already:
    There are so many options when you export an archive that would have to be exposed in that command just to pipe 1:1 into xcodebuild/exportOptionsPlist. You pretty much need an entire UI wizard flow in the CLA to make it manageable, which Xcode already has (and keeps updated with new App Store requirements). So either we build an identical wizard flow, or we expose all the below flags, and if you can successfully use them, then congrats! you are an Xcode guru and are probably already using xcodebuild directly.

    xcodebuild -exportArchive -archivePath <xcarchivepath> [-exportPath <destinationpath>] -exportOptionsPlist <plistpath>
    
    Available keys for -exportOptionsPlist:
    
    	compileBitcode : Bool
    
    		For non-App Store exports, should Xcode re-compile the app from bitcode? Defaults to YES.
    
    	destination : String
    
    		Determines whether the app is exported locally or uploaded to Apple. Options are export or upload. The available options vary based on the selected distribution method. Defaults to export.
    
    	distributionBundleIdentifier : String
    
    		Reformat archive to focus on eligible target bundle identifier.
    
    	embedOnDemandResourcesAssetPacksInBundle : Bool
    
    		For non-App Store exports, if the app uses On Demand Resources and this is YES, asset packs are embedded in the app bundle so that the app can be tested without a server to host asset packs. Defaults to YES unless onDemandResourcesAssetPacksBaseURL is specified.
    
    	generateAppStoreInformation : Bool
    
    		For App Store exports, should Xcode generate App Store Information for uploading with iTMSTransporter? Defaults to NO.
    
    	iCloudContainerEnvironment : String
    
    		If the app is using CloudKit, this configures the "com.apple.developer.icloud-container-environment" entitlement. Available options vary depending on the type of provisioning profile used, but may include: Development and Production.
    
    	installerSigningCertificate : String
    
    		For manual signing only. Provide a certificate name, SHA-1 hash, or automatic selector to use for signing. Automatic selectors allow Xcode to pick the newest installed certificate of a particular type. The available automatic selectors are "Mac Installer Distribution" and "Developer ID Installer". Defaults to an automatic certificate selector matching the current distribution method.
    
    	manifest : Dictionary
    
    		For non-App Store exports, users can download your app over the web by opening your distribution manifest file in a web browser. To generate a distribution manifest, the value of this key should be a dictionary with three sub-keys: appURL, displayImageURL, fullSizeImageURL. The additional sub-key assetPackManifestURL is required when using on-demand resources.
    
    	method : String
    
    		Describes how Xcode should export the archive. Available options: app-store, validation, ad-hoc, package, enterprise, development, developer-id, and mac-application. The list of options varies based on the type of archive. Defaults to development.
    
    	onDemandResourcesAssetPacksBaseURL : String
    
    		For non-App Store exports, if the app uses On Demand Resources and embedOnDemandResourcesAssetPacksInBundle isn't YES, this should be a base URL specifying where asset packs are going to be hosted. This configures the app to download asset packs from the specified URL.
    
    	provisioningProfiles : Dictionary
    
    		For manual signing only. Specify the provisioning profile to use for each executable in your app. Keys in this dictionary are the bundle identifiers of executables; values are the provisioning profile name or UUID to use.
    
    	signingCertificate : String
    
    		For manual signing only. Provide a certificate name, SHA-1 hash, or automatic selector to use for signing. Automatic selectors allow Xcode to pick the newest installed certificate of a particular type. The available automatic selectors are "Mac App Distribution", "iOS Developer", "iOS Distribution", "Developer ID Application", "Apple Distribution", "Mac Developer", and "Apple Development". Defaults to an automatic certificate selector matching the current distribution method.
    
    	signingStyle : String
    
    		The signing style to use when re-signing the app for distribution. Options are manual or automatic. Apps that were automatically signed when archived can be signed manually or automatically during distribution, and default to automatic. Apps that were manually signed when archived must be manually signed during distribtion, so the value of signingStyle is ignored.
    
    	stripSwiftSymbols : Bool
    
    		Should symbols be stripped from Swift libraries in your IPA? Defaults to YES.
    
    	teamID : String
    
    		The Developer Portal team to use for this export. Defaults to the team used to build the archive.
    
    	thinning : String
    
    		For non-App Store exports, should Xcode thin the package for one or more device variants? Available options: <none> (Xcode produces a non-thinned universal app), <thin-for-all-variants> (Xcode produces a universal app and all available thinned variants), or a model identifier for a specific device (e.g. "iPhone7,1"). Defaults to <none>.
    
    	uploadBitcode : Bool
    
    		For App Store exports, should the package include bitcode? Defaults to YES.
    
    	uploadSymbols : Bool
    
    		For App Store exports, should the package include symbols? Defaults to YES.
    

    And that will just export the archive, it doesn't run any validators.

  20. jmagman commented on Sep 25, 2020

    @jmagman
    Member

    Can we track the --config-only flag in a different feature request issue? I only just saw this, and have a few concerns, but I don't want to further muddy this feature request.

    Never mind, it was already merged :-(

  21. jmagman commented on Sep 25, 2020

    @jmagman
    Member

    The value add from flutter tooling would be the creation of the xcarchive--that's what is going to use all the build settings, compiling dart/embedding frameworks/thinning logic. So a flutter build xcarchive command.

    The last step of making the ipa is entirely specific to the developer and what they are using the ipa for, and Flutter can't and shouldn't assume any of the exportOptionsPlist values. So the developer is already signed up for reading some Apple docs to get the right values, and at that point the value of running

    xcodebuild -exportArchive -archivePath <xcarchivepath> [-exportPath <destinationpath>] -exportOptionsPlist <plistpath>
    

    vs

    flutter build ipa -exportOptionsPlist <plistpath>
    

    is not that valuable (though we could add that wrapper, it's just not the hard or valuable part).

  22. jmagman commented on Sep 25, 2020

    @jmagman
    Member

    Created #66619 to discuss there.

  23. MisterJimson commented on Sep 25, 2020

    @MisterJimson

    @jmagman I see your point but instead of mapping all of the exportOptionsPlist options we could just take a path to that file. Similar to how your keystore needs to exist on disk and how you have to manually setup your build.gradle file before you want to release for Android. There can be a happy medium for flutter build ipa.

  24. jmagman commented on Oct 9, 2020

    @jmagman
    Member
  25. jmagman commented on Oct 22, 2020

    @jmagman
    Member

    Command has been renamed flutter build ipa (alias flutter build xcarchive still works) and takes an optional --export-options-plist flag to make an IPA from the archive bundle. See flutter build ipa -h on the master channel for details.
    Website documentation forthcoming at flutter/website#4852.

  26. github-actions commented on Aug 10, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  27. locked as resolved and limited conversation to collaborators on Aug 10, 2021
  28. jmagman commented on Jan 25, 2022

    @jmagman
    Member

    If you're still interested in building for distribution from the command line...

    flutter build ipa has two stages for iOS distribution:

    1. Archive the app into an xcarchive bundle.
    2. Optionally, export the xcarchive into an ipa bundle for distribution to the App Store, or to a device, or enterprise distribution...

    Currently to get to number 2 and create the ipa file, users need to pass in a --export-options-plist file, which they need to create themselves, or know how to yank off a previously-build IPA. Flutter's iOS distribution docs don't say what needs to go into the plist, it just points to Apple docs, or tells them to launch Xcode and create the IPA there.

    1. Run flutter build ipa to produce a build archive.

    Note: When you export your app at the end of Distribute App, Xcode will create a directory containing an IPA of your app and an ExportOptions.plist file. You can create new IPAs with the same options without launching Xcode by running flutter build ipa --export-options-plist=path/to/ExportOptions.plist. See xcodebuild -h for details about the keys in this property list.

    1. Open build/ios/archive/MyApp.xcarchive in Xcode.

    I filed #97179 to track not requiring --export-options-plist for the most common app-store and ad-hoc methods via flutter build ipa flags. Please comment in that issue if you have any feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilitycustomer: crowdAffects or could affect many people, though not necessarily a specific customer.platform-iosiOS applications specificallyt: xcode"xcodebuild" on iOS and general Xcode project managementtoolAffects the "flutter" command-line tool. See also t: labels.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions