Provavelmente, nenhum de nós gosta de esperar muito pela conclusão da montagem do projeto, quando cada segundo é como uma eternidade. E é bom se for o horário de trabalho e você pode passar o tempo com um copo de café, discutindo todas as desvantagens da coleta automática de lixo.
Às vezes, é possível obter certo sucesso executando a otimização do CMake. A técnica considerada aqui é baseada em uma idéia simples: duas bibliotecas estáticas que usam as funções uma da outra podem ser montadas simultaneamente.
Um pouco de anatomia
Para começar, considere as etapas básicas da construção de uma biblioteca estática:
- pré - processador - remove todos os comentários dos arquivos de origem, insere os arquivos de cabeçalho e substitui as macros pelos valores calculados.
- compilador - converte os arquivos processados pelo pré-processador em código assembler.
- assembler - traduz código de montagem em código de máquina; O resultado é salvo como arquivos de objeto.
- arquivador - colete arquivos de objetos em um único arquivo.
Graficamente, estas etapas são mostradas no diagrama:
, . , . . , , .
, , CMake target_link_libraries. :
target_link_libraries(staticC PRIVATE staticB)
, — staticC
staticB
. , , , staticC
, staticB
.
, CoherentDeps, :
, staticC
staticB
, .
, , , ( , ) INTERFACE
, -meta ( , ). , -, .
target_link_libraries
.
, :
: NonCoherentDeps.
:
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
, , .
Também no meta-pacote, você pode adicionar uma dependência na forma de um comando para gerar arquivos de cabeçalho, e as propriedades são caminhos corretos.