CMake как правильно добавить файлы в качестве ресурсов?
Я пытаюсь сделать приложение с тестами (Google tests, но дело не в тестах) и для тестов решил создать тестовые данные, которые хотел бы прикрепить в качестве ресурсов. Компилирую проект с помощью CMake, сам проект на С++. Как правильно прописать в CMake добавление файла ресурсов? Сейчас я прописываю файл тем способом что представлен ниже и ниже же функция проверки чтения файла которую я использую, но вот беда, файл не хочет читаться. Если что то неверно делаю, то прошу указать, ранее не добавлял файлы подобным способом, для меня это несколько ново.
Структура директорий следующая:
project/
|
*-- CMakeLists.txt
|
*-- Expert Librariy/
| |
| *-- Tests/
| | \-- CMakeLists.txt
| |
| \-- CMakeLists.txt
|
\-- Resources/
\-- Test_MA_Std.csv
project/CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.2)
file(GLOB RESOURCE_FILES "Resourses/*")
message(${RESOURCE_FILES})
add_subdirectory(Expert\ Library)
project/Expert Librariy/CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.2)
add_subdirectory(Expert)
add_subdirectory(Tests)
project/Expert Librariy/Tests/CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.2)
project(Expert_tests)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../Expert/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g")
file(GLOB CPPS "src/*.cpp"
CPPH "include/*h")
add_executable(${PROJECT_NAME} ${CPPS} ${CPPH} ${RESOURCE_FILES})
target_link_libraries(${PROJECT_NAME}
lib::gtest
lib::Bonds_knifes
)
set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE ${RESOURCE_FILES})
Структуру директорий описал не полностью а лишь ту где лежат интересующие меня файлы. Файлы CMake через которые компилирую проект - приложил полностью что бы не было не каких недоговорок. Функция которая пытается прочесть файл и ее вызов - следующие:
struct file_closer {
constexpr file_closer() noexcept = default;
void operator()(std::ifstream* __ptr) const {
if(__ptr->is_open())
__ptr->close();
delete __ptr;
}
};
void read_file(std::string file_name) {
std::unique_ptr<std::ifstream,file_closer> file(new std::ifstream(file_name));
if (file->is_open()) {
std::cout << "File was opened\n";
}
else {
std::cout << "CAN`T OPEN FILE\n";
}
}
int main() {
read_file("Test_Ma_Std.csv");
return 0;
}
Прошу напишите где я сделал ошибку или же свои соображения. Если я указываю полностью путь к файлу - то чтение происходит, так что дело точно не в С++ коде, как я понимаю файл просто не добавляется в качестве ресурса. Заранее благодарю.
Ответы (3 шт):
Думаю вы все слишком усложняете: как я понял из вопроса - вам нужно чтобы экзешник открывал какой-то файл, но так как экзешник и файл могут быть в разных директориях, то это проблематично. Если файлы "ресурсов" не планируется перемещать после компиляции (а раз это тест - странно это было бы делать) то для решения этой задачи можно не прибегать к системе ресурсов а использовать функционал cmake. Тобишь в cmake берете абсолютный путь вашего тестового ресурсного файла (можно его даже пере этим скопировать в нужную директорию) и конфигурируете .hpp файл где в соответствующую константу (или define) записываете нужное значение. В результате ваш экзешник, независимо от расположения, всегда будет обращаться к одному и тому же файлу, главное не перемещать (после компиляции) сам файл. Для теста - это вполне себе приличный вариант, хотя для конечной программы, конечно, не годится.
В CMake для тестов есть специальный модуль CTest и команда add_test. Они созданы специально для тестирования кода и предусматривают работу с файлами ресурсов.
Чтобы в вашем случае использовать этот модуль достаточно в файле project/Expert Librariy/Tests/CMakeLists.txt добавить этот код:
enable_testing()
add_test(NAME ${PROJECT_NAME} ${PROJECT_NAME} WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../../Resources")
Этот код создаст новый тест с именем "Expert_tests", который запустит исполняемый файл сгенерированный таргетом "Expert_tests". При этом рабочая директория будет "Resources", так что файл "Test_Ma_Std.csv" будет доступен.
Чтобы запустить тесты нужно выполнить команду ctest внутри директории сгенерированной CMake. Либо же сбилдить таргет RUN_TESTS, который появится в проекте автоматически если используются тесты.
В общем, у меня было время и я сделал свой велосипед. Почти все сделано через генерацию кода с помощью CMake и основано на примере из статьи из LinuxJornal, которую мне скинули в комментариях. Всем спасибо, Ваши ответы помогли. Если вдруг захотите мое решение подправить, то буду благодарен за корректировки.