| # Copyright 2022 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| include_guard(GLOBAL) |
| |
| include($ENV{PW_ROOT}/pw_build/pigweed.cmake) |
| |
| set(pw_unit_test_ENABLE_PW_ADD_TEST ON CACHE BOOL |
| "Enable or disable pw_add_test calls. This is useful if you would like to \ |
| disable test generation when adding Pigweed to an existing project. Set to \ |
| OFF before the add_subdirectory(third_party/pigweed) call to prevent tests \ |
| from being generated.") |
| |
| set(pw_unit_test_BACKEND pw_unit_test.light CACHE STRING |
| "CMake target which implements GoogleTest, by default pw_unit_test.light \ |
| is used. You could, for example, point this at pw_unit_test.googletest \ |
| if using upstream GoogleTest directly on your host for GoogleMock.") |
| |
| set(pw_unit_test_GOOGLETEST_BACKEND "" CACHE STRING |
| "Warning: Deprecated build argument. When using googletest backend set |
| pw_unit_test_BACKEND to pw_unit_test.googletest instead.") |
| |
| # TODO(ewout): Remove the default. |
| set(pw_unit_test_ADD_EXECUTABLE_FUNCTION "pw_add_test_executable" CACHE STRING |
| "The name of the CMake function used to instantiate pw_unit_test \ |
| executables") |
| |
| # TODO(ewout): Remove the default. |
| set(pw_unit_test_ADD_EXECUTABLE_FUNCTION_FILE |
| "$ENV{PW_ROOT}/targets/host/pw_add_test_executable.cmake" CACHE STRING |
| "The path to the .cmake file that defines \ |
| pw_unit_test_ADD_EXECUTABLE_FUNCTION.") |
| |
| # TODO(ewout): Remove the default to match GN and support Windows. |
| set(pw_unit_test_AUTOMATIC_RUNNER "$ENV{PW_ROOT}/targets/host/run_test" CACHE |
| STRING |
| "Path to a test runner to automatically run unit tests after they are \ |
| built. \ |
| If set, a pw_add_test's {NAME}.run action will invoke the test runner \ |
| specified by this variable, passing the path to the unit test to run. If \ |
| set to an empty string, the {NAME}.run step will fail to build.") |
| |
| set(pw_unit_test_AUTOMATIC_RUNNER_TIMEOUT_SECONDS "" CACHE STRING |
| "Optional timeout to apply when running tests via the automatic runner. \ |
| Timeout is in seconds. Defaults to empty which means no timeout.") |
| |
| set(pw_unit_test_AUTOMATIC_RUNNER_ARGS "" CACHE STRING |
| "Optional list of arguments to forward to the automatic runner") |
| |
| # pw_add_test: Declares a single unit test suite with Pigweed naming rules and |
| # compiler warning options. |
| # |
| # {NAME} depends on ${NAME}.run if pw_unit_test_AUTOMATIC_RUNNER is set, else |
| # it depends on ${NAME}.bin |
| # {NAME}.lib contains the provided test sources as a library target, which can |
| # then be linked into a test executable. |
| # {NAME}.bin is a standalone executable which contains only the test sources |
| # specified in the pw_unit_test_template. |
| # {NAME}.run which runs the unit test executable after building it if |
| # pw_unit_test_AUTOMATIC_RUNNER is set, else it fails to build. |
| # |
| # Required Arguments: |
| # |
| # NAME: name to use for the produced test targets specified above |
| # |
| # Optional Arguments: |
| # |
| # SOURCES - source files for this library |
| # HEADERS - header files for this library |
| # PRIVATE_DEPS - private pw_target_link_targets arguments |
| # PRIVATE_INCLUDES - public target_include_directories argument |
| # PRIVATE_DEFINES - private target_compile_definitions arguments |
| # PRIVATE_COMPILE_OPTIONS - private target_compile_options arguments |
| # PRIVATE_LINK_OPTIONS - private target_link_options arguments |
| # |
| # TODO(ewout, hepler): Deprecate the following legacy arguments |
| # GROUPS - groups to which to add this test. |
| # |
| function(pw_add_test NAME) |
| if("${pw_unit_test_ENABLE_PW_ADD_TEST}") |
| pw_parse_arguments( |
| NUM_POSITIONAL_ARGS |
| 1 |
| MULTI_VALUE_ARGS |
| SOURCES HEADERS PRIVATE_DEPS PRIVATE_INCLUDES |
| PRIVATE_DEFINES PRIVATE_COMPILE_OPTIONS |
| PRIVATE_LINK_OPTIONS GROUPS |
| ) |
| |
| _pw_check_name_is_relative_to_root("${NAME}" "$ENV{PW_ROOT}" |
| REMAP_PREFIXES |
| third_party pw_third_party |
| ) |
| |
| pw_add_test_generic(${NAME} |
| SOURCES |
| ${arg_SOURCES} |
| HEADERS |
| ${arg_HEADERS} |
| PRIVATE_DEPS |
| # TODO: b/232141950 - Apply compilation options that affect ABI |
| # globally in the CMake build instead of injecting them into libraries. |
| pw_build |
| ${arg_PRIVATE_DEPS} |
| PRIVATE_INCLUDES |
| ${arg_PRIVATE_INCLUDES} |
| PRIVATE_DEFINES |
| ${arg_PRIVATE_DEFINES} |
| PRIVATE_COMPILE_OPTIONS_DEPS_BEFORE |
| pw_build.warnings |
| PRIVATE_COMPILE_OPTIONS |
| ${arg_PRIVATE_COMPILE_OPTIONS} |
| PRIVATE_LINK_OPTIONS |
| ${arg_PRIVATE_LINK_OPTIONS} |
| GROUPS |
| ${arg_GROUPS} |
| ) |
| endif() |
| endfunction() |
| |
| # pw_add_test_generic: Declares a single unit test suite. |
| # |
| # {NAME} depends on ${NAME}.run if pw_unit_test_AUTOMATIC_RUNNER is set, else |
| # it depends on ${NAME}.bin |
| # {NAME}.lib contains the provided test sources as a library target, which can |
| # then be linked into a test executable. |
| # {NAME}.bin is a standalone executable which contains only the test sources |
| # specified in the pw_unit_test_template. |
| # {NAME}.run which runs the unit test executable after building it if |
| # pw_unit_test_AUTOMATIC_RUNNER is set, else it fails to build. |
| # |
| # Required Arguments: |
| # |
| # NAME: name to use for the produced test targets specified above |
| # |
| # Optional Arguments: |
| # |
| # SOURCES - source files for this library |
| # HEADERS - header files for this library |
| # PRIVATE_DEPS - private pw_target_link_targets arguments |
| # PRIVATE_INCLUDES - public target_include_directories argument |
| # PRIVATE_DEFINES - private target_compile_definitions arguments |
| # PRIVATE_COMPILE_OPTIONS_DEPS_BEFORE - private target_compile_options BEFORE |
| # arguments from the specified deps's INTERFACE_COMPILE_OPTIONS. Note that |
| # these deps are not pulled in as target_link_libraries. This should not be |
| # exposed by the non-generic API. |
| # PRIVATE_COMPILE_OPTIONS - private target_compile_options arguments |
| # PRIVATE_LINK_OPTIONS - private target_link_options arguments |
| # TEST_MAIN - overrides the default test main dependency |
| # |
| # TODO(ewout, hepler): Deprecate the following legacy arguments |
| # GROUPS - groups to which to add this test. |
| # |
| function(pw_add_test_generic NAME) |
| pw_parse_arguments( |
| NUM_POSITIONAL_ARGS |
| 1 |
| ONE_VALUE_ARGS |
| TEST_MAIN |
| MULTI_VALUE_ARGS |
| SOURCES HEADERS PRIVATE_DEPS PRIVATE_INCLUDES |
| PRIVATE_DEFINES |
| PRIVATE_COMPILE_OPTIONS_DEPS_BEFORE PRIVATE_COMPILE_OPTIONS |
| PRIVATE_LINK_OPTIONS GROUPS |
| ) |
| |
| # Add the library target under "${NAME}.lib". |
| # OBJECT libraries require at least one source file. |
| if("${arg_SOURCES}" STREQUAL "") |
| set(lib_type "INTERFACE") |
| else() |
| set(lib_type "OBJECT") |
| endif() |
| pw_add_library_generic("${NAME}.lib" ${lib_type} |
| SOURCES |
| ${arg_SOURCES} |
| HEADERS |
| ${arg_HEADERS} |
| PRIVATE_DEPS |
| pw_unit_test |
| ${arg_PRIVATE_DEPS} |
| PRIVATE_INCLUDES |
| ${arg_PRIVATE_INCLUDES} |
| PRIVATE_DEFINES |
| ${arg_PRIVATE_DEFINES} |
| PRIVATE_COMPILE_OPTIONS_DEPS_BEFORE |
| ${arg_PRIVATE_COMPILE_OPTIONS_DEPS_BEFORE} |
| PRIVATE_COMPILE_OPTIONS |
| ${arg_PRIVATE_COMPILE_OPTIONS} |
| PRIVATE_LINK_OPTIONS |
| ${arg_PRIVATE_LINK_OPTIONS} |
| ) |
| |
| # Add the executable target under "${NAME}.bin". |
| if(("${pw_unit_test_ADD_EXECUTABLE_FUNCTION}" STREQUAL "") OR |
| ("${pw_unit_test_ADD_EXECUTABLE_FUNCTION_FILE}" STREQUAL "")) |
| pw_add_error_target("${NAME}.bin" |
| MESSAGE |
| "Attempted to build the ${NAME}.bin without enabling the unit " |
| "test executable function via pw_unit_test_ADD_EXECUTABLE_FUNCTION " |
| "and pw_unit_test_ADD_EXECUTABLE_FUNCTION_FILE. " |
| "See https://pigweed.dev/pw_unit_test for more details." |
| ) |
| else() |
| include("${pw_unit_test_ADD_EXECUTABLE_FUNCTION_FILE}") |
| if ("${arg_TEST_MAIN}" STREQUAL "") |
| cmake_language(CALL "${pw_unit_test_ADD_EXECUTABLE_FUNCTION}" |
| "${NAME}.bin" "${NAME}.lib") |
| else() |
| cmake_language(CALL "${pw_unit_test_ADD_EXECUTABLE_FUNCTION}_with_main" |
| "${NAME}.bin" "${NAME}.lib" "${arg_TEST_MAIN}") |
| endif() |
| endif() |
| |
| # Add the ${NAME} target and optionally the run target under ${NAME}.run. |
| add_custom_target("${NAME}") |
| if("${pw_unit_test_AUTOMATIC_RUNNER}" STREQUAL "") |
| # Test runner is not provided, only build the executable. |
| add_dependencies("${NAME}" "${NAME}.bin") |
| |
| pw_add_error_target("${NAME}.run" |
| MESSAGE |
| "Attempted to build ${NAME}.run which is not available because " |
| "pw_unit_test_AUTOMATIC_RUNNER has not been configured. " |
| "See https://pigweed.dev/pw_unit_test." |
| ) |
| else() # pw_unit_test_AUTOMATIC_RUNNER is provided. |
| # Define a target for running the test. The target creates a stamp file to |
| # indicate successful test completion. This allows running tests in parallel |
| # with Ninja's full dependency resolution. |
| if(NOT "${pw_unit_test_AUTOMATIC_RUNNER_TIMEOUT_SECONDS}" STREQUAL "") |
| set(optional_timeout_arg |
| "--timeout" "${pw_unit_test_AUTOMATIC_RUNNER_TIMEOUT_SECONDS}") |
| endif() |
| if(NOT "${pw_unit_test_AUTOMATIC_RUNNER_ARGS}" STREQUAL "") |
| set(optional_runner_args "--" "${pw_unit_test_AUTOMATIC_RUNNER_ARGS}") |
| endif() |
| add_custom_command( |
| COMMAND |
| python3 -m pw_unit_test.test_runner |
| --runner "${pw_unit_test_AUTOMATIC_RUNNER}" |
| --test "$<TARGET_FILE:${NAME}.bin>" |
| ${optional_timeout_arg} |
| ${optional_runner_args} |
| COMMAND |
| "${CMAKE_COMMAND}" -E touch "${NAME}.stamp" |
| DEPENDS |
| "${NAME}.bin" |
| OUTPUT |
| "${NAME}.stamp" |
| ) |
| add_custom_target("${NAME}.run" DEPENDS "${NAME}.stamp") |
| add_dependencies("${NAME}" "${NAME}.run") |
| endif() |
| |
| if(arg_GROUPS) |
| pw_add_test_to_groups("${NAME}" ${arg_GROUPS}) |
| endif() |
| endfunction(pw_add_test_generic) |
| |
| # pw_add_test_group: Defines a collection of tests or other test groups. |
| # |
| # Creates the following targets: |
| # |
| # {NAME} depends on ${NAME}.run if pw_unit_test_AUTOMATIC_RUNNER is set, else |
| # it depends on ${NAME}.bin |
| # {NAME}.bundle depends on ${NAME}.bundle.run if pw_unit_test_AUTOMATIC_RUNNER |
| # is set, else it depends on ${NAME}.bundle.bin |
| # {NAME}.lib depends on ${NAME}.bundle.lib. |
| # {NAME}.bin depends on the provided TESTS's <test_dep>.bin targets. |
| # {NAME}.run depends on the provided TESTS's <test_dep>.run targets if |
| # pw_unit_test_AUTOMATIC_RUNNER is set, else it fails to build. |
| # {NAME}.bundle.lib contains the provided tests bundled as a library target, |
| # which can then be linked into a test executable. |
| # {NAME}.bundle.bin standalone executable which contains the bundled tests. |
| # {NAME}.bundle.run runs the {NAME}.bundle.bin test bundle executable after |
| # building it if pw_unit_test_AUTOMATIC_RUNNER is set, else |
| # it fails to build. |
| # |
| # Required Arguments: |
| # |
| # NAME - The name of the executable target to be created. |
| # TESTS - pw_add_test targets and pw_add_test_group bundles to be included in |
| # this test bundle |
| # |
| function(pw_add_test_group NAME) |
| pw_parse_arguments( |
| NUM_POSITIONAL_ARGMENTS |
| 1 |
| MULTI_VALUE_ARGS |
| TESTS |
| REQUIRED_ARGS |
| TESTS |
| ) |
| |
| set(test_lib_targets "") |
| set(test_bin_targets "") |
| set(test_run_targets "") |
| foreach(test IN LISTS arg_TESTS) |
| list(APPEND test_lib_targets "${test}.lib") |
| list(APPEND test_bin_targets "${test}.bin") |
| list(APPEND test_run_targets "${test}.run") |
| endforeach() |
| |
| # This produces ${NAME}.bundle, ${NAME}.bundle.lib, ${NAME}.bundle.bin, and |
| # ${NAME}.bundle.run. |
| pw_add_test("${NAME}.bundle" |
| PRIVATE_DEPS |
| ${test_lib_targets} |
| ) |
| |
| # Produce ${NAME}.lib. |
| pw_add_library_generic("${NAME}.lib" INTERFACE |
| PUBLIC_DEPS |
| ${NAME}.bundle.lib |
| ) |
| |
| # Produce ${NAME}.bin. |
| add_custom_target("${NAME}.bin") |
| add_dependencies("${NAME}.bin" ${test_bin_targets}) |
| |
| # Produce ${NAME} and ${NAME}.run. |
| add_custom_target("${NAME}") |
| if("${pw_unit_test_AUTOMATIC_RUNNER}" STREQUAL "") |
| # Test runner is not provided, only build the executable. |
| add_dependencies("${NAME}" "${NAME}.bin") |
| |
| pw_add_error_target("${NAME}.run" |
| MESSAGE |
| "Attempted to build ${NAME}.run which is not available because " |
| "pw_unit_test_AUTOMATIC_RUNNER has not been configured. " |
| "See https://pigweed.dev/pw_unit_test." |
| ) |
| else() # pw_unit_test_AUTOMATIC_RUNNER is provided, build and run the test. |
| add_custom_target("${NAME}.run") |
| add_dependencies("${NAME}.run" ${test_run_targets}) |
| |
| add_dependencies("${NAME}" "${NAME}.run") |
| endif() |
| endfunction(pw_add_test_group) |
| |
| # Adds a test target to the specified test groups. Test groups can be built with |
| # the pw_tests_GROUP_NAME target or executed with the pw_run_tests_GROUP_NAME |
| # target. |
| function(pw_add_test_to_groups TEST_NAME) |
| foreach(group IN LISTS ARGN) |
| if(NOT TARGET "pw_tests.${group}") |
| add_custom_target("pw_tests.${group}") |
| add_custom_target("pw_run_tests.${group}") |
| endif() |
| |
| add_dependencies("pw_tests.${group}" "${TEST_NAME}.bin") |
| add_dependencies("pw_run_tests.${group}" "${TEST_NAME}.run") |
| endforeach() |
| endfunction(pw_add_test_to_groups) |