greenrobot / greenDAO

greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases.
http://greenrobot.org/greendao/
12.63k stars 2.89k forks source link

A bug on greendao-gradle-plugin when parallel execution task :app:greendao #914

Open zhenian opened 6 years ago

zhenian commented 6 years ago

Background

In a gradle project, there are two apps which use greenDAO. Define in settings.gradle:

include ':app'
include ':app2'
... 

in :app and :app2, there are some same classes defined at package com.xxx.model which mark with @org.greenrobot.greendao.annotation.Entity. Same name, same fields.

Issue

when I build or clean with commands:

It is ok.

but, when I make Clean Project with Android Studio, there is a error.

gradle task seqs:

Executing tasks: [clean, :app:generateDebugSources, :appbase:generateDebugSources, :app1:generateDebugSources]

Parallel execution with configuration on demand is an incubating feature.
:clean UP-TO-DATE
:appbase:clean
:app1:clean
:fixmapping:clean UP-TO-DATE
:app:clean
:app1:checkDebugClasspath
:appbase:preBuild UP-TO-DATE
:appbase:preDebugBuild UP-TO-DATE
:appbase:checkDebugManifest
:appbase:processDebugManifest FROM-CACHE
:appbase:compileDebugAidl NO-SOURCE
:appbase:packageDebugRenderscript NO-SOURCE
:appbase:compileDebugRenderscript
:app:checkDebugClasspath
:appbase:compileDebugRenderscript FROM-CACHE
:appbase:generateDebugResValues FROM-CACHE
:appbase:generateDebugResources UP-TO-DATE
:appbase:packageDebugResources FROM-CACHE
:appbase:generateDebugRFile FROM-CACHE
:appbase:generateDebugBuildConfig FROM-CACHE
:appbase:prepareLintJar UP-TO-DATE
:appbase:generateDebugSources UP-TO-DATE
:app:checkDebugClasspath FROM-CACHE
:app:preBuild UP-TO-DATE
:app:preDebugBuild
:app1:checkDebugClasspath FROM-CACHE
:app1:preBuild UP-TO-DATE
:app1:preDebugBuild FROM-CACHE
:app1:compileDebugAidl
:app:preDebugBuild FROM-CACHE
:app:compileDebugAidl
:app1:compileDebugAidl FROM-CACHE
:app1:compileDebugRenderscript
:app:compileDebugAidl FROM-CACHE
:app:compileDebugRenderscript
:app1:compileDebugRenderscript FROM-CACHE
:app1:checkDebugManifest
:app1:generateDebugBuildConfig
:app:compileDebugRenderscript FROM-CACHE
:app:checkDebugManifest
:app1:generateDebugBuildConfig FROM-CACHE
:app1:greendaoPrepare
:app:generateDebugBuildConfig FROM-CACHE
:app:greendaoPrepare
:app1:greendao
:app:greendao
:app1:greendao FAILED
:app:greendao FAILED

error message:


FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app1:greendao'.
> Constructor (see LocalVolume:20) has been changed after generation.
  Please either mark it with @Keep annotation instead of @Generated to keep it untouched,
  or use @Generated (without hash) to allow to replace it.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:greendao'.
> Constructor (see ComicChapPicTask:21) has been changed after generation.
  Please either mark it with @Keep annotation instead of @Generated to keep it untouched,
  or use @Generated (without hash) to allow to replace it.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================

* Get more help at https://help.gradle.org

BUILD FAILED in 4s
zhenian commented 6 years ago

@greenrobot-team

I want to fix this bug. But Where is the Gradle plugin source code? from #412

greenrobot-team commented 5 years ago

As the error message indicates, your constructors have changed in between runs.

Have a look at the docs on how to resolve this: http://greenrobot.org/greendao/documentation/modelling-entities/#Modifying_generated_code

Closing. Please re-open if you can verify (example code) that this is indeed an issue with the plugin. -ut

zhenian commented 5 years ago

3df0120ea2a415b3ad0c21f69f93f35e

@greenrobot-team

I make a litter demo for this bug: [ReplayBug4GreenDAOPlugin]

