I created a discussion topic with a similar title in the help section but it did not receive any attention. I am reiterating the issues I have found here to seek advice and suggestions from the Gradle team.
I have created a native test plugin using Boost Test for use with a large C++ project that I am porting to Gradle from CMake. The Boost Test unit tests that already exist have used the one test executable per test suite option which is terribly inefficient yet necessary for reasons I will not go into here. With the model of the existing native test plugins as a guide I found that the code for the library under test is compiled and linked into a unit test binary instead of the test binary having a “uses” dependency to the library under test. Aside from this being an invalid test IMHO since it is not testing the compiled library but a simulated binary with the code of the library embedded it is causing the compilation to happen as many times as there are test suites.
In this project there are over 1,300 test executables which are testing as many as 20 separate dynamic libraries. You can imagine that compiling and linking these is bad enough for the unit test source code alone, having the attached library source code added to the mix makes this completely unacceptable in terms of build time performance. On top of the source code recompilation issue the install task behavior is multiplied the same way. These 1,300 test executables if installed would require 1,300 copies of the library dependencies, not a sustainable build model in my opinion.
I addressed these issues in my Boost Test plugin by extracting the code that was part of the NativeBinariesTestPlugin and making the same work in my plugin by having the library under test as a library dependency of the generated test components. I also generated one test component per source file to satisfy the unfortunate choice of the executable per test suite operation of Boost. Finally I created a new task that constructs a “test-wrapper” script for each test executable that sets the LD_LIBRARY_PATH or the PATH in Windows correctly to make all the library dependencies accessible at runtime eliminating the need to “install” the test executable. This has proven successful and gives me high confidence that it is the final product being tested not a simulated binary with the compiled code embedded.
In addition to the problem I solved with the library dependency I made the plugin create test executables for both shared and static library variants. I managed that by giving each executable a separate type string with the keyword static or shared in it.
I would like to contribute all this work back to the core Gradle if possible. I still have to discuss with my employer the possibility of doing this soon. I hope we can agree that some of the ideas presented here are valuable and perhaps adjust the current CUnit and GoogleTest plugins to take similar approaches.