Skip to content

[Proposal] Avoid profile build dependencies in configureCMakeDebug; introduce configureCMakeProfile for profile mode #166744

Closed

Description

@middagj

We have a custom job per build mode attached to the the preDebugBuild, preProfileBuild and preReleaseBuild for the corresponding build modes. Since our upgrade from 3.27 to 3.29 we suddenly see that a flutter run for a debug build triggers the custom job both for the debug and profile build. After some debugging I found that configureCMakeDebug has a dependency on preProfileBuild which it doesn't had before. I bisected the code and found that #159756 introduced this behaviour. (#160205 fixes it and #160260 reintroduces it again). If the forceNdkDownload call is commented out the issue disappears.

I don't know if this is a Flutter specific issue, could also be Android.

Reproduce:

flutter create my_app
cd my_app/android
./gradlew --dry-run configureCMakeDebug

Activity

  1. maheshj01 commented on Apr 9, 2025

    @maheshj01
    Member

    @middagj thanks for filing the issue, Could you please clarify what the expected output should be when running

    ./gradlew --dry-run configureCMakeDebug

    This is what I see

    mahesh@MacBook-Pro-10 android % ./gradlew --dry-run configureCMakeDebug
    Starting a Gradle Daemon (subsequent builds will be faster)
    :app:compileFlutterBuildProfile SKIPPED
    :app:packJniLibsflutterBuildProfile SKIPPED
    :app:preBuild SKIPPED
    :app:preProfileBuild SKIPPED
    :app:configureCMakeDebug[arm64-v8a] SKIPPED
    :app:configureCMakeDebug[armeabi-v7a] SKIPPED
    :app:configureCMakeDebug[x86] SKIPPED
    :app:configureCMakeDebug[x86_64] SKIPPED
    :app:configureCMakeDebug SKIPPED
    
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
    
    You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
    
    For more on this, please refer to https://docs.gradle.org/8.10.2/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
    
    BUILD SUCCESSFUL in 13s
    6 actionable tasks: 1 executed, 5 up-to-date
    mahesh@MacBook-Pro-10 android % 
    
    flutter doctor -v

    stable

    [✓] Flutter (Channel stable, 3.29.2, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [822ms]
        • Flutter version 3.29.2 on channel stable at /Users/mahesh/Development/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision c236373904 (2 weeks ago), 2025-03-13 16:17:06 -0400
        • Engine revision 18b71d647a
        • Dart version 3.7.2
        • DevTools version 2.42.3
    [✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.2s]
        • Android SDK at /Users/mahesh/Library/Android/sdk
        • Platform android-35, build-tools 35.0.0
        • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 16.0) [3.1s]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 16A242d
        • CocoaPods version 1.16.2
    
    [✓] Chrome - develop for the web [136ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2024.3) [135ms]
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    
    [✓] IntelliJ IDEA Community Edition (version 2021.2.1) [134ms]
        • IntelliJ at /Applications/IntelliJ IDEA CE.app
        • Flutter plugin version 61.2.4
        • Dart plugin version 212.5080.8
    
    [✓] VS Code (version 1.96.2) [18ms]
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.102.0
    
    [✓] Connected device (4 available) [6.7s]
        • iPad Pro 11-inch (M4) (mobile)  • A97192B5-5CFD-4164-BF2A-A6E2972614FF • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-0
          (simulator)
        • macOS (desktop)                 • macos                                • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
        • Mac Designed for iPad (desktop) • mac-designed-for-ipad                • darwin         • macOS 15.1.1 24B2091 darwin-arm64
        • Chrome (web)                    • chrome                               • web-javascript • Google Chrome 131.0.6778.265
    
    [✓] Network resources [294ms]
        • All expected network resources are available.
    
    ! Doctor found issues in 1 category.
  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 9, 2025
  3. middagj commented on Apr 9, 2025

    @middagj
    Author

    @maheshj01 thanks for the quick reply. I did some more digging. If you use the taskTree plugin, this is what you get

    ./gradlew configureCMakeDebug taskTree
    
    > Task :app:taskTree
    
    ------------------------------------------------------------
    Project ':app'
    ------------------------------------------------------------
    
    :app:configureCMakeDebug
    +--- :app:configureCMakeDebug[arm64-v8a]
    |    +--- :app:packJniLibsflutterBuildProfile
    |    |    \--- :app:compileFlutterBuildProfile
    |    \--- :app:preProfileBuild
    |         \--- :app:preBuild
    +--- :app:configureCMakeDebug[armeabi-v7a]
    |    +--- :app:packJniLibsflutterBuildProfile *
    |    \--- :app:preProfileBuild *
    +--- :app:configureCMakeDebug[x86]
    |    +--- :app:packJniLibsflutterBuildProfile *
    |    \--- :app:preProfileBuild *
    \--- :app:configureCMakeDebug[x86_64]
         +--- :app:packJniLibsflutterBuildProfile *
         \--- :app:preProfileBuild *
    

    compare this to an empty Android project with the same config to force NDK download added:

            gradleProject.android {
                externalNativeBuild {
                    cmake {
                        // Respect the existing configuration if it exists - the NDK will already be
                        // downloaded in this case.
                        path = flutterSdkRootPath + "/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt"
                    }
                }
    
                defaultConfig {
                    externalNativeBuild {
                        cmake {
                            // CMake will print warnings when you try to build an empty project.
                            // These arguments silence the warnings - our project is intentionally
                            // empty.
                            arguments("-Wno-dev", "--no-warn-unused-cli")
                        }
                    }
                }
            }

    then I get the following taskTree on configureCMakeDebug

    +--- :app:configureCMakeDebug[arm64-v8a]
    |    \--- :app:preDebugBuild
    |         \--- :app:preBuild
    +--- :app:configureCMakeDebug[armeabi-v7a]
    |    \--- :app:preDebugBuild *
    +--- :app:configureCMakeDebug[x86]
    |    \--- :app:preDebugBuild *
    \--- :app:configureCMakeDebug[x86_64]
         \--- :app:preDebugBuild *
    

    Next to the configureCMakeDebug there is a configureCMakeRelWithDebInfo which has a taskTree:

    :app:configureCMakeRelWithDebInfo
    +--- :app:configureCMakeRelWithDebInfo[arm64-v8a]
    |    \--- :app:preReleaseBuild
    |         \--- :app:preBuild
    +--- :app:configureCMakeRelWithDebInfo[armeabi-v7a]
    |    \--- :app:preReleaseBuild *
    +--- :app:configureCMakeRelWithDebInfo[x86]
    |    \--- :app:preReleaseBuild *
    \--- :app:configureCMakeRelWithDebInfo[x86_64]
         \--- :app:preReleaseBuild *
    

    So with Android there is a 1-1 mapping between configureCMakeDebug to preDebugBuild and configureCMakeRelWithDebInfo to preReleaseBuild.

    Flutter adds the profile build mode and somehow the preDebugBuild dependency gets swapped with preProfileBuild (and packJniLibsflutterBuildProfile likewise) . The swapping is erroneous I believe. My expectation is that this does not happen.

    Note that even if the swapping is fixed, the added profile build mode has no natural configureCMake task. This task is a dependency of mergeDebugNativeLibs. So if the configureCMakeDebug only depends on preDebugBuild, the same problem arises when mergeProfileNativeLibs is executed: then the preDebugBuild is called which shouldn't. A better fix would probably when the profile build mode is added to copy the configureCMakeDebug to configureCMakeProfile and only change the dependencies, leaving the original dependencies of configureCMakeDebug untouched and let mergeProfileNativeLibs depend on configureCMakeProfile.

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 9, 2025
  5. maheshj01 commented on Apr 9, 2025

    @maheshj01
    Member

    Thank you for the detailed clarification, I'm going to label this as a proposal for the same and for insights from the Android team for this behavior.

  6. changed the title [-]Gradle task configureCMakeDebug depends on preProfileBuild since 3.29[/-] [+][Proposal] Avoid profile build dependencies in configureCMakeDebug; introduce configureCMakeProfile for profile mode[/+] on Apr 9, 2025
  7. added
    platform-androidAndroid applications specifically
    toolAffects the "flutter" command-line tool. See also t: labels.
    t: gradle"flutter build" and "flutter run" on Android
    c: proposalA detailed proposal for a change to Flutter
    team-androidOwned by Android platform team
    and removed
    in triagePresently being triaged by the triage team
    on Apr 9, 2025
  8. gmackall commented on Apr 15, 2025

    @gmackall
    Member

    Interesting, thanks for the detailed report.

    Recreating as you did with a blank Android project and using the taskTree plugin I see the same:

    mackall-macbookpro:blankandroid mackall$ ./gradlew configureCMakeDebug taskTree
    
    > Task :taskTree
    
    ------------------------------------------------------------
    Root project 'My Application'
    ------------------------------------------------------------
    
    
    (*) - subtree omitted (printed previously)
    Add --repeat to allow printing a subtree of the same task more than once.
    
    To see task dependency tree for a specific task, run gradlew <project-path>:<task> <project-path>:taskTree [--depth <depth>] [--with-inputs] [--with-outputs] [--with-description] [--repeat]
    Executions of all tasks except for taskTree are skipped. They are used for building the task graph only.
    
    > Task :app:taskTree
    
    ------------------------------------------------------------
    Project ':app'
    ------------------------------------------------------------
    
    :app:configureCMakeDebug
    +--- :app:configureCMakeDebug[arm64-v8a]
    |    \--- :app:preDebugBuild
    |         \--- :app:preBuild
    +--- :app:configureCMakeDebug[armeabi-v7a]
    |    \--- :app:preDebugBuild *
    +--- :app:configureCMakeDebug[x86]
    |    \--- :app:preDebugBuild *
    \--- :app:configureCMakeDebug[x86_64]
         \--- :app:preDebugBuild *
    

    But if I add a profile build type to the Android project in the same way Flutter does:

    ... 
    buildTypes {
            create("profile") {
                initWith(getByName("debug"))
            }
    ... // rest of buildTypes content
    

    I see the same behavior we are getting in Flutter:

    mackall-macbookpro:blankandroid mackall$ ./gradlew configureCMakeDebug taskTree
    
    ...
    
    :app:configureCMakeDebug
    +--- :app:configureCMakeDebug[arm64-v8a]
    |    \--- :app:preProfileBuild
    |         \--- :app:preBuild
    +--- :app:configureCMakeDebug[armeabi-v7a]
    |    \--- :app:preProfileBuild *
    +--- :app:configureCMakeDebug[x86]
    |    \--- :app:preProfileBuild *
    \--- :app:configureCMakeDebug[x86_64]
         \--- :app:preProfileBuild *
    

    Perhaps this is a bug in how the task names are created in the Android Gradle plugin? Or in how we are creating the build type? Need to dig into this further

  9. gmackall commented on Apr 15, 2025

    @gmackall
    Member

    I did a bit of inspection in to how AGP makes this name and
    #167240
    fixes the problem, I believe.

    Looks like for our case they get the name from the cmake args, so this passes in the build type name for the (android) BuildType to the cmake args, and also moves the forcing from before to after the creation of the profile build type.

  10. github-actions commented on Apr 30, 2025

    @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.

  11. locked as resolved and limited conversation to collaborators on Apr 30, 2025
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

    c: proposalA detailed proposal for a change to Flutterplatform-androidAndroid applications specificallyt: gradle"flutter build" and "flutter run" on Androidteam-androidOwned by Android platform teamtoolAffects 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