(https://github.com/zhenian/ReplayBug4GreenDAOPlugin) https://github.com/zhenian/ReplayBug4GreenDAOPlugin

replay step:

  1. clone the repo and open in Android studio.
  2. execute Rebuild project . first, it is ok.
  3. execute Rebuild project again. replay this bug.

image

blindpirate commented 5 years ago

We (Gradle core team) also found this issue. Seems like when two subprojects both apply greendao plugin and enable --parallel (which may execute tasks in order :subproject1:greendaoPrepare -> :subproject2:greendaoPrepare->:subproject1:greendao->:subproject2:greendao or simultaneously), this issue will occur on second execution.

Thanks @zhenian for the reproducible sample. One workaround I found is "simulating" serailization execution:

diff --git a/app/build.gradle b/app/build.gradle
index d5f1684..3055caf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,3 @@
-apply plugin: 'com.android.application'
-apply plugin: 'org.greenrobot.greendao'

 android {
     compileSdkVersion 28
diff --git a/app2/build.gradle b/app2/build.gradle
index ade9fe9..1d91245 100644
--- a/app2/build.gradle
+++ b/app2/build.gradle
@@ -1,5 +1,4 @@
-apply plugin: 'com.android.application'
-apply plugin: 'org.greenrobot.greendao'
+

 android {
     compileSdkVersion 28
diff --git a/build.gradle b/build.gradle
index 79ddbab..859ec75 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.

 buildscript {
-    
+
     repositories {
         maven { url "http://maven.aliyun.com/nexus/content/groups/public" }
         google()
@@ -17,6 +17,24 @@ buildscript {
     }
 }

+def greendaoTasks = []
+
+subprojects { subproject ->
+    apply plugin: 'com.android.application'
+    apply plugin: 'org.greenrobot.greendao'
+    afterEvaluate {
+        greendaoTasks.add(subproject.tasks.findByName('greendaoPrepare'))
+        greendaoTasks.add(subproject.tasks.findByName('greendao'))
+
+        if (greendaoTasks.size() == 4) {
+            println(greendaoTasks)
+            for (int i = 1; i < 4; ++i) {
+                greendaoTasks[i].mustRunAfter(greendaoTasks[i - 1])
+            }
+        }
+    }
+}
+
 allprojects {
     repositories {
         maven { url "http://maven.aliyun.com/nexus/content/groups/public" }

My speculation is greendao plugin lacks proper synchronization between different subproject. I'd like to see the plugin source code very much.

blindpirate commented 5 years ago

@zhenian can you please reopen this issue?

zhenian commented 5 years ago

@greenrobot-team had closed this issue so I have no right to reopen it.

@greenrobot-team , can you recheck this issue?

Add a new issue and reference to this issue

blindpirate commented 5 years ago

Well, AFAIK the author can reopen it, unless this issue is locked. Maybe I'm wrong.

greenrobot-team commented 5 years ago

I thought so too, sorry, reopening.

However, can not reproduce using the given example project updated to Gradle 4.10.2.

@zhenian As @blindpirate suggested this may be due to Gradle parallel mode. Do you have org.gradle.parallel=true set in your global gradle.properties file?

I see it commented out in the projects gradle.properties file. If I uncomment I can reproduce the above error.

Maybe try to explicitly disable parallel mode by adding org.gradle.parallel=false to your projects gradle.properties.

edit: You mention parallel execution in the title, so that must be it. -ut

blindpirate commented 5 years ago

I can reproduce with the given sample by running ./gradlew assemble --parallel twice. I think @zhenian might forget to enable org.gradle.parallel=true in the sample project.

BTW, org.gradle.parallel=false is default value, you don't have to set it explicitly.

autonomousapps commented 5 years ago

We don't generally want to recommend disabling parallel mode because it can really slow down a build. After all, my machine alone has 8 cores. Do I want 7 of them doing nothing during a build?

autonomousapps commented 5 years ago

Putting the following into the root build.gradle (and with parallel=true) fixes the sample project:

def greenDaoTasks = []
subprojects { subproject ->
    apply plugin: 'org.greenrobot.greendao'
    afterEvaluate {
        greenDaoTasks.add(subproject.tasks.findByName('greendaoPrepare'))
        greenDaoTasks.add(subproject.tasks.findByName('greendao'))

        if (greenDaoTasks.size() > 2) {
            println greenDaoTasks
            for (int i = 1; i < greenDaoTasks.size(); i++) {
                greenDaoTasks[i].mustRunAfter(greenDaoTasks[i - 1])
            }
        }
    }
}

You can now run ./gradlew assembleDebug && ./gradlew assembleDebug and the build does not fail. It's ugly as hell, though.

zhenian commented 5 years ago

Is there a plan to fix this bug?

if no, is there a plan to release Gradle plugin Source codes? #412

NightXlt commented 1 year ago

Is there a plan to fix this bug?

if no, is there a plan to release Gradle plugin Source codes?