CMake - набор костылей и говен
- Find*. каждый пишет как придётся, нет унификации порождаемых переменных (INCLUDE_DIR/INCLUDE_DIRS/INCLUDE_DIRECTORY/INCLUDE_DIRECTORIES, LIB/LIBS/LIBRARY/LIBRARIES, капитализация имени, капитализация компнонтов пакета)
- Некоторые пакеты использую pkgconfig, некоторые — нет
- Некоторые пакеты не знают, что такое variable cache
- Половина пакетов не использует find_package_handle_standard_args
- get_property/get_*_properties - GOD OH GOD WHY THEY HAVE DIFFERENT CALL CONVENTIONS?
- install(EXPORT) (ср. export()), find_filename_component(PROGRAM) (ср. find_program()) — почему они здесь?
- end*() - в теории, надо писать то же, что и в открывающем выражении. На практике, это лишняя работа, проверяется через раз (содержимое statement'ов вполне может разъехаться) и в итоге лучший способ в современном CMake - забивать и писать пустые скобки
- if() - variable vs its value - if ( VAR STREQUAL VAR) # XXX check
- списки, разделяемые точками с запятыми. По аналогии с шеллом, его IFS и $@.
- В реальности можно собирать только С и кресты (скорее всего, ещё фортран). God help you если возникнет желание собирать, например, java (впрочем в случае java, наполовину это обуславливается существующими способами сборки java, но имеющиеся в поставки модули для java ARE NOT HELPING).
- Костыли в основной поставке для fltk и qt, почему-то не завёрнутые в модули.
- case sensitive/insensitive в разных местах
- add_custom_command/add_custom_target: в add_custom_command есть синтаксис для добавления зависимостей некоторому таргету (add_custom_command(... APPEND)), у add_custom_target (где он, казалось бы, востребованней) его нет (при этом, зависимостями могут быть как файлы, так и phony-таргеты, естественно) (есть add_dependencies:). С другой стороны, add_custom_command нельзя добавить в ALL.
- COMPILE_DEFINITIONS/COMPILE_FLAGS - разный синтаксис добавления (первое - список, второе - строка)
Minor:
- Для сборки дистрибутива, использующего autotools, autotools не нужен. Для cmake это не так (более того, некоторые вещи без cmake -E унифицированно не сделаешь)
- Любимая всеми свистелка - прогресс сборки - кривая и код был написан явно очень давно. Как минимум, оно неправильно работает при частичной многопоточной сборке нескольких таргетов; плюс, точность его при частичной сборке отдельных таргетов в больших проектах сильно страдает. И никогда, никогда не следует смотреть на то, какой именно код задействован для вывода этих самых процентиков.
Best practices:
- В случае, если необходимо вернуть результат, обычно передают имя переменной. Все промежуточные операции над результатом лучше делать над некоей внутренней переменной с фиксированным именем (например, _res), и в конце сделать set("${_out}" "${_res}" PARENT_SCOPE) для избежания name clash между значением _out и одной из внутренних переменных.
- Пример обратного - CMakeParseArguments
- Ещё в 2.8.9/2.8.12 не работал cmake(var "" PARENT_SCOPE)
- Опять же, поскольку окружение наследуется, важно делать set/unset перед проверкой переменных (например if (DEFINED ...), после cmake_parse_arguments())