Проект C ++: зависимое от Artifact-Name заполнение каталога «include» с использованием CMake (время сборки) - PullRequest
1 голос
/ 06 февраля 2012

Я разработал хорошую структуру для нового проекта, который сейчас успешно использую.

ПРИМЕЧАНИЕ: Эта структура полезна для проекта, который разрабатывается несколькими программистами.

<Project Directory>
    + include
        + Haroogan
            + Utility
                - util.h
            + More
                - more.h
                + Whatever
                    - whatever.h

    + src
        + Haroogan.More             <--- Artifact
            - more.h
            - more.cpp
            - CMakeLists.txt
        + Haroogan.More.Whatever    <--- Artifact
            - whatever.h
            - whatever.cpp
            - CMakeLists.txt
        + Haroogan.Utility          <--- Artifact
            - util.h
            - util.cpp
            - CMakeLists.txt
        + Haroogan.Application      <--- Artifact
            - app.h
            - app.cpp
            - CMakeLists.txt
        - CMakeLists.txt            <--- "Root" CMakeLists.txt

Артефакт - это библиотека, исполняемый файл и т. Д. - вы получили точку.

Имя артефакта (как в теме) - это просто имя артефакта, которое выводится CMake из имени каталога, выделенного для артефакта. На самом деле термины Artifact и Artifact-Name по существу совпадают. Например: артефакт, находящийся в каталоге "Haroogan.More.Wh независимо", имеет имя "Haroogan.More.Whwhat".

Это имеет несколько последствий:

  • библиотека, исполняемый файл и т. Д., Созданные после сборки, будут названы Artifact-Name;
  • весь исходный код, относящийся к конкретному артефакту, заключен в пространство имен, соответствующее имени артефакта. Например: артефакт "Haroogan.More.Wh независимо" налагает "пространство имен Haroogan :: More :: Whither" на все его источники;
  • когда один артефакт хочет использовать другой, тогда нужно включить заголовки другого и, возможно, связать его. Тем не менее, мы все знаем, что написание #include "../Haroogan.More/more.h" не только выглядит грязно, но и нарушает основную идею, что артефакты на самом деле представляют собой отдельные компоненты, которые должны быть отделены даже с точки зрения файловой системы. Более того, концепция частных заголовков также нарушена, потому что таким образом я могу получить доступ к любым заголовкам внутри других артефактов.

Здесь нам нужен просто публичный репозиторий заголовков - каталог «include». Поэтому для решения последнего вопроса - я решил сделать следующее:

  • каждый артефакт сам решает (конечно, в своем CMakeLists.txt), какие заголовки он хочет экспортировать во внешний мир;
  • Затем он копирует (при каждой сборке, но, конечно, только при необходимости) эти заголовочные файлы в соответствующий каталог внутри «include». Например, если Artifact-Name имеет значение «Haroogan.More.Wh независимо», тогда заголовки будут скопированы в каталог «include / Haroogan / More / Whwhat /» (как показано выше).

Я полагаю, что это хороший и надежный подход, так как теперь, если я хочу использовать классы "what" и "more" из артефактов "Haroogan.More.Wh независимо" и "Haroogan.More" в других компонентах - я просто пишу:

#include <Haroogan/More/Whatever/whatever.h>
#include <Haroogan/More/more.h>

using Haroogan::More::Whatever::whatever;
using Haroogan::More::more;

Система работает как шарм (я могу предоставить сценарии CMake, если кто-нибудь захочет). Тем не менее, я не удовлетворен тем, что заголовки копируются. Было бы намного лучше, если бы, например, вместо копирования «what.h» CMake создал новый файл «what.h» в «Haroogan / More / Whwhat /» и inject #include "../../../../src/Haroogan.More.Whatever/whatever.h" в нем .

Моя система сейчас полностью автоматизирована. Другими словами, путь "Haroogan / More / Wh независимо" автоматически выводится из названия артефакта "Haroogan.More.Whwhat". Поэтому было бы здорово, если бы инъекция из #include "../../../../src/Haroogan.More.Whatever/whatever.h" со всеми этими мерзкими ../../ также была бы автоматизирована.

К сожалению, я новичок в CMake и не знаю, как реализовать эту функцию, но я думаю, что это возможно и может быть уже кем-то сделано. Спасибо.

EDIT:

Временное решение этой проблемы может быть следующим:

Вместо того, чтобы создавать "what.h" внутри "Haroogan / More / Whither /", которое сразу же приводит к беспорядку ../../, я мог бы просто создать "Haroogan.More.Whwhat.whever.h" (с префиксом " what.h "с" Haroogan.More.Whwhat ") прямо в каталоге" include "и используйте его как:

#include <Haroogan.More.Whatever.whatever.h>

using Haroogan::More::Whatever::whatever;

Это решение приемлемо, но мне оно не нравится так, как мне интересно.

1 Ответ

1 голос
/ 07 февраля 2012

Как насчет этого:

macro(add_public_headers)
  foreach(header ${ARGN})
    get_filename_component(abspath ${header} ABSOLUTE)
    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${header} "#include ${abspath}"
  endforeach()
endmacro()

Этот маро теперь можно использовать так:

В src/Haroogan.More.Whatever/CMakeLists.txt вы делаете

add_public_headers(whatever.h)

и это сгенерирует заголовок с одной строкой #include в директории сборки.

Единственное, что путь будет абсолютным, но для вас это не должно быть проблемой.

...