Fixed
Status Update
Comments
mi...@gmail.com <mi...@gmail.com> #2
This doesn't repro for me. Steps:
(1) Create new C++ project
(2) Run the app (this create's the binary directories
(3) Do something to cause a gradle Sync
(4) Look for files under .externalNativeBuild. They're there:
jomof@jomof:~/projects/client/src/android/MyApplication4/app$ find "." -name "*.o"
./.externalNativeBuild/cmake/debug/x86/CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
Please add repro steps so I can get a better idea of what's happening.
>> It should only delete the CMake binary directories *if and only if* parameters change in Gradle that cause cmake toolchain parameters to change (such as platform version, abi, toolchain) or parameters passed to CMake to change.
This is the way it's design to work and it is working that way for the cases I know
(1) Create new C++ project
(2) Run the app (this create's the binary directories
(3) Do something to cause a gradle Sync
(4) Look for files under .externalNativeBuild. They're there:
jomof@jomof:~/projects/client/src/android/MyApplication4/app$ find "." -name "*.o"
./.externalNativeBuild/cmake/debug/x86/CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
Please add repro steps so I can get a better idea of what's happening.
>> It should only delete the CMake binary directories *if and only if* parameters change in Gradle that cause cmake toolchain parameters to change (such as platform version, abi, toolchain) or parameters passed to CMake to change.
This is the way it's design to work and it is working that way for the cases I know
ch...@google.com <ch...@google.com> #3
I realized that there were a few things we were doing that were questionable. Specifically, we set up our CMake command line params in a variable at the root build.gradle script. We were generating build dates and such in gradle and passing those down to CMake. I think things like this may be causing the CMake args to change too often, possibly resulting in this behavior. I'm in the process of eliminating a lot of this, so I'll make sure to report back the results.
mn...@gmail.com <mn...@gmail.com> #4
So even after making my changes, I still see this behavior. My repro steps:
1. Make a change to a CMake script
2. Switch to Android Studio. I am prompted to do gradle sync, and so I do it.
On next build, a full rebuild is performed. For some reason it is not performing a delta build. Some libraries are rebuilding that should not be rebuilt. So obviously a "ninja clean" is happening somewhere. There's simply no other explanation for this.
Jomo, can you please reopen? This is still a very real problem.
1. Make a change to a CMake script
2. Switch to Android Studio. I am prompted to do gradle sync, and so I do it.
On next build, a full rebuild is performed. For some reason it is not performing a delta build. Some libraries are rebuilding that should not be rebuilt. So obviously a "ninja clean" is happening somewhere. There's simply no other explanation for this.
Jomo, can you please reopen? This is still a very real problem.
ch...@google.com <ch...@google.com> #5
Hey Robert,
From what you wrote I think this is intended behavior. If you change the CMake script then the CMake-generated Ninja project must be regenerated. Since there's a new Ninja project there needs to be a full build. There's no concept of delta build that survives changes to build command files (CMakeLists.txt or ninja build files) because any behavior difference is possible.
From what you wrote I think this is intended behavior. If you change the CMake script then the CMake-generated Ninja project must be regenerated. Since there's a new Ninja project there needs to be a full build. There's no concept of delta build that survives changes to build command files (CMakeLists.txt or ninja build files) because any behavior difference is possible.
mn...@gmail.com <mn...@gmail.com> #6
Most of the time, a CMakeLists.txt is modified to add, remove, or rename source files. CMake uses this list of source files as a way to know if it should regenerate to update its ninja scripts to build the new files, if new files were added.
If you do a traditional CMake build from the command line, CMake will regenerate but it will not clean your previously compiled translation units (the object files). Those remain in-place. This allows you to perform another build (e.g. execute "ninja" command) and the build tool and compiler working together will be smart enough to know which files need to be rebuilt.
From this standpoint, I disagree with your assertions. There's no functional reason AFAIC to "clean" build every time a CMake script changes. If command line parameters to CMake change in such a way that it would completely invalidate previously compiled translation units outside of the knowledge of ninja and the toolchain programs, such as changing the Android ABI via toolchain arguments, then yes you would need to clean everything and rebuild. However, beyond that, you should be relying on ninja and the compiler to perform delta builds on previously compiled translation units.
As you have it now, I am unable to do a simple task like add new CPP files without having to rebuild my entire project. This wastes about 15-20 minutes of my time (that's how long a full rebuild takes), versus less than 60 seconds to just build the new file.
I think you should aim for smarter introspection into how this mechanism works. I see two very simple scenarios:
1) A build & sync was triggered due to parameter changes from gradle (those that affect the externalNativeBuild configuration, such as native ABI changes and custom user arguments)
2) A build was triggered because CMake.exe told you that a regeneration was needed since it detected a CMakeLists.txt changed
#1 should perform a clean & rebuild
#2 should not require any special action from you; you should simply run "ninja" command as if the scripts hadn't changed at all, and let Ninja run CMake to regenerate as needed
I feel like #2 is being treated as #1 right now. Also I noticed that Android Studio wants to re-sync Gradle when a CMakeLists.txt file changed. I do not think Android Studio should be "watching" CMake scripts. It should only resync if gradle scripts changed. If a CMake script changes, let your "ninja" command handle it.
As a final note, I realize I'm probably oversimplifying this a little. I'm sure there's reasons and edge cases as to why you need that level of control over CMake. However, at some point the full clean build has to be triggered in a smarter way to avoid these giant productivity problems. You obviously know much more about how CMake integrates with Android Studio than I do; I can only offer feedback based on my direct usage of CMake outside of AS. However, I hope my feedback makes sense and is agreeable.
If you do a traditional CMake build from the command line, CMake will regenerate but it will not clean your previously compiled translation units (the object files). Those remain in-place. This allows you to perform another build (e.g. execute "ninja" command) and the build tool and compiler working together will be smart enough to know which files need to be rebuilt.
From this standpoint, I disagree with your assertions. There's no functional reason AFAIC to "clean" build every time a CMake script changes. If command line parameters to CMake change in such a way that it would completely invalidate previously compiled translation units outside of the knowledge of ninja and the toolchain programs, such as changing the Android ABI via toolchain arguments, then yes you would need to clean everything and rebuild. However, beyond that, you should be relying on ninja and the compiler to perform delta builds on previously compiled translation units.
As you have it now, I am unable to do a simple task like add new CPP files without having to rebuild my entire project. This wastes about 15-20 minutes of my time (that's how long a full rebuild takes), versus less than 60 seconds to just build the new file.
I think you should aim for smarter introspection into how this mechanism works. I see two very simple scenarios:
1) A build & sync was triggered due to parameter changes from gradle (those that affect the externalNativeBuild configuration, such as native ABI changes and custom user arguments)
2) A build was triggered because CMake.exe told you that a regeneration was needed since it detected a CMakeLists.txt changed
#1 should perform a clean & rebuild
#2 should not require any special action from you; you should simply run "ninja" command as if the scripts hadn't changed at all, and let Ninja run CMake to regenerate as needed
I feel like #2 is being treated as #1 right now. Also I noticed that Android Studio wants to re-sync Gradle when a CMakeLists.txt file changed. I do not think Android Studio should be "watching" CMake scripts. It should only resync if gradle scripts changed. If a CMake script changes, let your "ninja" command handle it.
As a final note, I realize I'm probably oversimplifying this a little. I'm sure there's reasons and edge cases as to why you need that level of control over CMake. However, at some point the full clean build has to be triggered in a smarter way to avoid these giant productivity problems. You obviously know much more about how CMake integrates with Android Studio than I do; I can only offer feedback based on my direct usage of CMake outside of AS. However, I hope my feedback makes sense and is agreeable.
jo...@nuzzel.com <jo...@nuzzel.com> #7
Just to clarify, in the logs this is the exact problem:
External native generate JSON x86Debug: - dependent build file missing or changed
External native generate JSON x86Debug: removing stale contents from 'E:\code\frontend\source\Applications\zPayService\TestTool\.externalNativeBuild\cmake\x86Debug\x86'
The "removing stale contents"... those contents aren't stale at all. A build could be executed that reuses those existing object files if all I did was modify the cmake script to add new files to compile.
External native generate JSON x86Debug: - dependent build file missing or changed
External native generate JSON x86Debug: removing stale contents from 'E:\code\frontend\source\Applications\zPayService\TestTool\.externalNativeBuild\cmake\x86Debug\x86'
The "removing stale contents"... those contents aren't stale at all. A build could be executed that reuses those existing object files if all I did was modify the cmake script to add new files to compile.
ch...@google.com <ch...@google.com>
mn...@gmail.com <mn...@gmail.com> #8
Also CMake will think CMake scripts changed if you swap between git branches:
1. Go from branch A to branch B
2. Go from branch B back to A
Cmake script is still physically the same, but because you swapped branches around, the timestamp of the Cmake script changed so this triggers a full rebuild.
At this point I'd say this is our biggest issue at Ziosk and the one causing the most productivity problems. Our team of about 15 engineers is constantly complaining. There's concern on how long Google will take to address these issues, some have proposed rolling back to Eclipse + ANT. If we're a year out from any improvements I may have to consider it.
1. Go from branch A to branch B
2. Go from branch B back to A
Cmake script is still physically the same, but because you swapped branches around, the timestamp of the Cmake script changed so this triggers a full rebuild.
At this point I'd say this is our biggest issue at Ziosk and the one causing the most productivity problems. Our team of about 15 engineers is constantly complaining. There's concern on how long Google will take to address these issues, some have proposed rolling back to Eclipse + ANT. If we're a year out from any improvements I may have to consider it.
ki...@google.com <ki...@google.com> #9
I'm prototyping a change to address this. There is a concern that CMake doesn't operate incrementally under certain circumstances. For example, changing the compiler. I think Refresh Linked C++ Projects should be enough to cover this case. I'm still looking for other cases that would be more concerning
al...@google.com <al...@google.com> #10
Another kind of change to CMakeLists.txt is affected. If a build target is removed then CMake won't delete the .so and related .o files. Gradle packages *.so rather than the explicit list of .so files because build systems sometimes copy extra .so files into the output folder to be packaged.
I think I can cover this case by specific removing only unrecognized .so files during sync.
I think I can cover this case by specific removing only unrecognized .so files during sync.
al...@google.com <al...@google.com> #11
To your example: Changing compiler means changing command line arguments (e.g. `-G Ninja`) or alternatively, changing environment such as C and CXX variables. In the latter case, normal CMake does not watch for changes to environment variables, so it's the responsibility of the user (or in your case, the IDE) to monitor changes to environment and control CMake accordingly.
However, this still falls into the pattern of behavior I've outlined previously. Indirect or direct changes to Gradle or Gradle scripts that result in a different command line invocation of CMake should result in a full clean (delete binary dir + regenerate using CMake). Changes to the CMake scripts themselves shouldn't be monitored by Android Studio at all. If you have weird cases where CMake is doing work the NDK toolchain should be doing, such as lots of system introspection and runtime changes to toolchain, I'd simply document that Google does not support that usage of CMake, and all changes should go through Gradle instead (or file a bug with the NDK team and have them fix the toolchain file).
However, this still falls into the pattern of behavior I've outlined previously. Indirect or direct changes to Gradle or Gradle scripts that result in a different command line invocation of CMake should result in a full clean (delete binary dir + regenerate using CMake). Changes to the CMake scripts themselves shouldn't be monitored by Android Studio at all. If you have weird cases where CMake is doing work the NDK toolchain should be doing, such as lots of system introspection and runtime changes to toolchain, I'd simply document that Google does not support that usage of CMake, and all changes should go through Gradle instead (or file a bug with the NDK team and have them fix the toolchain file).
ki...@google.com <ki...@google.com> #12
Concerning stale *.so files: What I did for my ANT integration custom targets in CMake was to delete all *.so files before running a build, that way when a build is finished, you're left with only *.so files that were copied to that destination by custom commands tied to real targets. So if a target was completely removed, its corresponding *.so file would not make it to the temporary/intermediate copy destination where you look for *.so files to package into the APK.
This solution is simple and doesn't require introspection into CMake targets. If you have more direct access to targets defined by CMake, you could keep track a list of targets found during configuration and query the OUTPUT property on each of them and correlate that to files you find in your CMake output directory. Not sure if this has much benefit over the idea above, though.
This solution is simple and doesn't require introspection into CMake targets. If you have more direct access to targets defined by CMake, you could keep track a list of targets found during configuration and query the OUTPUT property on each of them and correlate that to files you find in your CMake output directory. Not sure if this has much benefit over the idea above, though.
mn...@gmail.com <mn...@gmail.com> #13
I've submitted a fix for this. Unless we find a problem the fix will appear in the next 3.1 canary
ki...@google.com <ki...@google.com> #14
Could you explain the fix here so I (and others) can get a good understanding of how the behavior is changing as well as what the root cause (original behavior) was?
mn...@gmail.com <mn...@gmail.com> #15
supportLibs : '25.3.1'
ki...@google.com <ki...@google.com> #16
Is this happening under beta1 of 26.0.0 as well?
mn...@gmail.com <mn...@gmail.com> #17
I can verify in am.
ch...@google.com <ch...@google.com> #18
@Kirill: If this is touching text color then it's not resource flushing, that was specifically for drawables. Look at my last comment in the blocked by bug, that's the cause for this.
mn...@gmail.com <mn...@gmail.com> #19
Our issue was resolved on our end.
ch...@google.com <ch...@google.com>
ki...@google.com <ki...@google.com>
[Deleted User] <[Deleted User]> #20
da...@gmail.com <da...@gmail.com> #21
#20 as you say, that's not good. Using `Application` as `WebView` context has other side effects, like `WebView` is unable to show dialogs (input date) and you need to develop workarounds...
ch...@google.com <ch...@google.com> #22
Just to ping this bug. We're still looking into this and MAY have a solution: https://android-review.googlesource.com/c/platform/frameworks/support/+/878200
No guarantees on whether this will land, since there's a lot of tricky stuff to handle here.
No guarantees on whether this will land, since there's a lot of tricky stuff to handle here.
ch...@google.com <ch...@google.com> #23
CL is in, and should be out in AppCompat 1.1.0-alpha03. Please test it!
xw...@gmail.com <xw...@gmail.com> #24
testing
ja...@gmail.com <ja...@gmail.com> #25
ch...@google.com <ch...@google.com> #26
Not yet, going out in ~2 weeks.
ja...@gmail.com <ja...@gmail.com> #27
Perfect, thanks!
ja...@gmail.com <ja...@gmail.com> #28
Seems to be working for me
ch...@google.com <ch...@google.com> #29
Awesome, closing this as AppCompat v1.1.0-alpha03 was released yesterday.
mi...@dailymotion.com <mi...@dailymotion.com> #30
Hi I'm using the appcompat 1.1.0, and I get this issue on a Pixel 3
Instantiating a WebView after setDefaultNightMode, revert to my default theme.
Putting WebView(this) before setDefaultNightMode is a (ugly) workaround for the moment.
Do you have some news about that ?
Thanks
Instantiating a WebView after setDefaultNightMode, revert to my default theme.
Putting WebView(this) before setDefaultNightMode is a (ugly) workaround for the moment.
Do you have some news about that ?
Thanks
ro...@gmail.com <ro...@gmail.com> #31
When will this be fixed? Still doesn't work with appcompat 1.2.0 alpha versions.
ga...@gmail.com <ga...@gmail.com> #32
When will this be fixed? Still doesn't work with appcompat 1.2.0 alpha versions.
xj...@gmail.com <xj...@gmail.com> #33
1.2.0-rc01 issue still here ...
[Deleted User] <[Deleted User]> #34
After about 2 years I come back this thread again. The issue still happens when I used native advance ads when using appcompat 1.2.0 and 1.3.0-apha01.
The only way to resolve this problem that still init a dummy WebView in Application before set night theme
The only way to resolve this problem that still init a dummy WebView in Application before set night theme
[Deleted User] <[Deleted User]> #35
1.2.0 issue still here ...
[Deleted User] <[Deleted User]> #36
Hey! You should try custom config workaround.
https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/BaseTestActivity.java;l=89-104?q=BaseTestActivity&ss=androidx%2Fplatform%2Fframeworks%2Fsupport
This is the suggestion.
https://www.reddit.com/r/androiddev/comments/idefss/were_on_the_engineering_team_for_android_jetpack/g3263de?utm_source=share&utm_medium=web2x&context=3
This is the suggestion.
ca...@seadowg.com <ca...@seadowg.com> #38
Still seeing this problem with appcompat 1.3.1. Constructing a dummy WebView
before forcing night mode acts as a workaround (as described earlier in this thread). This should be reopened I think.
sl...@pentacomp.pl <sl...@pentacomp.pl> #39
This issue is still present, using appcompat 1.4.0 here
ta...@gmail.com <ta...@gmail.com> #40
This issue is still present, using appcompat 1.6.0-rc01
ki...@google.com <ki...@google.com>
al...@google.com <al...@google.com>
dm...@gmail.com <dm...@gmail.com> #41
The issue is still present, using appcompat 1.5.1
da...@grupoasesores.com.mx <da...@grupoasesores.com.mx> #42
Still present nowdays... as a work around I've made this as suggested by ch...@google.com
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= 24) {
new WebView(this);
}
super.onCreate(savedInstanceState);
}
It's weird but it works.
FYI: I'm developing a multi fragment application with only one MainActivity, so I had to implement this one-time and that fixed the UiMode issue.
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= 24) {
new WebView(this);
}
super.onCreate(savedInstanceState);
}
It's weird but it works.
FYI: I'm developing a multi fragment application with only one MainActivity, so I had to implement this one-time and that fixed the UiMode issue.
pu...@gmail.com <pu...@gmail.com> #43
This is still an issue using Theme.Material3.DayNight from latest material-components-android, but only on Android 10 devices and below. This is particularly annoying when using AdMob. The ugly workaround to instantiate a WebView prior to calling AppCompatDelegate#setDefaultNightMode still work for these devices:
int nightMode = ...;
if (nightMode != AppCompatDelegate.MODE_NIGHT_NO && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
try {
new WebView(getApplicationContext());
} catch (Exception ignored) {
}
}
AppCompatDelegate.setDefaultNightMode(nightMode);
ab...@gmail.com <ab...@gmail.com> #44
Still present, using androidx.appcompat:appcompat:1.7.0 and the hack "new WebView(this);" still works
Description
Version used: 25.0.0
Theme used: Theme.AppCompat.DayNight
Devices/Android versions reproduced on: Nexus 5x, Nexus 6 - Android 7.0
The activity containing a WebView is recreated (from onStart() method) because uiMode is changed when WebView is being created (inside its constructor). This only happens on the first WebView inflation.
Steps to reproduce this bug:
1º - Set the default night mode to AppCompatDelegate.MODE_NIGHT_YES on application class.
2º - Add a WebView to layout file (in the attached example a CustomWebView has been created only for logs purposes, common WebView has the same effect).
3º - Launch the app and the activity is recreated.
In appcompat-v7 versions previous to 24.2.0 the activity is not recreated but the uiMode is changed too.
Here some logs from:
Main: Before onCreate super() - Mode night active: false
Main: After onCreate super() - Mode night active: true
CustomWebView: Before constructor super() - Mode night active: true
CustomWebView: After constructor super() - Mode night active: false
Main: Before onCreate super() - Mode night active: false
Main: After onCreate super() - Mode night active: true
CustomWebView: Before constructor super() - Mode night active: true
CustomWebView: After constructor super() - Mode night active: true