CMake Optimization for Static Libraries

Probably none of us like to wait long for the completion of the project assembly, when every second is like an eternity. And itโ€™s good if itโ€™s working hours, and you can pass the time with a glass of coffee, discussing all the shortcomings of automatic garbage collection.


Sometimes, certain success can be achieved by performing CMake optimization. The technique considered here is based on a simple idea: two static libraries that use each other's functions can be assembled simultaneously.


A bit of anatomy


To begin, consider the basic steps of building a static library:


  • preprocessor - removes all comments from source files, inserts header files and replaces macros with calculated values.
  • compiler - converts the files processed by the preprocessor into assembler code.
  • assembler - translates assembly code into machine code; The result is saved as object files.
  • archiver - collect object files into a single archive.

Graphically, these steps are shown in the diagram:



, . , . . , , . 



, , CMake target_link_libraries. :


target_link_libraries(staticC PRIVATE staticB)

, โ€” staticC staticB. , , , staticC, staticB.


, CoherentDeps, :



, staticC staticB, .



, , , ( , ) INTERFACE, -meta ( , ). , -, .


target_link_libraries .


, :



: NonCoherentDeps.


:


  • staticA
  • staticB
  • staticC

NonCoherentDeps.


staticB staticA, staticC staticB, NonCoherentDeps staticC. :



CMake- staticA - :


add_library(staticA-meta INTERFACE)
target_include_directories(staticA-meta  INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")

, :


target_link_libraries(staticA PUBLIC staticA-meta)

staticB CMake


target_link_libraries(staticB PRIVATE staticA)

:


target_link_libraries(staticB PRIVATE staticA-meta)

staticA staticB, . staticB staticA .


:



โ€” :


add_executable(NonCoherentDeps main.cpp)
target_link_libraries(NonCoherentDeps PRIVATE staticC staticB staticA )


, .
, staticA, target_include_directories. NonCoherentDeps, :


target_include_directories(staticB PRIVATE "${path_to_headers_in_staticA}")

:


target_link_libraries(staticB PRIVATE staticA-meta)

, staticB staticA, staticC :


target_include_directories(staticC PRIVATE "${path_to_headers_in_staticB}" "${path_to_headers_in_staticA}")

. :


target_link_libraries(staticB-meta INTERFACE staticA-meta)

staticC :


target_link_libraries(staticC INTERFACE staticB-meta)

staticB, , .


Also in the meta-package you can add a dependency in the form of a command to generate header files, and the properties are correct paths.

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


All Articles