问题描述
我有一个名为foo的控制台应用程序,它使用一个参考文本文件作为输入(in.txt),并在标准输出中生成文本(我想保持这种行为)。
在make(不是cmake)中,我使用一个测试目标,它调用foo并将输出重定向到一个文件(out.txt),如下所示。然后,我使用diff来比较文件out.txt与预期的参照(ref.txt)
test:
./foo -a test / in.txt> test / out.txt
diff test / out.txt test / ref.txt
使用make工作良好。现在我的问题是; 如何使用cmake创建一个类似的Makefile?
我在一个名为build的子目录中尝试了
project(foo)
...
add_test(NAME test1 COMMAND ./foo ../test/in.txt>。 ./test/out.txt)
enable_testing()
使用cmake 3.5版本得到一个没有错误的Makefile,但是当我调用 make test
时,测试本身失败。看起来cmake命令 add_test
支持命令行参数,但不支持重定向。我试着报价,逃避失败的成功。因为我不能通过这部分,我没有尝试使用diff。我只是想象,我可以打包foo和diff在一行使用&你可以用bash做。
将我的评论转换为答案 b
$ b
正如@Tsyvarev所说,CTest命令不在shell的上下文中运行。但你可以只添加需要自己的shell和使用例如。 sh
作为要使用 add_test()
调用的命令。
我使用您的示例代码运行了一些测试,并且以下操作成功:
add_test(NAME test1 COMMAND sh -c$< TARGET_FILE:foo> ../test/in.txt> ../test/out.txt)
此解决方案不是平台无关的(它取决于在搜索路径中可用的 sh
)。
因此,如果你想要更灵活,你可以这样做:
include(FindUnixCommands)
档案(TO_NATIVE_PATH$ {CMAKE_CURRENT_SOURCE_DIR} /test/in.txt_in)
档案(TO_NATIVE_PATH) $ {CMAKE_CURRENT_SOURCE_DIR} /test/out.txt_out)
if(BASH)
add_test(
NAME test1
COMMAND $ {BASH} -c$< TARGET_FILE :foo> $ {_ in}> $ {_ out}
)
else()
if(WIN32)
add_test(
NAME test1
COMMAND $ {CMAKE_COMMAND} -E chdir $< TARGET_FILE_DIR:foo> $ ENV {ComSpec} / c$< TARGET_FILE_NAME:foo> $ {_ in}> $ {_ out}
)
else()
message(FATAL_ERROR$ {CMAKE_HOST_SYSTEM_NAME}的未知shell命令)
endif()
endif()
此外,还可以执行更多平台独立 diff
与 $ {CMAKE_COMMAND} -E compare_files< file1> < file2>
。所以你可以简化你在CMake中完整的基于makefile的示例:
add_custom_command(
TARGET foo
POST_BUILD
COMMAND $ {CMAKE_COMMAND} -E echoRunning $< TARGET_FILE_NAME:foo> ...
COMMAND foo in.txt> out.txt
WORKING_DIRECTORY $ {CMAKE_CURRENT_SOURCE_DIR} / test
)
add_test(
NAME test1
COMMAND $ {CMAKE_COMMAND} -E compare_files in.txt out.txt
WORKING_DIRECTORY $ {CMAKE_CURRENT_SOURCE_DIR} / test
)
参考
I have a console application called "foo", which takes a reference text file as input (in.txt) and generates text at standard output (I want to keep this behaviour).
In make (not cmake), I use a test target, which calls foo and redirects the output to a file (out.txt) as follows. Then, I use diff to compare the file out.txt with the expected refernece (ref.txt)
test:
./foo -a test/in.txt > test/out.txt
diff test/out.txt test/ref.txt
This works fine using make. Now my question is; how can I use cmake to create a similar Makefile?
From within a subdrectory called build, I tried
project(foo)
...
add_test(NAME test1 COMMAND ./foo ../test/in.txt > ../test/out.txt)
enable_testing()
Using cmake version 3.5, I get a Makefile without errors, but when I call make test
, the test itself fails. It seems the cmake command add_test
supports command line arguments, but not the redirection. I tried quotes and escaping witout success. Since I could not pass this part, I didn't try to use diff. I just imagine that I could pack foo and diff in one line using & as you can do with bash. That would be the second step.
Turning my comment into an answer
As @Tsyvarev has stated, CTest commands are not run in a shell's context. But you could just add the shell needed yourself and use e.g. sh
as the command to be called with add_test()
.
I've run some tests with your example code and the following did work successfully:
add_test(NAME test1 COMMAND sh -c "$<TARGET_FILE:foo> ../test/in.txt > ../test/out.txt")
This solution is not platform independent (it depends on sh
to be available in the search paths).
So if you want to be more flexible you could do something like:
include(FindUnixCommands)
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/test/in.txt" _in)
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/test/out.txt" _out)
if (BASH)
add_test(
NAME test1
COMMAND ${BASH} -c "$<TARGET_FILE:foo> ${_in} > ${_out}"
)
else()
if (WIN32)
add_test(
NAME test1
COMMAND ${CMAKE_COMMAND} -E chdir $<TARGET_FILE_DIR:foo> $ENV{ComSpec} /c "$<TARGET_FILE_NAME:foo> ${_in} > ${_out}"
)
else()
message(FATAL_ERROR "Unknown shell command for ${CMAKE_HOST_SYSTEM_NAME}")
endif()
endif()
Additionally there is the possibility to execute a more platform independent diff
with ${CMAKE_COMMAND} -E compare_files <file1> <file2>
. So you could simplify your complete makefile based example in CMake with:
add_custom_command(
TARGET foo
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Running $<TARGET_FILE_NAME:foo> ..."
COMMAND foo in.txt > out.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test
)
add_test(
NAME test1
COMMAND ${CMAKE_COMMAND} -E compare_files in.txt out.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test
)
References
- Integrate bash test scripts in cmake
- CMake: piping commands to executable
- cmake: make tests successfully passing part of the build process
这篇关于如何在cmake add_test中使用重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!