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 @@ -438,74 +438,54 @@ get_fq_target_name(${test_name}.libc fq_libc_target_name) get_fq_deps_list(fq_deps_list ${INTEGRATION_TEST_DEPENDS}) - # All integration tests setup TLS area and the main thread's self object. - # So, we need to link in the threads implementation. Likewise, the startup - # code also has to run init_array callbacks which potentially register - # their own atexit callbacks. So, link in exit and atexit also with all - # integration tests. - list( - APPEND fq_deps_list + list(APPEND fq_deps_list + # All integration tests setup TLS area and the main thread's self object. + # So, we need to link in the threads implementation. Likewise, the startup + # code also has to run init_array callbacks which potentially register + # their own atexit callbacks. So, link in exit and atexit also with all + # integration tests. libc.src.__support.threads.thread libc.src.stdlib.atexit libc.src.stdlib.exit libc.src.unistd.environ - libc.test.IntegrationTest.test) + ) + list(APPEND memory_functions + libc.src.string.bcmp + libc.src.string.bzero + libc.src.string.memcmp + libc.src.string.memcpy + libc.src.string.memmove + libc.src.string.memset + ) + # We remove the memory function deps because we want to explicitly add the + # object files which include the public symbols of the memory functions. + list(REMOVE_ITEM fq_deps_list ${memory_functions}) list(REMOVE_DUPLICATES fq_deps_list) # TODO: Instead of gathering internal object files from entrypoints, # collect the object files with public names of entrypoints. get_object_files_for_test( link_object_files skipped_entrypoints_list ${fq_deps_list}) - if(skipped_entrypoints_list) - message(STATUS "Skipping ${fq_target_name} as it has skipped deps.") - return() - endif() - - # Create a sysroot structure - set(sysroot ${CMAKE_CURRENT_BINARY_DIR}/${test_name}/sysroot) - file(MAKE_DIRECTORY ${sysroot}) - file(MAKE_DIRECTORY ${sysroot}/include) - set(sysroot_lib ${sysroot}/lib) - file(MAKE_DIRECTORY ${sysroot_lib}) - set(startup_object_file $) - set(crti_object_file $) - set(crtn_object_file $) - set(dummy_archive $/lib$.a) - # TODO: Copy the startup files to the correct target-triple directory instead - # of to a partly hard-coded directory. - set(startup_dst ${sysroot_lib}/${LIBC_TARGET_ARCHITECTURE}-linux-gnu) - add_custom_command( - OUTPUT ${startup_dst} ${sysroot}/lib/crti.o ${sysroot}/lib/crtn.o ${sysroot}/lib/libm.a ${sysroot}/lib/libc++.a - COMMAND cmake -E copy ${startup_object_file} ${startup_dst}/$ - COMMAND cmake -E copy ${crti_object_file} ${sysroot_lib}/$ - COMMAND cmake -E copy ${crtn_object_file} ${sysroot_lib}/$ - # We copy the dummy archive as libm.a and libc++.a as the compiler drivers expect them. - COMMAND cmake -E copy ${dummy_archive} ${sysroot_lib}/libm.a - COMMAND cmake -E copy ${dummy_archive} ${sysroot_lib}/libc++.a - DEPENDS ${INTEGRATION_TEST_STARTUP} libc.startup.linux.crti libc.startup.linux.crtn libc_integration_test_dummy - ) - add_custom_target( - ${fq_target_name}.__copy_startup__ - DEPENDS ${startup_dst} - ) - + # We add the memory functions objects explicitly. Note that we + # are adding objects of the targets which contain the public + # C symbols. This is because compiler codegen can emit calls to + # the C memory functions. + foreach(func IN LISTS memory_functions) + list(APPEND link_object_files $) + endforeach() + list(REMOVE_DUPLICATES link_object_files) + + # Make a library of all deps add_library( - ${fq_libc_target_name} + ${fq_target_name}.__libc__ STATIC + EXCLUDE_FROM_ALL ${link_object_files} - # We add the memory functions objects explicitly. Note that we - # are adding objects of the targets which contain the public - # C symbols. This is because compiler codegen can emit calls to - # the C memory functions. - $ - $ - $ - $ - $ - $ ) - set_target_properties(${fq_libc_target_name} PROPERTIES ARCHIVE_OUTPUT_NAME c) - set_target_properties(${fq_libc_target_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${sysroot_lib}) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc) set(fq_build_target_name ${fq_target_name}.__build__) add_executable( @@ -523,16 +503,13 @@ ${LIBC_BUILD_DIR} ${LIBC_BUILD_DIR}/include ) - target_compile_options(${fq_build_target_name} PRIVATE -ffreestanding ${INTEGRATION_TEST_COMPILE_OPTIONS}) - # We set a number of link options to prevent picking up system libc binaries. - # Also, we restrict the integration tests to fully static executables. The - # rtlib is set to compiler-rt to make the compiler drivers pick up the compiler - # runtime binaries using full paths. Otherwise, files like crtbegin.o are passed - # as is (and not as paths like /usr/lib/.../crtbegin.o). - target_link_options(${fq_build_target_name} PRIVATE --sysroot=${sysroot} -static -stdlib=libc++ --rtlib=compiler-rt) + target_compile_options(${fq_build_target_name} + PRIVATE -ffreestanding ${INTEGRATION_TEST_COMPILE_OPTIONS}) + target_link_options(${fq_build_target_name} PRIVATE -nostdlib -static) + target_link_libraries(${fq_build_target_name} + ${INTEGRATION_TEST_STARTUP} ${fq_target_name}.__libc__ + libc.test.IntegrationTest.test) add_dependencies(${fq_build_target_name} - ${fq_target_name}.__copy_startup__ - ${fq_libc_target_name} libc.test.IntegrationTest.test ${INTEGRATION_TEST_DEPENDS}) @@ -541,6 +518,5 @@ COMMAND ${INTEGRATION_TEST_ENV} $ ${INTEGRATION_TEST_ARGS} COMMENT "Running integration test ${fq_target_name}" ) - add_dependencies(${INTEGRATION_TEST_SUITE} ${fq_target_name}) endfunction(add_integration_test) diff --git a/libc/startup/linux/aarch64/start.cpp b/libc/startup/linux/aarch64/start.cpp --- a/libc/startup/linux/aarch64/start.cpp +++ b/libc/startup/linux/aarch64/start.cpp @@ -23,6 +23,9 @@ #include extern "C" int main(int, char **, char **); +// The BFD linker requires a reference to __dso_handle to trigger creating +// a symbol for it when -nostdlib is used.. +extern "C" void *__dso_handle = nullptr; // Source documentation: // https://github.com/ARM-software/abi-aa/tree/main/sysvabi64 diff --git a/libc/startup/linux/x86_64/start.cpp b/libc/startup/linux/x86_64/start.cpp --- a/libc/startup/linux/x86_64/start.cpp +++ b/libc/startup/linux/x86_64/start.cpp @@ -22,6 +22,9 @@ #include extern "C" int main(int, char **, char **); +// The BFD linker requires a reference to __dso_handle to trigger creating +// a symbol for it when -nostdlib is used.. +extern "C" void *__dso_handle = nullptr; namespace __llvm_libc {