CMake collaborative project subdirectories avoid restructuring

For the project, I use Android gradle scripts with the CMake plugin, gradle is version 3: 0: 0, version CMake 3.6. Both gradle and CMake files are quite simple and uninteresting (just defining the files used - I can still copy them if necessary).

I have the following project structure; basically a codebase that produces dozens of .so files (native to Android packages that are packaged in apk, thereby called โ€œexecutable filesโ€), which all depend on the same code in a shared library (static libraries called so called "Libraries" "). The library code is still (relatively) volatile, so I want the executable files to be dependent on the project level, so whenever the executable executable files are created, the libraries are restored on demand every time, hen their code changes the structure looks like this.:

+ LibProjects/ ---Bin/ (Originally empty) ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) ... ---Lib10/CMakeLists.txt (same) + Executables/ ---Executable1/CMakeLists.txt (source files here) --------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt) ... ---Executable40/CMakeLists.txt 

CMakeLists libraries redirect their output to the bin folder using

 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName}) 

Executable projects add library dependencies "as usual"

 add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})... 

Everything almost works, in the sense that I can get reasonable executable files and trigger assemblies of library executable files.

The problem is that when sequentially creating executable files, each of them DOES NOT reuse the outputs of the others library project: when I create Executable1, it will build all the libraries (normal), and then it will build it. Subsequently, when I create Executable2, it will NOT reuse libraries that were already created for Executable1, and so on - this effectively increases the build time by 10 times.

I can find the output of the assembly of each library inside the / Bin folder, as expected, but they are not reused in the executable files - there are no CMake project files (this is the correct term) in the bin folder, they are all generated inside the assembly executable directory.

The problem I'm trying to solve is the build time associated with the fact that each library is restored for each executable.

At the moment, the solutions I'm considering are somehow to instruct CMake to use the Bin folder (or another folder) as the working folder for each library in its own folder instead of the executable, hoping that the gradle android plugin will be smart enough. to then determine that neither cmakefiles nor object files need to be restored, and avoid recovery.

The limitation that I have is that I cannot restructure the code base itself and that each executable function must be built separately from the others - there is absolutely no possibility of top-level CMake - each executable must be launched on its own.

+5
source share
3 answers

CMake can guess if the assembly is updated by reading information from the current assembly directory.

When you start CMake manually in the Executables/<x> directory, cmake retrieves information from the assembly directory associated with the Executable/<x> directory. Then check to see if the timestamp of the embedded file matches the latest assembly performed in this assembly directory. If not, it is restored. It happens that: Lib1 library file is created after executable1 is built, then you run cmake in Executalbe2 , it compares the timestamp of the target file Lib1 , see that this file was not created by this instance, create cmake and then rebuild lib. And so on.

So, you have two options:

1- Either you create a library and install your target files in the bin (using the install cmake and make install bash commands). Then in Executalbe<x>/CMakeLists you use the find_library command instead of add_subdirectory .

2- Or you create a superproject that has the following structure:

 + supper_project ---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)... + LibProjects/ ---Bin/ (Originally empty) ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) ... ---Lib10/CMakeLists.txt (same) + Executables/ ---Executable1/CMakeLists.txt (source files here) --------------/AndroidFiles/build.gradle (and other android project files) (not any more:points to the CMakeLists.txt) ... ---Executable40/CMakeLists.txt 
+2
source

I think the problem is how you defined your dependencies.

For each executable, you create separate targets using add_subdirectory. for example for executable 1 you have add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1}) , and for executable 2 you also have add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1}) , so cmake will create two separate targets for one library1 in each executable subdirectory, and thus create separate timestamps and cache files. That's why it looks like he is building the same library several times, but in fact they are different purposes for cmake.

To fix this, you can include all the libraries in the top-level CMakeLists.txt using add_subdirectory , and add a dependency in each CMakeLists.txt executable using the add_dependencies .

0
source

I managed to get around this problem, but in the end it worked, not with CMake.

I removed the CMakeFile level dependencies (add_subdirectory) and left only the libraries at the link level (target_link_libraries Executable [library files])

Then I created gradle scripts for each library and added dependencies to these scripts in every gradle script application, so library creation is started using gradle dependencies instead of CMake dependencies. This is slower than it would be if gradle could be avoided, but much faster than rebuilding every time, and the overhead is at least constant (a few seconds per project).

0
source

Source: https://habr.com/ru/post/1274046/


All Articles