blob: ebbb1e0ddbd6b8cdb3d015bb709b040a7f185ef2 [file] [log] [blame]
##===- SingleMultiSource.cmake --------------------------------------------===##
#
# Defines helpers to add executables and tests. The entry points to this
# file are:
# `llvm_singlesource()` and
# `llvm_multisource()`
#
# Each is a macro that uses the environment it was called in to determine
# what to build and how, and generates a test file that can be given to LIT.
# The test file is generated at configure time.
#
##===----------------------------------------------------------------------===##
# get_unique_exe_name - Given a source file name after which a test should be
# named, create a unique name for the test. Usually this is just the source file
# with the suffix stripped, but in some cases this ends up causing duplicates
# so attempt to make each unique (by adding pathname segments until they become
# unique).
#
# FIXME: Swap this with a simpler procedure to just append a numeral
set_property(GLOBAL PROPERTY registered_executables)
function(get_unique_exe_name new_name main_src)
get_property(registered_executables GLOBAL PROPERTY registered_executables)
string(REGEX REPLACE ".[cp]+$" "" path ${main_src})
string(REGEX REPLACE ".*/" "" name ${path})
list(FIND registered_executables ${name} name_idx)
if(${name_idx} EQUAL -1)
set(${new_name} ${name} PARENT_SCOPE)
set_property(GLOBAL APPEND PROPERTY registered_executables ${name})
return()
endif()
# There is a clash. Rename the target. Each time around the loop pull in
# a new path component.
foreach(n RANGE 1 4)
string(REGEX REPLACE ".*/([^/]+/${name})" "\\1" name ${path})
string(REGEX REPLACE "/" "-" safe_name ${name})
list(FIND registered_executables ${safe_name} name_idx)
if(${name_idx} EQUAL -1)
set(${new_name} ${safe_name} PARENT_SCOPE)
set_property(GLOBAL APPEND PROPERTY registered_executables ${safe_name})
return()
endif()
endforeach()
message(FATAL_ERROR "Failed to uniquify executable name!")
endfunction()
# append_cflags - add flags to the CFLAGS for target.
macro(append_cflags target flags)
if(NOT "${${flags}}" STREQUAL "")
get_target_property(old_cflags ${target} COMPILE_FLAGS)
if(${old_cflags} STREQUAL "old_cflags-NOTFOUND")
set(old_cflags)
endif()
string(REPLACE ";" " " s "${old_cflags};${${flags}}")
set_target_properties(${target} PROPERTIES COMPILE_FLAGS ${s})
endif()
endmacro()
# append_ldflags - add flags to the LDFLAGS for target.
macro(append_ldflags target flags)
if(NOT "${${flags}}" STREQUAL "")
get_target_property(old_ldflags ${target} LINK_FLAGS)
if(${old_ldflags} STREQUAL "old_ldflags-NOTFOUND")
set(old_ldflags)
endif()
string(REPLACE ";" " " s "${old_ldflags};${${flags}}")
set_target_properties(${target} PROPERTIES LINK_FLAGS ${s})
endif()
endmacro()
# llvm_add_test - Create a .test driver file suitable for LIT.
#
# The test template lives in cmake/lit-test-template.in and is configured by this function.
function(llvm_add_test name exename)
# Fall back to old style involving RUN_OPTIONS and STDIN_FILENAME if
# llvm_test_run() was not called yet.
if(NOT TESTSCRIPT)
if(DEFINED STDIN_FILENAME)
list(APPEND RUN_OPTIONS "< ${STDIN_FILENAME}")
endif()
llvm_test_run(${RUN_OPTIONS})
# Hash if we've been asked to.
if(HASH_PROGRAM_OUTPUT)
llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh %o")
endif()
if(NOT DEFINED PROGRAM_IS_NONDETERMINISTIC)
# Find the reference output file key name.
if(SMALL_PROBLEM_SIZE)
set(KEY small)
elseif(LARGE_PROBLEM_SIZE)
set(KEY large)
else()
set(KEY)
endif()
# Pick the best reference output based on "programname.reference_output".
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${ENDIAN}-endian.${KEY})
set(REFERENCE_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${ENDIAN}-endian.${KEY})
elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${KEY})
set(REFERENCE_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${KEY})
elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${ENDIAN}-endian)
set(REFERENCE_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output.${ENDIAN}-endian)
elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output)
set(REFERENCE_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${name}.reference_output)
else()
message("-- No reference output found for test ${name}")
endif()
set(DIFFPROG ${CMAKE_BINARY_DIR}/tools/fpcmp)
if(DEFINED FP_TOLERANCE)
set(DIFFPROG "${DIFFPROG} -r ${FP_TOLERANCE}")
endif()
if(DEFINED FP_ABSTOLERANCE)
set(DIFFPROG "${DIFFPROG} -a ${FP_ABSTOLERANCE}")
endif()
if(REFERENCE_OUTPUT)
llvm_test_verify("${DIFFPROG} %o ${REFERENCE_OUTPUT}")
endif()
endif()
endif()
# Replace $EXECUTABLE$ placeholder.
string(REPLACE "$EXECUTABLE$" "${CMAKE_CURRENT_BINARY_DIR}/${exename}" TESTSCRIPT "${TESTSCRIPT}")
# Produce .test file
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${exename}.test
CONTENT "${TESTSCRIPT}")
endfunction()
# llvm_singlesource - configure the current directory as a SingleSource subdirectory -
# i.e. every file in *.{c,cpp,cc} is treated as its own test.
macro(llvm_singlesource)
file(GLOB sources *.c *.cpp *.cc)
foreach(source ${sources})
# Find the pure name of the test
string(REGEX REPLACE ".[cp]+$" "" path ${source})
string(REGEX REPLACE ".*/" "" name ${path})
# Should we skip this?
list(FIND PROGRAMS_TO_SKIP ${name} name_idx)
if(${name_idx} EQUAL -1)
get_unique_exe_name(source_exename ${source})
add_executable(${source_exename} ${source})
append_cflags(${source_exename} CFLAGS)
append_cflags(${source_exename} CPPFLAGS)
append_cflags(${source_exename} CXXFLAGS)
append_ldflags(${source_exename} LDFLAGS)
llvm_add_test(${name} ${source_exename})
add_dependencies(${source_exename} timeit timeit-target fpcmp)
endif()
endforeach()
endmacro()
# llvm_multisource - configure the current directory as a MultiSource subdirectory -
# i.e. there is one test and it consists of all sources in the directory (or a curated
# list, if Source is defined).
macro(llvm_multisource)
if(DEFINED Source)
set(sources ${Source})
else()
file(GLOB sources *.c *.cpp *.cc)
endif()
list(LENGTH sources sources_len)
if(sources_len GREATER 0 AND DEFINED PROG)
# Should we skip this?
list(FIND PROGRAMS_TO_SKIP ${PROG} name_idx)
if(${name_idx} EQUAL -1)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
get_unique_exe_name(source_exename "${PROG}.c")
add_executable(${source_exename} ${sources})
append_cflags(${source_exename} CFLAGS)
append_cflags(${source_exename} CPPFLAGS)
append_cflags(${source_exename} CXXFLAGS)
append_ldflags(${source_exename} LDFLAGS)
llvm_add_test(${PROG} ${source_exename})
add_dependencies(${source_exename} timeit timeit-target fpcmp)
endif()
endif()
endmacro()
macro(llvm_test_run)
CMAKE_PARSE_ARGUMENTS(ARGS "" "RUN_TYPE;EXECUTABLE;WORKDIR" "" ${ARGN})
# If no executable is specified use $EXECUTABLE$ placeholder which will be
# replaced later.
if(NOT DEFINED ARGS_EXECUTABLE)
set(ARGS_EXECUTABLE "$EXECUTABLE$")
endif()
if(NOT DEFINED TESTSCRIPT)
set(TESTSCRIPT "" PARENT_SCOPE)
endif()
if(DEFINED ARGS_WORKDIR)
set(ARGS_EXECUTABLE "cd ${ARGS_WORKDIR} ; ${ARGS_EXECUTABLE}")
endif()
# ARGS_UNPARSED_ARGUMENTS is a semicolon-separated list. Change it into a
# whitespace-separated string.
string(REPLACE ";" " " JOINED_ARGUMENTS "${ARGS_UNPARSED_ARGUMENTS}")
if(NOT DEFINED ARGS_RUN_TYPE OR "${ARGS_RUN_TYPE}" STREQUAL "${TEST_SUITE_RUN_TYPE}")
set(TESTSCRIPT "${TESTSCRIPT}RUN: ${ARGS_EXECUTABLE} ${JOINED_ARGUMENTS}\n")
endif()
endmacro()
macro(llvm_test_verify)
CMAKE_PARSE_ARGUMENTS(ARGS "" "RUN_TYPE" "" ${ARGN})
if(NOT DEFINED TESTSCRIPT)
set(TESTSCRIPT "" PARENT_SCOPE)
endif()
# ARGS_UNPARSED_ARGUMENTS is a semicolon-separated list. Change it into a
# whitespace-separated string.
string(REPLACE ";" " " JOINED_ARGUMENTS "${ARGS_UNPARSED_ARGUMENTS}")
if(NOT DEFINED ARGS_RUN_TYPE OR "${ARGS_RUN_TYPE}" STREQUAL "${TEST_SUITE_RUN_TYPE}")
set(TESTSCRIPT "${TESTSCRIPT}VERIFY: ${JOINED_ARGUMENTS}\n")
endif()
endmacro()