aboutsummaryrefslogtreecommitdiff
path: root/cmake/modules/TestSuite.cmake
blob: ca037c7f82e6fafc4a4ca2e23f2dd60a8a5f8c12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
##===- TestSuite.cmake ----------------------------------------------------===##
#
# Defines helper functions to build benchmarks and the corresponding .test files
#
##===----------------------------------------------------------------------===##
include(TestFile)
include(CopyDir)

# Copies files and directories to be used as benchmark input data to the
# directory of the benchmark executable.
# Paths are interepreted relative to CMAKE_CURRENT_SOURCE_DIR by default but
# this can be changed with the SOURCE_DIR argument.
function(llvm_test_data target)
  cmake_parse_arguments(_LTDARGS "MUST_COPY" "SOURCE_DIR" "" ${ARGN})
  set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
  if(_LTDARGS_SOURCE_DIR)
    set(SOURCE_DIR ${_LTDARGS_SOURCE_DIR})
  endif()
  foreach(file ${_LTDARGS_UNPARSED_ARGUMENTS})
    set(full_path ${SOURCE_DIR}/${file})
    if(_LTDARGS_MUST_COPY)
      if(IS_DIRECTORY ${full_path})
        llvm_copy_dir(${target} $<TARGET_FILE_DIR:${target}>/${file} ${full_path})
      else()
        llvm_copy(${target} $<TARGET_FILE_DIR:${target}>/${file} ${full_path})
      endif()
    else()
      get_filename_component(file_subdir ${file} DIRECTORY)
      if(file_subdir)
        llvm_make_directory(${target} ${file_subdir})
      endif()
      llvm_create_symlink(${target} $<TARGET_FILE_DIR:${target}>/${file} ${full_path})
    endif()
  endforeach()
endfunction()

# Creates a new executable build target. Use this instead of `add_executable`.
# It applies CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS. Creates a .test file if
# necessary, registers the target with the TEST_SUITE_TARGETS list and makes
# sure we build the required dependencies for compiletime measurements
# and support the TEST_SUITE_PROFILE_USE mode.
function(llvm_test_executable target)
  add_executable(${target} ${ARGN})
  append_target_flags(COMPILE_FLAGS ${target} ${CFLAGS})
  append_target_flags(COMPILE_FLAGS ${target} ${CPPFLAGS})
  append_target_flags(COMPILE_FLAGS ${target} ${CXXFLAGS})
  # Note that we cannot use target_link_libraries() here because that one
  # only interprets inputs starting with '-' as flags.
  append_target_flags(LINK_LIBRARIES ${target} ${LDFLAGS})
  set(target_path ${CMAKE_CURRENT_BINARY_DIR}/${target})
  if(TEST_SUITE_PROFILE_USE)
    append_target_flags(COMPILE_FLAGS ${target} -fprofile-instr-use=${target_path}.profdata)
    append_target_flags(LINK_LIBRARIES ${target} -fprofile-instr-use=${target_path}.profdata)
  endif()

  set_property(GLOBAL APPEND PROPERTY TEST_SUITE_TARGETS ${target})
  llvm_add_test(${CMAKE_CURRENT_BINARY_DIR}/${target}.test ${target_path})
  test_suite_add_build_dependencies(${target})
  set(TESTSCRIPT "" PARENT_SCOPE)
endfunction()

# Creates a new library build target. Use this instead of `add_library`.
# Behaves like `llvm_test_executable`, just produces a library instead of an
# executable.
function(llvm_test_library target)
  add_library(${target} ${ARGN})

  append_target_flags(COMPILE_FLAGS ${target} ${CFLAGS})
  append_target_flags(COMPILE_FLAGS ${target} ${CPPFLAGS})
  append_target_flags(COMPILE_FLAGS ${target} ${CXXFLAGS})
  # Note that we cannot use target_link_libraries() here because that one
  # only interprets inputs starting with '-' as flags.
  append_target_flags(LINK_LIBRARIES ${target} ${LDFLAGS})

  # TODO: How to support TEST_SUITE_PROFILE_USE properly?

  test_suite_add_build_dependencies(${target})
endfunction()

# Add dependencies required for compiletime measurements to a target. You
# usually do not need to call this directly when using `llvm_test_executable`
# or `llvm_test_library`.
function(test_suite_add_build_dependencies target)
  add_dependencies(${target} build-timeit build-timeit-target build-fpcmp)
endfunction()

# Internal function that transforms a list of flags to a string and appends
# it to a given property of a target.
function(append_target_flags propertyname target)
  if(NOT "${ARGN}" STREQUAL "")
    get_target_property(old_flags ${target} ${propertyname})
    if(${old_flags} STREQUAL "old_flags-NOTFOUND")
      set(old_flags)
    endif()
    # Transform ${ARGN} which is a cmake list into a series of commandline
    # arguments. This requires some shell quoting (the approach here isn't
    # perfect)
    string(REPLACE " " "\\ " quoted "${ARGN}")
    string(REPLACE "\"" "\\\"" quoted "${quoted}")
    string(REPLACE ";" " " quoted "${quoted}")
    # Ensure that there is no leading or trailing whitespace
    # This is especially important if old_flags is empty and the property
    # is LINK_LIBRARIES, as extra whitespace violates CMP0004
    string(STRIP "${old_flags} ${quoted}" new_flags)
    set_target_properties(${target} PROPERTIES ${propertyname} "${new_flags}")
  endif()
endfunction()