2011-08-03 16 views
59

Tengo un proyecto de C++ en el que he usado directorios como un elemento más de la organización, la forma en que uno podría usar paquetes en Java o directorios en PHP. Los directorios no pretenden ser elementos autosuficientes, sino simplemente una forma de organizar todo el proyecto y evitar que las fuentes lo abrumen. ¿Cómo puedo construir mis archivos CMakeLists.txt para manejar esto? Hacer las bibliotecas de directorios no parece encajar aquí, ya que todas son interdependientes y no están destinadas a ser utilizadas de esa manera.¿Cómo puedo crear un proyecto en C++ con múltiples subdirectorios interdependientes?

Como un problema relacionado, la mayoría de los ejemplos que he visto de múltiples subdirectorios en CMake (y no son muchos) han ignorado o pasado por alto el problema de configuración include_directories, que es algo que he estado teniendo problemas con. Sin peinar mis archivos de origen para determinar qué archivo depende de qué directorio y en qué directorio, de todos modos hay que configurar todos los directorios bajo /src/ como posibles directorios de inclusión y dejar que CMake determine cuáles son realmente dependientes.

He aquí un ejemplo de estructura:

--src 
    --top1 
    --mid1 
     --bot1 
     --src1.cpp 
     --hdr1.h 
     --bot2 
     --src2.cpp 
     --hdr2.h 
    --mid2 
     --bot3 
     --src3.cpp 
     --src4.cpp 
     --hdr3.h 
    --top2 
    --mid3 
     --src5.cpp 
     --hdr4.h 

así sucesivamente y así sucesivamente. ¿Cómo puedo estructurar mis archivos CMakeLists.txt para manejar este tipo de estructura?

+1

¿Es absolutamente necesario utilizar CMake? –

+0

1.) ¿Está trabajando con un Generador preferido? 2.) ¿De verdad crees que CMake debería descubrir qué depende de qué? Creo que debería ser posible definir módulos (por ejemplo, mid1, mid2, top2) que deberían ser independientes entre sí. 3.) ¿Incluyes #include "hdr2.h" o algo así como ? – Philipp

+0

@benoit Supongo que no, pero eso es lo que estoy usando actualmente. Prefiero no usar Automake, me parece un gran esfuerzo incorporar el aprendizaje de un sistema de compilación cuando mis compilaciones no son tan complejas. –

Respuesta

50

Como la estructura de directorios de su proyecto está ahí para mantener sus archivos organizados, un enfoque es tener CMakeLists.txt que encuentre automáticamente todos los archivos de fuentes en el directorio src y también agregue todos los directorios como directorios de inclusión que tengan un archivo de encabezado en ellos. El siguiente archivo de CMake puede servir como punto de partida:

cmake_minimum_required(VERSION 3.0) 

project (Foo) 

file(GLOB_RECURSE Foo_SOURCES "src/*.cpp") 
file(GLOB_RECURSE Foo_HEADERS "src/*.h") 

set (Foo_INCLUDE_DIRS "") 
foreach (_headerFile ${Foo_HEADERS}) 
    get_filename_component(_dir ${_headerFile} PATH) 
    list (APPEND Foo_INCLUDE_DIRS ${_dir}) 
endforeach() 
list(REMOVE_DUPLICATES Foo_INCLUDE_DIRS) 

add_executable (FooExe ${Foo_SOURCES}) 
target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS}) 

Los dos comandos file(GLOB_RECURSE ... determinar el conjunto de archivos de origen y de cabecera. El ciclo foreach calcula el conjunto de directorios de inclusión de la lista de todos los archivos de encabezado.

Una desventaja al calcular el conjunto de archivos fuente es que CMake no detectará automáticamente cuando se agreguen nuevos archivos a su árbol fuente. Usted tiene que volver a crear manualmente sus archivos de compilación entonces.

+0

Ya había intentado algo similar, pero con diferente lógica include_directories (que falló miserablemente). Voy a probar esto. –

+15

¡Gracias por esto! No puedo entender que esto sea tan difícil de encontrar: ¿nadie está organizando sus archivos fuente en subdirectorios? – Cygon

+2

@Cygon - aparentemente no. :-) –

2

No soy un experto en CMake pero como no hay otras respuestas, echaré un vistazo al documento y lo intentaré. Organizar fuentes e incluir archivos en diferentes directorios es prácticamente la norma.

Parece que CMake le permite dar una lista de directorios de inclusión: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories

Así que algo como:

include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ...) 

Estos se pasan al compilador para que pueda encontrar los archivos de cabecera y la voluntad pasar por cada uno de los archivos de origen. Por lo tanto, cualquiera de sus archivos fuente debe poder incluir cualquiera de los archivos de encabezado (que creo que es lo que está pidiendo).

similares a que debe ser capaz de enumerar todos los archivos de origen en el comando add_executable:

add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...) 

lo que esta sería una forma ingenua de conseguir todo para construir. Cada archivo fuente se compilará y buscará encabezados en todos esos directorios y luego los archivos del objeto se vincularán entre sí. Considere si hay alguna forma de simplificar esto, de modo que no necesite tantas carpetas de inclusión, quizás haya solo unos pocos archivos de encabezado comunes a los que todos los archivos fuente deban hacer referencia. Si las cosas se vuelven más complejas, puede crear sub-jerarquías en bibliotecas, etc. También considere separar los archivos de origen y los encabezados (por ejemplo, en src e include).

Cuestiones relacionadas