【问题标题】:Cmake - How to copy files with input data to build output folderCmake - 如何使用输入数据复制文件以构建输出文件夹
【发布时间】:2017-10-09 12:34:32
【问题描述】:

我正在使用 CLion 和 CMake 进行项目构建。我已经创建了 Google Test 构建配置,我的项目树如下所示:

tokenizer 的测试很简单:tokenizer 应该打开源文件并输出令牌。

这是我用于 tokenizer_test 的 CMakeLists.txt 文件:

include_directories(${gtest_SOURCE_DIRS}/include ${gtest_SOURCE_DIRS})
add_subdirectory(test_src)
add_executable(run_tokenizer_tests
    tokenizer_test.cpp ${CMAKE_SOURCE_DIR}/includes/tokenizer.h
    ${CMAKE_SOURCE_DIR}/src/tokenizer.cpp
)

target_link_libraries(run_tokenizer_tests gtest gtest_main) 

我是否可以将测试源(如图片上的 0.cpp)放置在可执行文件附近,还是应该编写自己的测试脚本?我该怎么做?

【问题讨论】:

  • 看看CMake variables。有一些为您提供了可用于测试的项目和源目录(通过在构建时将它们添加为宏,或在运行测试时作为参数传递)。
  • @Someprogrammerdude,不幸的是,我没有找到,所以我写了这个。
  • @ДмитрийТерехов “测试源”是什么意思,“0.cpp”到底包含什么? tokenizer_tests 的输入数据?
  • @Liastre 它是分词器的来源。 Tokenizer 获取源文件并输出找到的标记(词位)。
  • 您的分词器希望如何接收输入?

标签: c++ c cmake clion ctest


【解决方案1】:

您可以拨打file(COPY source DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

有关其他变量,请参阅 https://cmake.org/Wiki/CMake_Useful_Variables

这是我们项目中的 sn-p,它执行此操作以及其他功能。

总的来说,这个 sn-p 允许您避免对文件系统上特定文件位置的依赖,前提是您的构建目录是活动的,因为文件路径将在您的单元测试中被硬编码。

它简化了自动构建和检查 - 无需在调用测试运行程序之前跟踪 cd 的位置。

它还提高了单元测试中代码的可读性。

CMakeLists.txt:

# list all test images

set(test_data

    orig_5_15Fps_3_27.png
    orig_5_15Fps_5_34.png
    ....
)

# Loop over all items in the "test_data" list
# Copy PNG, JPEG and BMP images to the directory, where test binaries are created
# And generate full paths to them for hardcoding in the include file test_config.h

foreach(df ${test_data})

    # copy images to build dir

    if(${df} MATCHES "((jp|pn)g|bmp)$")
        file(COPY ${df} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})   
        set(df_file_path ${CMAKE_CURRENT_BINARY_DIR}/${df})
    else()
        set(df_file_path ${CMAKE_CURRENT_SOURCE_DIR}/${df}) 
    endif()

    # generate some C++ code in CMake variables IMAGE_PATHS and IMAGE_IDS
    # (see below)

    if (NOT IMAGE_PATHS)
        set(IMAGE_PATHS "    \"${df_file_path}\"")
    else()
        set(IMAGE_PATHS "${IMAGE_PATHS},\n    \"${df_file_path}\"")
    endif()

    string(REGEX REPLACE "[^a-zA-Z0-9]" "_" df_id ${df})

    if (NOT IMAGE_IDS)
        set(IMAGE_IDS "    img_${df_id}")
    else()
        set(IMAGE_IDS "${IMAGE_IDS},\n    img_${df_id}")
    endif()
endforeach()

set(TEST_PATH \"${CMAKE_CURRENT_BINARY_DIR}\")

configure_file(test_config.h.in test_config.h @ONLY)  # see below for test_config.h.in 

...
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )   # make test_config.h visible for compiler
add_executable (some_unit_test some_unit_test.cpp)
add_test(NAME some_unit_test COMMAND some_unit_test WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
 ... 
add_executable ( ... )
add_test(  ... )
...

文件test_config.h.in

/* DO NOT EDIT THIS FILE, IT IS AUTOGENERATED!
   All your changes will be overwritten.

   If you want to add new test data files, 
   add them to the `test_data` list in file CMakeLists.txt
*/ 

#ifndef __TEST_CONFIG_H__
#define __TEST_CONFIG_H__

const char* test_path = @TEST_PATH@; //!< full path to test data, without trailing slash

//! full paths to all test images
const char* image_paths[] = {
    @IMAGE_PATHS@
};

enum image_ids { //!< test file names, converted to enum constants
    @IMAGE_IDS@
};

#endif

调用configure_file@TEST_PATH@@IMAGE_PATHS@@IMAGE_IDS@ 替换为它们的值。

这是构建目录中配置文件test_config.h 的样子。

/* DO NOT EDIT THIS FILE, IT IS AUTOGENERATED!
   All your changes will be overwritten.

   If you want to add new test data files, 
   add them to the `test_data` list in file CMakeLists.txt
*/ 

#ifndef __TEST_CONFIG_H__
#define __TEST_CONFIG_H__

const char* test_path = "F:/projects/project/build64/test"; //!< full path to test data, without trailing slash


//! full paths to all test images
const char* image_paths[] = {
  "F:/projects/project/build64/test/orig_5_15Fps_3_27.png",
  "F:/projects/project/build64/test/orig_5_15Fps_5_34.png",
   ... 
};

enum image_ids { //!< test file names, converted to enum constants
    img_orig_5_15Fps_3_27_png,
    img_orig_5_15Fps_5_34_png,
...
};

#endif

在测试中使用:

#include "test_config.h"
....     
img0 = cv::imread(image_paths[img_orig_5_15Fps_3_27_png], cv::IMREAD_GRAYSCALE);

enum image_ids 用于image_paths 数组中的可读索引。恕我直言,它比image_paths[0] 好得多,因为它清楚地显示了读取的图像。

【讨论】:

    【解决方案2】:

    您可以使用带有COPYONLY 标志的configure_file CMake 函数。它将复制文件而不替换任何变量引用或其他内容。你的CMakeLists.txt 靠近tokenizer_test.cpp 应该包含:

    configure_file(test_src/0.cpp 0.cpp COPYONLY)
    

    PS:我建议你根据你正在做的测试重命名每个源文件和输入文件,在你的情况下0.cpp应该被命名为tokenizer_test_parse_input.cpp,最好把这个文件放在`tokenizer_test附近.cpp”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2017-08-24
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多