In CTest, why is the variable argument to my function not set? - cmake

I have a CTestList.cmake file containing this function definition and call:
function(add_test_r testname )
add_test(
${testname} python executeRegressionTestCase.py ${testname}
)
endfunction(add_test_r)
add_test_r(Test01)
I need to support testing through CMake directly, cmake ..; make test, and through CTest without running CMake first. When CMake builds the test target and I run make test, the function above executes fine. However, when I run the same file with CTest, ${testname} is empty. Are function variables not supported in CTestList when running with CTest or is there something I'm missing?

I don't have a definitive answer, but after some testing it looks like CMake does a preprocessing step for the input files. Specifically, it reads in CTestList.cmake, evaluates the variables and functions, and generates an "expanded" CTestTestfile.cmake. Running CTest with a steering script does not run the preprocessing step so the variables and functions are not expanded. A few people on the internet have suggested that the CTestTestfile.cmake used in the steering script should be generated by CMake in the first place. Unfortunately, thats not the use case I'm looking for, but it may help someone else with running into this problem.

Related

googletest - command line option to execute "the first, the second, etc"

I'm using gcov and I'd like to gather coverage results on a per test case basis.
QUESTION
When I execute the googletest executable, is it possible to pass in an argument on command line that says execute only the Nth test case?
I'd even be ok with passing in the name of the fixture+case; I can just use Python with regex to pull out all the tests.
Obviously I can accomplish the same thing by having one test case per .cpp file but that sounds ... stupid.
googletest allows to run a single test case or even the subset of the tests. You can specify a filter string in the GTEST_FILTER environment variable or in the --gtest_filter command line option and googletest will only run the tests whose full names (in the form of TestSuiteName.TestName) match the filter. More information about the format of the filter string can be found in Running a Subset of the Tests section. Also googletest supports --gtest_list_tests command line option to print the list of all test cases. It can be useful in your case.

Add variables defined in a list to add_compile_definitions() using cmake

I have a list of vars definedinside a cmake which is called using from main CMakeLists.txt:
add_custom_target(gen_a
COMMAND ${CMAKE_COMMAND} -P "gen_sigs.cmake"
)
add_dependencies(${PROJECT_NAME} gen_a)
My gen_sigs.cmake:
set(SIG_LIST SIGNAL_A=0 SIGNAL_B=1 SIGNAL_C=0 )
I want to use this list to add preprocessor definitions to the compiler command line like (in main CMakeLists.txt):
add_compile_definitions(
SIGNAL_A=0
SIGNAL_B=1
SIGNAL_C=0
)
I tried using the following but it does not work (in main CMakeLists.txt):
add_compile_definitions(
${SIG_LIST}
)
I am new to cmake so any suggestions on how to make this work will be helpful. Also the add_custom_target is defined before the add_compile_definitions() still it doesn't help. My guess is there is some problem with the order of execution because the ${SIG_LIST} has no value when I am printing it in cmakelists.txt. Is there a way to add dependency to add_compile_definitions so that my add_custom_target command gets forcibly executed before the add_compiler_definitions()?
Your question is not very clear, but from what you've shown, the following should work:
include("${CMAKE_CURRENT_SOURCE_DIR}/gen_sigs.cmake")
target_compile_definitions(main_target PRIVATE ${SIG_LIST})
Adding a custom target defers processing until build time, but what you (appear to) want to do is fundamentally a configure/generation time thing. include() will cause the external script to be executed in the same scope as the call, immediately.

Running a python script as part of a cmake build

I'm using cmake for the first time and am just not having luck finding examples that help me figure out what I'm doing wrong. The functionality seems very basic, but nothing I've tried thus far has given me any meaningful output or error.
I have a PRELOAD command for a document, and this works fine as long as the document has already been created.
set(variable_name
PRELOAD ${_source_directory}/Documents/output.txt AS output.txt
)
But I want the document generation(which is accomplished via a python script) to be part of the cmake build process as well. The command I want to run is
python_script.py ${_source_directory}/Documents/input.txt
${_source_directory}/Documents/output.txt
and I want that to run before the PRELOAD statement is executed.
Here's an example of what I've tried
add_custom_command(
OUTPUT ${_source_directory}/Documents/output.txt
COMMAND python_script.py ${_source_directory}/Documents/input.txt
${_source_directory}/Documents/output.txt
)
set(variable_name
PRELOAD ${_source_directory}/Documents/output.txt AS output.txt
)
But that gives me the same error as if the add_custom_command wasn't even there ("No rule to make target ${_source_directory}/Documents/output.txt").
You do/understand it wrong. As it was mentioned in comments set() has nothing like PRELOAD.
The correct way is to use add_custom_target() which would produce an output.txt in desired directory and then add_dependencies() for target you want to build and which would use the output.txt.

