Saturday, April 4, 2015

Определение корневого каталога теневой сборки qmake

Как оказалось, в qmake не так просто определить корневую директорию теневой сборки. Проблема появляется, когда есть несколько вложенных проектов subdirs. Например, мы можем иметь такую структуру проектов:

Project_1 (subdirs) (уровень 1)
  Project_1.1 (subdirs) (уровень 2)
    Project_1.1.1 (lib) (уровень 3)
    Project_1.1.2 (lib)
    ...
    Project_1.1.m (app)
  Project_1.2 (subdirs)
    ...
  ...
  Project_1.n (subdirs)
    ...

Если запустить qmake для проекта Project_1, то для проекта Project_1.1.1 корневая директория теневой сборки будет $$PWD/../../ ($$PWD - путь к файлу проекта Project_1.1.1). Если же запустить qmake для проекта Project_1.1, то для проекта Project_1.1.1 корневая директория теневой сборки будет $$PWD/../. Проблема в том, что из .pro файла проекта Project_1.1.1 невозможно узнать, для какого проекта запущен qmake, как следствие, нельзя узнать корневую директорию теневой сборки.

Но при некоторых особых (очень особых) обстоятельствах есть один прием. Это можно сделать, если имя каталога теневой сборки не совпадает с именем проекта, а вложенность проектов не превосходит 3. При этом узнать корневой каталог теневой сборки можно только при запуске qmake для проектов первого и второго уровня. Вот как выглядит дерево каталогов теневой сборки для Project_1.

Project_1_sb
  Project_1.1
    Project_1.1.1
    Project_1.1.2
    ...
    Project_1.1.m
  Project_1.2
    ...
  ...
  Project_1.n
    ...

А вот так оно выглядит для проекта Project_1.1.

Project_1.1_sb
  Project_1.1.1
  Project_1.1.2
  ...
  Project_1.1.m

Идея заключается в том, чтобы разбить $$PDW на компоненты, и подниматься вверх по директориям до того момента, когда имя каталога не совпадет с именем проекта второго уровня (Project_1.1). Если каталог с именем Project_1.1 был найден в $$PWD, то корневая директория теневой сборки находится на уровень выше этой директории. Если же такой каталог не был найден, то корневая директория теневой сборки находится в $$PWD/../. Функция для определения корневого каталога теневой сборки принимает на вход имя проекта второго уровня (Project_1.1), а возвращает абсолютный путь к корневой директории теневой сборки.

defineReplace(getShadowRoot) {
    __ROOT_PROJECT_NAME = $$1

    __SPLITTED_PATH = $$split(OUT_PWD, "\\")
    __SPLITTED_PATH = $$split(__SPLITTED_PATH, "/")

    __SPLITTED_ROOT = $$__SPLITTED_PATH
    __REVERSED_SPLITTED_ROOT = $$reverse(__SPLITTED_PATH)

    for(__DIR_NAME, __REVERSED_SPLITTED_ROOT) {
        __SPLITTED_ROOT -= $$__DIR_NAME
        equals(__DIR_NAME, $$__ROOT_PROJECT_NAME):return($$join(__SPLITTED_ROOT,"/"))
    }

    __SPLITTED_PATH -= $$last(__SPLITTED_PATH)
    return($$join(__SPLITTED_PATH,"/"))
}
К сожалению, это единственный способ, который пришел мне в голову. Да, решение нельзя назвать красивым или удачным, но оно работает именно в том случае, который мне нужен.

No comments:

Post a Comment