CMake Build Project

Utlizarei essa sessão para descrever algumas idéias a serem discutidas e inseridas no projeto do CMake da TerraLib5, caso acordado.

Arquivos de template usados pelo CMake

Os arquivos de template, são arquivos que podem ser usados pelo CMake, para a geração de arquivos, cujo conteúdo é dinâmico, e que podem ser escritos em tempo de execução do CMake. Esses arquivos podem conter referências para variáveis definidas pelos projetos do CMake. A idéia é que o CMake escreva o arquivo substituindo essas variáveis por seus valores correspondentes no momento da configuração do CMake. A seguir um exemplo de arquivo de template que pode ser usado pelo CMake:

set(PACKAGE_VERSION "@TERRALIB_VERSION@")
 
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
  set(PACKAGE_VERSION_COMPATIBLE TRUE)
  if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
    set(PACKAGE_VERSION_EXACT TRUE)
  endif()
endif()

Neste exemplo, a variável TERRALIB_VERSION, delimitada por '@' será atualizada pelo valor desta variável no momento em que a função de configure do CMake for chamada. O comando do CMake que escreve o arquivo com seus valores atualizados é o seguinte:

configure_file(teBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/teBuildTreeSettings.cmake" @ONLY)

A função é configure_file e os parâmetros são: o primeiro é o nome do arquivo de template e o segundo é o nome do arquivo de saída.

Esses arquivos podem ser úteis em diversas ocasiões, mas aqui discutiremos apenas duas: geração de arquivos de configuração para código c++, e arquivos para códigos CMake.

Arquivos de configuração para código c++

Arquivos de configuração de código c++, são usados para definir variáveis que podem ser usadas em códigos c++. Um exemplo disso é a definição de variáveis conforme os módulos que foram compilados. Nesse caso podemos usar ou não códigos c++ dependendo dos módulos que foram compilados. Outro exemplo é a customização de códigos por plataforma de compilação. Assim como mostrado no exemplo descrito na seção arquivos de template, podemos usar variéveis definidas no projeto CMake delimitados por '@', mas especificamente no caso de códigos c++, existe um comando do CMake, o #cmakedefine, que é usado pra substituir no arquivo gerado por #define, conforme o valor da variável.

#cmakedefine TE_PDI_ENABLED

Neste exemplo, caso o valor da variável TE_PDI_ENABLED seja true, essa linha será subsituída por

#define TE_PDI_ENABLED

no arquivo de saída, caso contrário esse define ainda existirá, porém estará comentado.

Arquivos de configuração para código CMake

Os arquivos de configuração do CMake são criados para carregar informações da compilação para serem acessados por projetos clientes baseados em CMake. Essa é uma facilidade oferecida pelo CMake para poder encontrar definições de bibliotecas.

Quando temos que usar uma biblioteca de terceiros, precisamos inserir no código do projeto CMake um comando find_package. Usar esse comando requer que um pre-requisito seja atendido: é necessário dizer ao CMake, como ele encontra as informações necessárias para usar a biblioteca pesquisada (caminho(s) de include, caminho(s) dos binários, definições, etc). Essas informações podem ser definidas de duas maneiras :

  1. Usando um arquivo find<Biblioteca>.cmake
  2. Usando um arquivo de configuração <Biblioteca>-config.cmake ou <Biblioteca>Config.cmake

No caso de o cliente chamar o comando find_package e o cmake não encontre uma das duas coisas (ou arquivo find ou o config) um erro será gerado e as alternativas serão propostas como solução.

Quando usar o arquivo find e o config

O arquivo find, pode ser usado e escrito em qualquer ocasião. Normalmente é necessário escrever um arquivo de find quando precisamos usar uma biblioteca de terceiros que não usa CMake. Existem diversos arquivos deste tipo dentro do CMake, e é possível criar quantos forem necessários.

O arquivo config é gerado por projetos que usam CMake. Isso facilita para que outros projetos, baseados em CMake, que usem o primeiro, possam encontrar as informações necessárias para linkar com a biblioteca. Facilita porque o cliente da biblioteca não precisará escrever um arquivo de find para encontrá-la. O efeito que se tem é o mesmo do find, porém já disponiblizado pela biblioteca. Além disso, o arquivo é gerado em tempo de execução do CMake, o que o torna dinâmico. Qualquer informação pode ser facilmente adicionada e/ou modificada.

A seguir o template de arquivo config usado na terralib 4.x

# - Config file for the terralib package
# It defines the following variables
#  TE_INCLUDE_DIRS - include directories for FooBar
#  TE_LIBRARIES    - libraries to link against
#  TE_BINARIES 	   - binaries of terralib dependencies
 
# Usage:
#	- In your cmake project use "find_package ( terralib )" command.
# 	- Terralib may also be required with specific modules using "find_package (terralib COMPONENTS shp spl ...) command.
#	- Note that if a module is required and NOT available (was not compiled) an exeception will be raised to cmake.
#
# 	- Components that can be required:
#		- stat (Algorithms for spatial statistics)
#		- shp (Shapefile format support)
#		- dxf (DXF format support)
#		- spl (SPL support for constructing plug-ins)
#		- pdi (Support for image processing algorithms)
#		- dtm (DTM support)
#		- qt4_drivers (Some drivers for qt4 use)
#		- qwt4_drivers (Some drivers for qwt-qt4 use)
 
# Compute paths
get_filename_component(TERRALIB_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
if(EXISTS "${TERRALIB_CMAKE_DIR}/CMakeCache.txt")
   # In build tree
   include("${TERRALIB_CMAKE_DIR}/teBuildTreeSettings.cmake")
else()
	set ( TE_DIRS @TE_INST_DIRS@ )	
	set ( TE_INCLUDE_DIRS ${TERRALIB_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@)
	set ( TE_BINS @TE_BINS@ )
	set ( TE_TRANS "@TE_TRANSLATIONS@" )
	set ( TE_QT4_DRIVERS_ENABLED "@TE_QT4_DRIVERS_ENABLED@")
	set ( LEGACY_QT3_DRIVERS_ENABLED "@LEGACY_QT3_DRIVERS_ENABLED@")
 
	foreach( TRANSLATION ${TE_TRANS} )
		STRING ( REGEX REPLACE ".*/" "" FILENAME "${TRANSLATION}")
		list ( APPEND TE_TRANSLATIONS "${TDK_CMAKE_DIR}/@CONF_REL_BIN_DIR@/translation/${FILENAME}")
	endforeach()	
	foreach( TBIN ${TE_BINS} )
		STRING ( REGEX REPLACE ".*/" "" BIN "${TBIN}")
		list ( APPEND TE_BINARIES "${TERRALIB_CMAKE_DIR}/@CONF_REL_BIN_DIR@/${BIN}")
	endforeach()	
	foreach( TDIR ${TE_DIRS} )
		list ( APPEND TE_INCLUDE_DIRS "${TERRALIB_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@/${TDIR}")
	endforeach()	
	include ( ${TERRALIB_CMAKE_DIR}/CMakeUtils.cmake )	
endif()
 
 
 
# Our library dependencies (contains definitions for IMPORTED targets)
include("${TERRALIB_CMAKE_DIR}/teLibraryDepends.cmake")
 
# These are IMPORTED targets created by teLibraryDepends.cmake
set ( TE_LIBRARIES @TGT_LIBS@ )
 
# Modules compiled 
# This code is used to verify the compiled components.
set ( TE_MODULES @TE_MODULES@ )
 
IF( terralib_FIND_COMPONENTS )
  FOREACH( comp ${terralib_FIND_COMPONENTS} )
	list ( FIND TE_MODULES ${comp} cmp_found )
    if( cmp_found EQUAL "-1" )
      SET(terralib_${comp}_FOUND 0)
      IF(terralib_FIND_REQUIRED_${comp})
        MESSAGE(FATAL_ERROR "TerraLib ${comp} not available.")
      ENDIF()
    ELSE()
      SET(terralib_${comp}_FOUND 1)
	  MESSAGE("TerraLib module ${comp} available.")
    ENDIF()
  ENDFOREACH()
ENDIF() 

Esse template é usado para várias coisas. Ele carrega diversas informações necessárias para o uso correto da terralib. Uma coisa que se pode notar, logo no inicio do arquivo, são os comentários que indicam quais variáveis serão fornecidas ao usuário. Neste caso são três:

  1. TE_INCLUDE_DIRS : define os diretórios de include da TerraLib.
  2. TE_LIBRARIES : define as bibliotecas da TerraLib que estão contidas na compilação.
  3. TE_BINARIES : usado somente em sistemas MS-Windows para informar quais DLL's que serão necessárias na execução (incluindo as de terceiros).

Outra função, é descobrir qual o arquivo de dependencias que ele irá usar. Existem duas possibilidades:

  1. O cliente vai usar uma TerraLib compilada, usando a sua arvore de build.
  2. O cliente vai usar uma TerraLib instalada.

Tais arquivos são usados para que o cliente tenha acesso as corretas localizações dos cabeçalhos e dos binários.

Por último, esse arquivo tem testes para verificar se os módulos requeridos pelo cliente estão compilados.

Técnicas empregadas no CMake da T4

Automatização de carga de arquivos .h, .cpp. Criamos uma função onde passamos quais as pastas que serão usadas. Essa função carrega arquivos .cpp e .h e as subdivide em grupos (para serem usadas no visual studio, por exemplo) que tem os mesmos nomes (montando uma estrutura idêntica à que se tem em disco). Essa função é chamada por todo o código. Fica mais simples na hora de definir quais arquivos fazem parte do projeto.

Modularização dos códigos de projeto. A idéia é que tenhamos dois arquivos: um contendo definições de projeto e o outro contendo as regras de processamento dos arquivos daquele módulo. Com isso conseguimos condensar e/ou expandir módulos mais facilmente.

Definição de layout das dependencias:

  • root <win32>
    • include
      • gdal
      • geos
    • lib
      • *.lib / *.a
    • bin
      • *.dll / *.so

Usar o CMake para setar variaveis de ambiente. Dessa forma não precisariamos replicar os FindModule. E não seria preciso que o usuário definisse nenhuma variável de ambiente, a entrada seria fornecida no próprio CMake.

Inclusão de módulos é feita de forma inversa ao que temos na TerraLib 4. Na terralib 5, primeiramente, são pesquisadas todas as bibliotecas de terceiros, caso elas sejam encontradas, os módulos vão sendo habilitados. No projeto da T4, fazemos o caminho inverso, só pesquisamos as bibliotecas cujos módulos sejam dependentes.

Frederico Augusto Bede 2012/05/16 10:51

Variáveis de Configuração

TE_DEFAULT_LOGCONF_FILE → Location of the log files output.

TE_SCHEMA_LOCATION → Location of the xsd schemas of the TerraLib. (<TerraLib_DIR>/schemas/terralib)

TE_LOGO → Location of the TerraLib logo.

TE_JSON_FILES_LOCATION → Location of the JSON files for initialization purposes.

TE_SQL_FILES_LOCATION → Location of the SQL files for initialization purposes.

TE_XML_FILES_LOCATION → Location of the XML files for initialization purposes.

TE_ABOUT_LOGO → Location of the ABOUT logo.

TE_ICONS_THEME_PATH → Location of the icons themes. (<Terralib_DIR>/resources/themes)

TE_ICONS_THEME → Name of the icons theme to be used. ( Actually the value is “terralib”)

TE_BIN_DIR → Location of the TerraLib binary output.

TERRALIB_MAJOR_VERSION → TerraLib version major value.

TERRALIB_MINOR_VERSION → TerraLib version minor value.

TERRALIB_PATCH_VERSION → TerraLib version patch value.

TERRALIB_RELEASE_STATUS → TerraLib release status value.

TERRALIB_STRING_VERSION → TerraLib version as a string value.

TERRALIB_INT_VERSION → TerraLib version as an integer value.

TE_VERSION → TerraLib complete version.(<TERRALIB_MAJOR_VERSION>.<TERRALIB_MINOR_VERSION>.<TERRALIB_PATCH_VERSION>)

TE_DIR_ENVIRONMENT_VARIABLE → Name of the variable that contains the location of the binaries of the TerraLib. (Actually the value is “TE_BIN_DIR”)

TVIEW_CONFIG_FILE → Location and name of the configuration file of the TerraView. (Actually the value is <TE_BIN_DIR>/config.xml)

TVIEW_RESOURCE_FILE → Location of the Qt help file collection.

TVIEW_TE_LOGO → Logo used in the TerraView about dialog.

TVIEW_LOGO → TerraView logo.

TVIEW_LARGE_LOGO → TerraView logo extended.

TVIEW_SPLASH_SCREEN_PIXMAP → Image used in the initialization of the TerraView in the splash screen.


QR Code
QR Code wiki:designimplementation:build:cmake (generated for current page)