diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -68,6 +68,22 @@ add_subdirectory(include) add_subdirectory(config) + +include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt") +include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt") + +set(TARGET_ENTRYPOINT_NAME_LIST "") +foreach(entrypoint IN LISTS TARGET_LIBC_ENTRYPOINTS TARGET_LIBM_ENTRYPOINTS) + string(FIND ${entrypoint} "." last_dot_loc REVERSE) + if(${last_dot_loc} EQUAL -1) + message(FATAL "Invalid entrypoint target name ${entrypoint}; Expected a '.' " + "(dot) in the name.") + endif() + math(EXPR name_loc "${last_dot_loc} + 1") + string(SUBSTRING ${entrypoint} ${name_loc} -1 entrypoint_name) + list(APPEND TARGET_ENTRYPOINT_NAME_LIST ${entrypoint_name}) +endforeach() + add_subdirectory(src) add_subdirectory(utils) diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake --- a/libc/cmake/modules/LLVMLibCObjectRules.cmake +++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake @@ -86,6 +86,23 @@ set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME}) endif() + list(FIND TARGET_ENTRYPOINT_NAME_LIST ${entrypoint_name} entrypoint_name_index) + if(${entrypoint_name_index} EQUAL -1) + add_custom_target(${fq_target_name}) + set_target_properties( + ${fq_target_name} + PROPERTIES + "ENTRYPOINT_NAME" ${entrypoint_name} + "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE} + "OBJECT_FILE" "" + "OBJECT_FILE_RAW" "" + "DEPS" "" + "SKIPPED" "YES" + ) + message(STATUS "Skipping libc entrypoint ${fq_target_name}.") + return() + endif() + if(ADD_ENTRYPOINT_OBJ_ALIAS) # Alias targets help one add aliases to other entrypoint object targets. # One can use alias targets setup OS/machine independent entrypoint targets. diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -3,12 +3,18 @@ # recursively produced by "add_entrypoint_object" and "add_object_library" # targets. # Usage: -# get_object_files_for_test( [ ...]) +# get_object_files_for_test( +# +# [ ...]) # +# The list of object files is collected in . +# If skipped entrypoints were found, then is +# set to a true value. # targetN is either an "add_entrypoint_target" target or an # "add_object_library" target. -function(get_object_files_for_test result) +function(get_object_files_for_test result skipped_entrypoints_list) set(object_files "") + set(skipped_list "") foreach(dep IN LISTS ARGN) get_target_property(dep_type ${dep} "TARGET_TYPE") if(NOT dep_type) @@ -23,6 +29,11 @@ list(APPEND object_files ${dep_object_files}) endif() elseif(${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}) + get_target_property(is_skipped ${dep} "SKIPPED") + if(is_skipped) + list(APPEND skipped_list ${dep}) + continue() + endif() get_target_property(object_file_raw ${dep} "OBJECT_FILE_RAW") if(object_file_raw) list(APPEND object_files ${object_file_raw}) @@ -30,11 +41,17 @@ endif() get_target_property(indirect_deps ${dep} "DEPS") - get_object_files_for_test(indirect_objfiles ${indirect_deps}) + get_object_files_for_test( + indirect_objfiles indirect_skipped_list ${indirect_deps}) list(APPEND object_files ${indirect_objfiles}) + if(indirect_skipped_list) + list(APPEND skipped_list ${indirect_skipped_list}) + endif() endforeach(dep) list(REMOVE_DUPLICATES object_files) set(${result} ${object_files} PARENT_SCOPE) + list(REMOVE_DUPLICATES skipped_list) + set(${skipped_entrypoints_list} ${skipped_list} PARENT_SCOPE) endfunction(get_object_files_for_test) # Rule to add a libc unittest. @@ -68,8 +85,43 @@ "'add_entrypoint_object' targets.") endif() - get_fq_target_name(${target_name} fq_target_name) + get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS}) + get_object_files_for_test( + link_object_files skipped_entrypoints_list ${fq_deps_list}) + if(skipped_entrypoints_list) + # If a test is OS/target machine independent, it has to be skipped if the + # OS/target machine combination does not provide any dependent entrypoints. + # If a test is OS/target machine specific, then such a test will live is a + # OS/target machine specific directory and will be skipped at the directory + # level if required. + # + # There can potentially be a setup like this: A unittest is setup for a + # OS/target machine independent object library, which in turn depends on a + # machine specific object library. Such a test would be testing internals of + # the libc and it is assumed that they will be rare in practice. So, they + # can be skipped in the corresponding CMake files using platform specific + # logic. This pattern is followed in the loader tests for example. + # + # Another pattern that is present currently is to detect machine + # capabilities and add entrypoints and tests accordingly. That approach is + # much lower level approach and is independent of the kind of skipping that + # is happening here at the entrypoint level. + + set(msg "Skipping unittest ${fq_target_name} as it has missing deps: " + "${skipped_entrypoints_list}.") + message(STATUS ${msg}) + add_custom_target(${fq_target_name}) + + # A post build custom command is used to avoid running the command always. + add_custom_command( + TARGET ${fq_target_name} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo ${msg} + ) + return() + endif() + add_executable( ${fq_target_name} EXCLUDE_FROM_ALL @@ -90,8 +142,6 @@ ) endif() - get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS}) - get_object_files_for_test(link_object_files ${fq_deps_list}) target_link_libraries(${fq_target_name} PRIVATE ${link_object_files}) set_target_properties(${fq_target_name} diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -1,4 +1,4 @@ -set(LIBC_ENTRYPOINTS +set(TARGET_LIBC_ENTRYPOINTS # assert.h entrypoints libc.src.assert.__assert_fail @@ -43,7 +43,7 @@ libc.src.unistd.write ) -set(LIBM_ENTRYPOINTS +set(TARGET_LIBM_ENTRYPOINTS # math.h entrypoints libc.src.math.ceil libc.src.math.ceilf diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -1,4 +1,4 @@ -set(PUBLIC_HEADERS +set(TARGET_PUBLIC_HEADERS libc.include.assert_h libc.include.errno libc.include.math diff --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt --- a/libc/lib/CMakeLists.txt +++ b/libc/lib/CMakeLists.txt @@ -1,16 +1,13 @@ -include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt") -include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt") - add_entrypoint_library( llvmlibc DEPENDS - ${LIBC_ENTRYPOINTS} + ${TARGET_LIBC_ENTRYPOINTS} ) add_entrypoint_library( llvmlibm DEPENDS - ${LIBM_ENTRYPOINTS} + ${TARGET_LIBM_ENTRYPOINTS} ) add_redirector_library( diff --git a/libc/loader/linux/CMakeLists.txt b/libc/loader/linux/CMakeLists.txt --- a/libc/loader/linux/CMakeLists.txt +++ b/libc/loader/linux/CMakeLists.txt @@ -56,6 +56,11 @@ ) endfunction() +if(NOT (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_MACHINE})) + message(STATUS "Skipping loader for target machine ${LIBC_TARGET_MACHINE}") + return() +endif() + add_subdirectory(${LIBC_TARGET_MACHINE}) add_loader_object( diff --git a/libc/test/loader/CMakeLists.txt b/libc/test/loader/CMakeLists.txt --- a/libc/test/loader/CMakeLists.txt +++ b/libc/test/loader/CMakeLists.txt @@ -38,7 +38,7 @@ ) get_fq_deps_list(fq_deps_list ${ADD_LOADER_TEST_DEPENDS}) - get_object_files_for_test(link_object_files ${fq_deps_list}) + get_object_files_for_test(link_object_files has_skipped_entrypoint_list ${fq_deps_list}) target_link_libraries(${fq_target_name} ${link_object_files}) target_link_options( diff --git a/libc/test/loader/linux/CMakeLists.txt b/libc/test/loader/linux/CMakeLists.txt --- a/libc/test/loader/linux/CMakeLists.txt +++ b/libc/test/loader/linux/CMakeLists.txt @@ -1,3 +1,8 @@ +if(NOT (EXISTS ${LIBC_SOURCE_DIR}/loader/linux/${LIBC_TARGET_MACHINE})) + message("Skipping loader tests for target machine ${LIBC_TARGET_MACHINE}.") + return() +endif() + add_loader_test( loader_args_test SRC diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -9,13 +9,10 @@ add_subdirectory(threads) add_subdirectory(unistd) -include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt") -include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt") - set(public_test ${CMAKE_CURRENT_BINARY_DIR}/public_integration_test.cpp) set(entrypoints_name_list "") -foreach(entry IN LISTS LIBC_ENTRYPOINTS LIBM_ENTRYPOINTS) +foreach(entry IN LISTS TARGET_LIBC_ENTRYPOINTS TARGET_LIBM_ENTRYPOINTS) get_target_property(entry_name ${entry} "ENTRYPOINT_NAME") list(APPEND entrypoints_name_list ${entry_name}) endforeach()