В чем разница между переменными CMake и свойствами?

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

У каждого из них есть свои собственные разделы документации, но оба могут влиять на систему сборки, оба «уже существуют», и оба могут быть динамически сгенерированы на основе других команд CMake. Похоже, у них должны быть разные цели. Кто они такие?

В свойстве вы можете создать имя из составного токена, такого как <name>:<os_name>:<config_name>:<arch_name> и т. д., И проанализировать его как отдельную переменную, используя регулярное выражение или что угодно. В имени переменной вы не можете использовать этот метод, потому что имя переменной не должно содержать недопустимых символов, таких как :. Таким образом, свойства вместе друг с другом могут использоваться для каких-то значений структурных переменных.

Andry 11.02.2019 20:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
1
2 007
3

Ответы 3

Если коротко и просто подумать об этом, свойства - это переменные, привязанные к цели. Например:

add_executable(foo foo.cpp)
set_target_properties(foo PROPERTIES
    CXX_STANDARD 14
    CXX_EXTENSIONS OFF
)
# Build foo with c++11 for some reason
add_executable(foo11 foo.cpp)
set_target_properties(foo11 PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS OFF
)

Если CMakeLists.txt был написан на C++, это могло бы выглядеть примерно так:

const char * src_files[] = { "foo.cpp" };
executable foo{src_files};
foo.setCxxStandard(14);
foo.setCxxExtensions(false);

executable foo11{src_files};
foo.setCxxStandard(11);
foo.setCxxExtensions(false);

Если бы мы использовали переменные для этих вещей, это выглядело бы примерно так:

// globals
int CMAKE_CXX_STANDARD = 14;
bool CMAKE_CXX_EXTENSIONS = false;

// later, in a function
const char * src_files[] = { "foo.cpp" };
executable foo{src_files}; // foo copies global settings

CMAKE_CXX_STANDARD = 11;
executable foo11{src_files};

Поскольку свойства являются частью цели, а не глобальными объектами, это также означает, что их можно экспортировать. Санировал один из моих проектов:

set_target_properties(Foo::bar PROPERTIES
    INTERFACE_COMPILE_FEATURES "cxx_std_14"
    INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/"
    INTERFACE_SOURCES "${_IMPORT_PREFIX}/include/foo/bar.hpp"
)

Это означает, что если вы импортируете Foo::bar (возможно, через что-то вроде find_package(Foo)), ваш проект уже знает, что для вещей, связывающихся с Foo::bar, необходимо использовать C++ 14 (INTERFACE_COMPILE_FEATURES), ему нужно что-то добавить в путь включения (INTERFACE_INCLUDE_DIRECTORIES), и есть некоторые исходные файлы, о которых он заботится (мои заголовки, INTERFACE_SOURCES).

Ах, я думаю, я могу понять разницу, поскольку свойства могут быть ограничены, тогда как переменные всегда глобальны. За исключением документации по свойствам, здесь свойства cmake.org/cmake/help/v3.11/manual/cmake-properties.7.html также могут быть глобальными, поэтому в этом случае меня все еще сбивает с толку, и различие кажется произвольным.

user1489829 22.04.2018 00:47

@ user1489829 - Признаюсь, я не знал о глобальных свойствах, поэтому мне пришлось бы это выяснить. Мой ответ касается свойств целевых объектов, но сравнение можно расширить для любого неглобального свойства.

Stephen Newell 22.04.2018 03:07

Как обозначено user1489829, есть также свойства Global Scope, что делает этот ответ неверным. Так что все же хотелось бы получить правильный и более исчерпывающий ответ. По состоянию на май 2018 года поиск в Google не дал ничего полезного.

Fedorov7890 16.05.2018 15:23

Я думаю, что ответ Стивена Ньюэлла отражает основную мотивацию для свойств (и аналогия С ++ переменных-членов и переменных, не являющихся членами, очень полезна).

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

Возможно, чтобы переменная ('Глобальный') и (глобальное) свойство с тем же именем существовали одновременно (но польза от этого не очевидна).

Таким образом, свойства в первую очередь полезны тем, что они «привязаны» к чему-то вроде цели. Глобальные свойства также ограничены одним «глобальным объектом». (По аналогии со Стивеном они могут быть переменными-членами синглтона). Свойства устанавливаются / получают с другим синтаксисом переменных. И свойство с заданной областью действия может одновременно существовать с другими с тем же именем в любой другой области (включая глобальную), а также как обычная переменная с тем же именем.

здесь дает одну возможную пользу от объединения глобальных свойств и переменных:

A global property can be a useful uncached global variable. Many target properties are initialised from a matching variable with CMAKE_ at the front. So setting CMAKE_CXX_STANDARD, for example, will mean that all new targets created will have CXX_STANDARD set to that when they are created

Во-первых, как языки программирования обрабатывают переменные? Переменные в языках программирования можно разделить на две группы. На основе стека или объекта.

  • Переменные на основе стека - это переменные, которые хранятся в памяти, которую резервирует каждая функция, память, найденная в стеке. Зарезервированная область в стеке постоянно увеличивается и уменьшается при вызове функций. Когда вводится новая функция, эта функция резервирует память для переменных в верхней части стека. Выход из функции приведет к уничтожению области и стиранию переменных.
  • Переменные на основе объекта хранятся в области памяти, зарезервированной для объекта. Переменные на основе объекта уничтожаются при уничтожении объекта. Обычно они уничтожаются каким-либо типом операции / команды. Этот тип объектных переменных иногда называют переменными-членами.

Языки сценариев тоже работают так же, но в них есть хитрости для имитации стека. Когда функция вводится на языке сценариев, стек обычно также является одним объектом. Этот объект знает о своем стеке вызывающего абонента. Он работает как дерево, где переменные ветви растут и сжимаются, каждая ветвь знает о своем родителе и имеет листья, которые здесь являются переменными. Время запуска для запуска программ-скриптов не может быть слишком долгим, поэтому время на анализ кода для его оптимизации ограничено. Это дерево стека, которое существует в языках сценариев, является компромиссом и упрощает их синтаксический анализ и анализ по сравнению с языком, который хранит переменные в стеке, поскольку процессор компьютера может с этим справиться.

Итак, как переменные и свойства работают в CMake. Код не проверял, но догадываюсь. Переменные основаны на стеке, свойства основаны на объектах. Для печати значения переменной с сообщением требуется переменная на основе стека, команда сообщения может найти переменные, хранящиеся в стеке. Он не может найти свойства, потому что они являются членами одного объекта в CMake. Чтобы получить значение из свойства, вам также понадобится объект, поэтому вам нужна другая команда, например get_property.

Вот учебник CMake

«Я не проверял код, но догадываюсь».

johnwbyrd 26.12.2020 22:19

Другие вопросы по теме