Скрытый mkdir
шаг ExternalProject
(от которого все другие шаги прямо или косвенно зависят) всегда пытается создать полный набор каталогов, даже если они не будут использоваться.Вы можете увидеть это здесь .Для справки, он делает это:
ExternalProject_Add_Step(${name} mkdir
COMMENT "Creating directories for '${name}'"
COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
)
Местоположение установки по умолчанию в системах Unix, вероятно, будет /usr/local
, поэтому, если у вас нет разрешения на запись во все каталоги, которые он пытается создать, то это может быть связано с вашей проблемой.Я предлагаю вам проверить разрешения каждого из этих мест и убедиться, что они уже существуют или доступны для записи.В качестве альтернативы вы можете указать каталог установки, который является локальным для дерева сборки, так что даже если он не будет использоваться, он, по крайней мере, всегда будет создаваться (см. Пример ниже).
Если вы используете ниндзя, он будет более строгим в проверке зависимостей, чем make.target-ep
выполняет загрузку, которая обеспечивает libwhatever.a
, поэтому вам нужно BUILD_BYPRODUCTS
, чтобы сообщить Ninja, что target-ep
- это то, что создает этот файл.Как вы узнали, если вы этого не сделаете, target-imp
укажет на библиотеку, которая изначально не существует, и ниндзя справедливо жалуется на то, что она отсутствует, и не знает, как ее создать.Если вы предоставляете BUILD_BYPRODUCTS
, то имеет смысл, что шаг сборки не должен быть пустым, поэтому вам, вероятно, нужно сделать что-то как шаг сборки, даже если это просто BUILD_COMMAND
, который на самом деле ничего не делает значащим.
Следующее измененное определение target-ep
должно заставить вас работать:
ExternalProject_Add(target-ep
INSTALL_DIR ${CMAKE_CURRENT_BUILD_DIR}/dummyInstall
DOWNLOAD_COMMAND <whatever>
BUILD_BYPRODUCTS /path/to/install/lib/libwhatever.a
BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append
INSTALL_COMMAND ""
CONFIGURE_COMMAND "")
Ваш исходный вопрос также создает зависимость от неверной цели.target-imp
должно зависеть от target-ep
, но вместо этого target
зависит от target-ep
.Правильная зависимость может быть выражена следующим образом:
add_dependencies(target-imp target-ep)
С опцией BUILD_BYPRODUCTS
Ninja уже знает вышеуказанную зависимость, но она необходима для других генераторов, включая make.
YouЯ не указал, что делает ваша команда <whatever>
download, но я предполагаю, что она отвечает за то, чтобы библиотека существовала на /path/to/install/lib/libwhatever.a
, когда она будет выполнена.Вы также можете попробовать заполнить DOWNLOAD_COMMAND
пустым и вместо него ввести <whatever>
в качестве BUILD_COMMAND
.
Чтобы ответить на ваши конкретные вопросы:
- Возможно ли это ввсе с ниндзя и CMake?(Версия не является проблемой, я могу использовать последний CMake, если это решит проблему)
Да, я проверил, что упомянутый выше подход работает с Ninja 1.8.2 для фиктивного тестапроект на macOS с использованием CMake 3.11.0.Я ожидаю, что он будет работать с CMake 3.2 или более поздней версии (именно тогда была добавлена поддержка опции BUILD_BYPRODUCTS
).
Если есть какой-то способ обхода с явным перечислением BUILD_BYPRODUCTS, есть ли способ просто сообщить, что весь каталог, который будет установлен, является побочным продуктом?То есть / path / to / install / * является побочным продуктом?
Маловероятно.Откуда ниндзя узнает, что ожидается в таком каталоге?Единственный способ получить надежные зависимости - это явно перечислить каждый ожидаемый файл, что вы и делаете, используя BUILD_BYPRODUCTS
в вашем случае.