Proper way to call a found executable in a custom command?

I have a program on my computer, let's say C:/Tools/generate_v23_debug.exe
I have a FindGenerate.cmake file which allows CMake to find that exact path to the executable.
So in my CMake code, I do:
find_program(Generate)
if (NOT Generate_FOUND)
message(FATAL_ERROR "Generator not found!")
So CMake has found the executable. Now I want to call this program in a custom command statement. Should I use COMMAND Generator or COMMAND ${GENERATOR_EXECUTABLE}? Will both of these do the same thing? Is one preferred over the other? Is name_EXECUTABLE a variable that CMake will define (it's not in the FindGenerate.cmake file), or is it something specific to someone else's example code I'm looking at? Will COMMAND Generator be expanded to the correct path?
add_custom_command(
OUTPUT blahblah.txt
COMMAND Generator inputfile1.log
DEPENDS Generator
)
find_program stores its result into the variable given as a first argument. You can verify this by inserting some debug output:
find_program(GENERATOR Generate)
message(${GENERATOR})
Note that find_program does not set any additional variables beyond that. In particular, you mentioned Generate_FOUND and GENERATOR_EXECUTABLE in your question and neither of those gets introduced implicitly by the find_program call.
The second mistake in your program is the use of the DEPENDS option on the add_custom_command. DEPENDS is used to model inter-target dependencies at build time and not to manipulate control flow in the CMakeLists. For example, additional custom command can DEPEND on the output of your command (blahblah.txt), but a custom command cannot DEPEND on the result of a previous find operation.
A working example might look something like this:
find_program(GENERATOR Generate)
if(NOT GENERATOR)
message(FATAL_ERROR "Generator not found!")
endif()
add_custom_command(
OUTPUT blahblah.txt
COMMAND ${GENERATOR} inputfile1.log
)
P.S.: You asked why the code examples were not properly formatted in your question. You indented everything correctly, but you need an additional newline between normal text and code paragraphs. I edited your question accordingly.

Cmake with fruit tests

I have a project that uses fruit for testing (fortran code).
This is my code.
calculator.f90
module calculator
implicit none
contains
subroutine add (a, b, output)
integer, intent(in) :: a, b
integer, intent(out):: output
output = a+b
end subroutine add
end module calculator
And my test calculator_test.f90
module calculator_test
use fruit
contains
subroutine test_5_2_2
use calculator, only: add
integer :: result
call add(2,2,result)
call assertEquals(4,result)
end subroutine test_5_2_2
subroutine test_5_2_3
use calculator, only: add
integer :: result
call add(2,3,result)
call assertEquals(5,result)
end subroutine test_5_2_3
end module
Now I'd like to use Cmake to build and run my tests (triggered by jenkins), so my question is: Do I need to change the tests or is it possible to just run the test I've written through cmake, and if so how?
I've searched a lot online but all testing with cmake seems to be done with c++ and then by using executeable testfiles files.
Thanks!
-Minde
You can run the tests you have written as is, you just need to tell CMake how to run them. This is what the COMMAND argument to ADD_TEST is for.
ENABLE_TESTING()
ADD_TEST(NAME "YourTest"
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND ${TEST_DIRECTORY}/test_dim)
Usually, you see some example like the one above, where the command is an executable (as you have seen in c++ examples). But it doesn't have to be. For example, I am running python tests through CMake, and I add the test like so:
ADD_TEST(NAME PythonTests
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND ${PYTHON_EXECUTABLE} setup.py test
So, to run your Fruit tests, you would call the command that creates the Fruit test runner for you (I believe it is a rake command... I will assume this is true below, but you should substitute for whatever you actually call on the command line to run your tests):
ADD_TEST(NAME FruitTests
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND rake test) # Or whatever the command is.
When you run make test on the command line, it should tell you if "FruitTests" failed or succeeded.
A word of caution CMake determines the success or failure of the test by the exit code of the program. By default Fortran programs do not have a exit code (or if they do, it is always 0). When I use Fruit and CMake to do my Fortran tests, I write the test runner myself and use the call exit(exit_code) builtin subroutine to make sure an exit code is returned to CMake. I am not sure if Fruit's automatic test runner creator does this; you will have to verify this yourself.