Как я могу построить проект С++ с несколькими взаимозависимыми подкаталогами?

У меня есть проект на С++, где я использовал каталоги как более организационный элемент - способ использования пакетов в Java или каталогов в PHP. Каталоги не предназначены для самодостаточных элементов, а всего лишь способом организации всего проекта и не позволяя мне быть перегруженным источниками. Как я могу создать мои файлы CMakeLists.txt, чтобы справиться с этим? Создание библиотек каталогов, похоже, не подходит, поскольку они все взаимозависимы и не предназначены для использования таким образом.

Как связанная проблема, большинство примеров, которые я видел в нескольких подкаталогах в CMake (и их не так много), игнорировали или замалчивали проблему установки include_directories, что является чем-то, что я ' у меня были проблемы. Если вы не расчесываете мои исходные файлы, чтобы определить, какой файл зависит от того, в каком и в каком каталоге, есть ли все-таки просто установить все каталоги в /src/, поскольку потенциальные включают каталоги и разрешить CMake работать, какие из них действительно зависят?

Вот пример структуры:

--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

Итак, и т.д. Как я могу структурировать файлы CMakeLists.txt для обработки такой структуры?

Ответ 1

Поскольку структура каталогов в вашем проекте находится там, чтобы поддерживать ваши файлы, один подход состоит в том, чтобы иметь CMakeLists.txt, который автоматически находит все исходные файлы в каталоге src, а также добавляет все каталоги в качестве включенных каталогов, которые имеют заголовочный файл в них. В качестве отправной точки может служить следующий файл CMake:

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})

Две команды file(GLOB_RECURSE ... определяют набор исходных и заголовочных файлов. Цикл foreach вычисляет набор включенных каталогов из списка всех файлов заголовков.

Одним из недостатков при вычислении набора исходных файлов является то, что CMake не будет автоматически обнаруживать, когда новые файлы добавляются в исходное дерево. Вам необходимо вручную создать файлы сборки.

Ответ 2

Я не эксперт в CMake, но, поскольку нет других ответов, я взгляну на документ и даю ему понять. Организация источника и включение файлов в разные каталоги в значительной степени является нормой.

Похоже, что CMake позволяет вам указывать список каталогов include: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories

Так что-то вроде:

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

Они передаются компилятору, чтобы он мог находить файлы заголовков и передаваться для каждого из исходных файлов. Поэтому любой из ваших исходных файлов должен иметь возможность включать любой из файлов заголовков (что, я думаю, это то, о чем вы просите).

Аналогично этому вы должны иметь возможность перечислять все исходные файлы в команде add_executable:

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

Итак, это был бы наивный способ заставить все строить. Каждый исходный файл будет скомпилирован и будет искать заголовки во всех этих каталогах, а затем файлы объектов будут связаны друг с другом. Подумайте, есть ли способ упростить это, так что вам не нужно так много включенных папок, может быть, есть только несколько общих файлов заголовков, на которые нужно ссылаться всеми исходными файлами. Если все усложняется, вы можете создавать подъярусы в библиотеках и т.д. Также рассмотрите разделение исходных файлов и заголовков (например, в src и include).