Проект C++: Зависещо от името на артефакта включва популация на директория с помощта на CMake (време на компилация)

Измислих добра структура за нов проект, който в момента използвам успешно.

ЗАБЕЛЕЖКА: Тази структура е от полза за проекта, който е разработен от множество програмисти.

<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.Whatever“, има име „Haroogan.More.Whatever“.

Това има няколко последствия:

  • библиотека, изпълним файл и т.н., произведени след компилация, ще бъдат наименувани с Artifact-Name;
  • целият изходен код, отнасящ се до определен артефакт, е затворен в пространство от имена, съответстващо на името на артефакта. Например: артефактът "Haroogan.More.Whatever" налага "Haroogan::More::Whatever" пространство от имена на всички свои източници;
  • когато един артефакт иска да използва друг, тогава човек трябва да включи заглавките на друг и по желание да се свърже с него. Въпреки това, всички знаем, че писането на #include "../Haroogan.More/more.h" не само изглежда объркано, но също така нарушава основната идея, че артефактите всъщност представляват самостоятелни компоненти, които трябва да бъдат отделени дори по отношение на файловата система. Освен това концепцията за частни заглавки също е нарушена, защото по този начин имам достъп до всякакви заглавки в други артефакти.

Това, от което се нуждаем тук, е просто публично хранилище на заглавки – директорията „включване“. Затова, за да се справя с последния проблем - реших да направя следното:

  • всеки артефакт решава (разбира се, в своя CMakeLists.txt) сам кои хедъри иска да експортира към външния свят;
  • след това копира (при всяка компилация, но само когато е необходимо, разбира се) тези заглавни файлове в съответната директория вътре в "include". Например, ако Artifact-Name е "Haroogan.More.Whatever", тогава заглавките ще бъдат копирани в директорията "include/Haroogan/More/Whatever/" (както е показано по-горе).

Вярвам, че това е хубав и стабилен подход, тъй като сега, ако искам да използвам класове "каквото" и "повече" от артефакти "Haroogan.More.Whatever" и "Haroogan.More" в други компоненти - просто пиша:

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

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

Системата работи като чар (мога да осигуря CMake скриптове, ако някой иска). Въпреки това не съм доволен от факта, че заглавките се копират. Би било много по-добре, ако например вместо да копира "whatever.h" CMake създаде нов файл "whatever.h" в "Haroogan/More/Whatever/" и инжектира #include "../../../../src/Haroogan.More.Whatever/whatever.h" в него.

Моята система в момента е напълно автоматизирана. С други думи, пътят "Haroogan/More/Whatever" автоматично се извежда от името на артефакта "Haroogan.More.Whatever". Ето защо би било чудесно, ако инжектирането на #include "../../../../src/Haroogan.More.Whatever/whatever.h" с всички тези гадни ../../ също бъде автоматизирано.

За съжаление, аз съм нов в CMake и не знам как да постигна тази функционалност, но мисля, че е възможно и може вече да е направено от някой. Благодаря ти.

РЕДАКТИРАНЕ:

Временно решение на този проблем може да бъде следното:

Вместо да създавам "whatever.h" вътре в "Haroogan/More/Whatever/", което незабавно води до справяне с ../../ бъркотия, мога просто да създам "Haroogan.More.Whatever.whatever.h" (като префикс "whatever.h" с „Haroogan.More.Whatever“) точно в директорията „включване“ и го използвайте като:

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

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

Това решение е приемливо, но не ми харесва толкова, колкото това, което ме интересува.


person Alexander Shukaev    schedule 06.02.2012    source източник
comment
Алтернативен подход би бил, ако всеки CMake-проект във вашата структура дефинира набор от CMake-Project_INCLUDE_DIRS, който след това може да се управлява на ниво CMake   -  person André    schedule 07.02.2012


Отговори (1)


Какво ще кажете за това:

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

Този maro може да се използва сега по следния начин:

В src/Haroogan.More.Whatever/CMakeLists.txt правите

add_public_headers(whatever.h)

и това ще генерира заглавка с един ред #include във вашата директория за компилация.

Единственото нещо е, че този път ще бъде абсолютен, но не би трябвало да е проблем за вас.

person arrowd    schedule 07.02.2012
comment
Значи искаш да кажеш, че въпреки че има други разработчици, които ще изтеглят този проект на своите машини, аз не трябва да се интересувам много от относителните пътища? С други думи, те ще получат свои собствени абсолютни пътища, когато изградят проекта. Е, да, в момента се чувствам комфортно с това решение. Ако обаче се случи да намерите начин да въведете относителен път тук - благодарен съм, ако го споделите. Благодаря, arrowdodger. - person Alexander Shukaev; 07.02.2012
comment
Точно така, те ще получат свои собствени абсолютни пътища. Освен това тези заглавки ще бъдат регенерирани при всяка компилация. - person arrowd; 07.02.2012