Как CMake add_executable работает внутренне (зависимости и автоматическое обнаружение источника c)? - PullRequest
0 голосов
/ 29 апреля 2020

Я работаю над своим первым проектом CMake / C, и я столкнулся с проблемой со своей сборкой, которая заставляет меня переспросить, как работает компиляция.

Я хотел бы, чтобы люди объяснили мне, что именно происходит когда вы вызываете add_executable и как make создает C файловых зависимостей.

Что я думал

Я думал, что при вызове add_executable (name, sources) , CMake будет видеть sources как расширенный набор необходимых исходных файлов для построения целевого имени. Поэтому он внутренне анализирует зависимости РЕАЛЬНОГО МИНИМАЛЬНОГО, анализируя файл, содержащий main, и рекурсивно добавляет включенные файлы .h с соответствующими объявлениями в файлах. c.

Что, по-видимому, происходит (Я хочу подтверждение)

CMake видит sources как реальный минимум зависимостей для исполняемого файла. Кажется, он скомпилирует НИЧЕГО в sources , независимо от того, используется он где-либо или нет.

Следствие

Это для меня действительно раздражает. В моем проекте я использую обнаружение источников, то есть все, что находится в каталоге sr c, добавляется к источникам. Затем, если я хочу скомпилировать модульный тест (make this_unit_test), он фактически собирается скомпилировать каждый файл .o в моем исходном каталоге вместо компиляции только необходимых файлов. Это означает, что если что-то не встраивается в часть моего проекта, я не могу больше строить тесты.

Что я могу сделать?

Если CMake действительно сделан так, как вы нужно указать себе минимальные зависимости для любого исполняемого файла, как я могу все еще использовать автоматическое c обнаружение источника / теста? Лучшее решение было бы из файла CMakeList, функции, которая берет список исходных файлов и возвращает его подмножество, соответствующее тому, что фактически включено в некоторый момент файлом, содержащим main. Что люди делают, чтобы решить эту проблему?

1 Ответ

4 голосов
/ 29 апреля 2020

Нет, CMake не сканирует минимальные исходные зависимости для вашего исполняемого файла, и как это может? CMake не сканирует исходные файлы и не знает, что включает / определяет ваш исполняемый файл, в конечном счете, нужен или не нужен. Эта функциональность должна была появиться на этапе компиляции (после завершения CMake), потому что это препроцессор / компилятор, который анализирует ваши исходные файлы и интерпретирует их для семантики (значения). Существуют стандартные инструменты анализа c, которые могут помочь в достижении чего-то подобного, например include-what-you-use .

Использование методов обнаружения источника методов в CMake (например, file(GLOB ...)) может быть ошибка:

  1. Как вы уже видели, механизм обнаружения источника может захватывать файлы, которые вам не нужны для построения конкретной цели.
  2. Еще хуже, обнаружение источника может пропустить файлов, которые необходимы для построения конкретной цели.

Документация CMake сама даже предупреждает против этого!

Примечание: Мы не рекомендуем использовать GLOB для сбора список исходных файлов из вашего исходного дерева. Если файл CMakeLists.txt не изменяется при добавлении или удалении источника, сгенерированная система сборки не может знать, когда запросить CMake для регенерации.

Как общее практическое правило, всегда безопаснее всего перечислить каждый отдельный файл, который требуется для каждой цели явно , например:

add_executable(MyExe 
    main.c
    MyHelperFunctions.c
    MyOtherStructs.c
)
...