Status Update
Comments
pa...@google.com <pa...@google.com>
zt...@google.com <zt...@google.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
[Deleted User] <[Deleted User]> #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.
[Deleted User] <[Deleted User]> #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.
[Deleted User] <[Deleted User]> #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.
[Deleted User] <[Deleted User]> #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.
zt...@google.com <zt...@google.com>
zt...@google.com <zt...@google.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.
[Deleted User] <[Deleted User]> #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.
[Deleted User] <[Deleted User]> #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
zt...@google.com <zt...@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.
Description
In Slice.svg:
ERROR@ line 7 <use> is not supported
ERROR@ line 11 <defs> is not supported
Using Android Studio 1.5.1 on Linux.