diff --git a/libc/cmake/modules/LLVMLibCLibraryRules.cmake b/libc/cmake/modules/LLVMLibCLibraryRules.cmake --- a/libc/cmake/modules/LLVMLibCLibraryRules.cmake +++ b/libc/cmake/modules/LLVMLibCLibraryRules.cmake @@ -1,4 +1,6 @@ function(collect_object_file_deps target result) + # NOTE: This function does add entrypoint targets to |result|. + # It is expected that the caller adds them separately. set(all_deps "") get_target_property(target_type ${target} "TARGET_TYPE") if(NOT target_type) @@ -28,7 +30,6 @@ endif() set(entrypoint_target ${aliasee}) endif() - list(APPEND all_deps ${entrypoint_target}) get_target_property(deps ${target} "DEPS") foreach(dep IN LISTS deps) collect_object_file_deps(${dep} dep_targets) @@ -80,6 +81,21 @@ endif() collect_object_file_deps(${dep} recursive_deps) list(APPEND all_deps ${recursive_deps}) + # Add the entrypoint object target explicitly as collect_object_file_deps + # only collects object files from non-entrypoint targets. + if(${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}) + set(entrypoint_target ${dep}) + get_target_property(is_alias ${entrypoint_target} "IS_ALIAS") + if(is_alias) + get_target_property(aliasee ${entrypoint_target} "DEPS") + if(NOT aliasee) + message(FATAL_ERROR + "Entrypoint alias ${entrypoint_target} does not have an aliasee.") + endif() + set(entrypoint_target ${aliasee}) + endif() + endif() + list(APPEND all_deps ${entrypoint_target}) endforeach(dep) list(REMOVE_DUPLICATES all_deps) set(objects "") diff --git a/libc/config/baremetal/entrypoints.txt b/libc/config/baremetal/entrypoints.txt --- a/libc/config/baremetal/entrypoints.txt +++ b/libc/config/baremetal/entrypoints.txt @@ -17,6 +17,9 @@ libc.src.ctype.tolower libc.src.ctype.toupper + # errno.h entrypoints + libc.src.errno.errno + # string.h entrypoints libc.src.string.bcmp libc.src.string.bcopy diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -17,6 +17,9 @@ libc.src.ctype.tolower libc.src.ctype.toupper + # errno.h entrypoints + libc.src.errno.errno + # fcntl.h entrypoints libc.src.fcntl.creat libc.src.fcntl.open diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -17,6 +17,9 @@ libc.src.ctype.tolower libc.src.ctype.toupper + # errno.h entrypoints + libc.src.errno.errno + # string.h entrypoints libc.src.string.bcmp libc.src.string.bcopy 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 @@ -17,6 +17,9 @@ libc.src.ctype.tolower libc.src.ctype.toupper + # errno.h entrypoints + libc.src.errno.errno + # fcntl.h entrypoints libc.src.fcntl.creat libc.src.fcntl.open diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst --- a/libc/docs/dev/code_style.rst +++ b/libc/docs/dev/code_style.rst @@ -65,3 +65,40 @@ definitions that are implicitly inline. Examples of such functions are class methods (static and non-static) defined inline and ``constexpr`` functions. + +Setting ``errno`` from runtime code +=================================== + +Many libc functions set ``errno`` to indicate an error condition. If LLVM's libc +is being used as the only libc, then the ``errno`` from LLVM's libc is affected. +If LLVM's libc is being used in the :ref:`overlay_mode`, then the ``errno`` from +the system libc is affected. When a libc function, which can potentially affect +the ``errno``, is called from a unit test, we do not want the global ``errno`` +(as in, the ``errno`` of the process thread running the unit test) to be +affected. If the global ``errno`` is affected, then the operation of the unit +test infrastructure itself can be affected. To avoid perturbing the unit test +infrastructure around the setting of ``errno``, the following rules are to be +followed: + +#. A special macro named ``libc_errno`` defined in ``src/errno/libc_errno.h`` + should be used when setting ``errno`` from libc runtime code. For example, + code to set ``errno`` to ``EINVAL`` should be: + + .. code-block:: c++ + + libc_errno = EINVAL; + +#. ``errno`` should be set just before returning from the implementation of the + public function. It should not be set from within helper functions. Helper + functions should use idiomatic C++ constructs like + `cpp::optional `_ + and + `ErrorOr `_ + to return error values. + +#. The header file ``src/errno/libc_errno.h`` is shipped as part of the target + corresponding to the ``errno`` entrypoint ``libc.src.errno.errno``. We do + not in general allow dependecies between entrypoints. However, the ``errno`` + entrypoint is the only exceptional entrypoint on which other entrypoints + should explicitly depend on if they set ``errno`` to indicate error + conditions. diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt --- a/libc/src/errno/CMakeLists.txt +++ b/libc/src/errno/CMakeLists.txt @@ -1,4 +1,4 @@ -add_object_library( +add_entrypoint_object( errno SRCS libc_errno.cpp