Правило cmake, которое зависит от вывода команды - PullRequest
0 голосов
/ 11 июня 2019

Как сгенерировать исходные файлы на этапе предварительной сборки, если и только если они должны быть восстановлены?

Одной из зависимостей моего проекта является библиотека (libfoo), которую дорого связать (несколькоминут) и даже дороже на восстановление (менее часа).Генерация исходных файлов для этой зависимости стоит недорого (несколько секунд), но использование устаревших источников сделает бесполезным полученный набор приложений.У меня есть команда check_foo.sh, которая будет выходить с ненулевым статусом, когда источники должны быть восстановлены, но я не смог определить, как убедить CMake запускать check_foo.sh во время каждой сборки и только перестраивать libfooкогда check_foo.sh возвращает ненулевое значение.

При попытке создать простое доказательство самое близкое, что я получил, заключается в следующем, хотя generate_foo_if.sh запускается только один раз.Конечная цель состоит в том, что generate_foo_if.sh запускается безоговорочно, но libfoo перестраивается только тогда, когда generate_foo_if.sh изменяет foo.cpp.

CMakeLists.txt

cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(my_project
        VERSION 1.0.0.0
        LANGUAGES CXX)
add_custom_command(OUTPUT foo.cpp
                   COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/generate_foo_if.sh" "${CMAKE_CURRENT_BINARY_DIR}/foo.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/check_foo.sh"
                   WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
                   COMMENT "Generating foo.cpp..."
                  )
add_library(foo STATIC foo.cpp)
add_executable(main main.cpp)
target_link_libraries(main foo)

main.cpp

#include "foo.hpp"
int main(int,char**){
    return foo::exit_status;
}

foo.hpp

#pragma once
namespace foo {
extern const int exit_status;
}

check_foo.sh

#!/usr/bin/env bash
exit $(((${RANDOM} % 2 )))

generate_foo_if.sh

#!/usr/bin/bash
CHECK=${2:-./check_foo.sh}
if [ ${CHECK} -eq 0 ]; then
    exit 0
fi
msg=$(cat <<__EOF
#include "foo.hpp"
namespace foo {
const int exit_status = 1;
}
__EOF
)
echo "${msg}" >${1:-foo.cpp}

1 Ответ

0 голосов
/ 12 июня 2019

Оказывается, я был не очень далеко от цели.

Кажется, что критическое различие заключается в создании пользовательской цели, а не пользовательской команды, с использованием BYPRODUCTS вместо OUTPUT, иявно добавив зависимость.Обновленный файл CMakeLists.txt находится ниже и приводит к желаемому поведению (то есть libfoo восстанавливается только в том случае, если оно должно быть).

cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(my_project
    VERSION 1.0.0.0
    LANGUAGES CXX)
add_custom_target(generate_foo
              COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/generate_foo_if.sh"  "${CMAKE_CURRENT_BINARY_DIR}/foo.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/check_foo.sh"
              WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
              BYPRODUCTS foo.cpp
             )
add_library(foo STATIC foo.cpp)
add_dependencies(foo generate_foo)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
add_executable(main main.cpp)
target_link_libraries(main foo)

Хотя я не могу сказать, что знаю почему это работает, это делает то, что я хочу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...