Преглед изворни кода

newlib: auto-detect sizeof(time_t)

To make the transition from 32-bit time_t to 64-bit time_t smoother,
detect the size of this type in CMake and remove the manual option in
Kconfig.
The information about 64-bit time_t support is moved from Kconfig help
string into the "system time" section of the API reference.
Ivan Grokhotkov пре 4 година
родитељ
комит
d2b894862c

+ 10 - 0
CMakeLists.txt

@@ -209,6 +209,16 @@ if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
     list(APPEND compile_options "-fno-use-cxa-atexit")
 endif()
 
+# For the transition period from 32-bit time_t to 64-bit time_t,
+# auto-detect the size of this type and set corresponding variable.
+include(CheckTypeSize)
+check_type_size("time_t" TIME_T_SIZE)
+if(TIME_T_SIZE)
+    idf_build_set_property(TIME_T_SIZE ${TIME_T_SIZE})
+else()
+    message(FATAL_ERROR "Failed to determine sizeof(time_t)")
+endif()
+
 idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
 idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
 idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)

+ 0 - 20
Kconfig

@@ -104,26 +104,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
         default 0x000E if IDF_TARGET_ESP32H2_BETA_VERSION_2 # ESP32H2-TODO: IDF-3475
         default 0xFFFF
 
-    menu "SDK tool configuration"
-
-        config SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
-            bool "Toolchain supports time_t wide 64-bits"
-            default n
-            help
-                Enable this option in case you have a custom toolchain which supports time_t wide 64-bits.
-                This option checks time_t is 64-bits and disables ROM time functions
-                to use the time functions from the toolchain instead.
-                This option allows resolving the Y2K38 problem.
-                See "Setup Linux Toolchain from Scratch" to build
-                a custom toolchain which supports 64-bits time_t.
-
-                Note: ESP-IDF does not currently come with any pre-compiled toolchain
-                that supports 64-bit wide time_t.
-                This will change in a future major release,
-                but currently 64-bit time_t requires a custom built toolchain.
-
-    endmenu  # SDK tool configuration
-
 
     menu "Build type"
 

+ 36 - 37
components/esp_rom/CMakeLists.txt

@@ -57,6 +57,8 @@ else()
     rom_linker_script("libgcc")
 endif()
 
+idf_build_get_property(time_t_size TIME_T_SIZE)
+
 if(BOOTLOADER_BUILD)
     if(target STREQUAL "esp32")
         rom_linker_script("newlib-funcs")
@@ -91,19 +93,20 @@ else() # Regular app build
         rom_linker_script("syscalls")
 
         if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND)
+            # ESP32 only: these ROM functions may only be used if PSRAM cache workaround is disabled.
+            # Otherwise we need to link to a multilib version of libc compiled with PSRAM workaround.
             rom_linker_script("newlib-funcs")
-            if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-                # If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
-                # then all time functions from the ROM memory will not be linked.
-                # Instead, those functions can be used from the toolchain by ESP-IDF.
+
+            if(time_t_size EQUAL 4)
+                # The ROM functions listed in this linker script depend on sizeof(time_t).
+                # Since ROM for ESP32 was compiled for 32-bit time_t, only link these functions
+                # if the toolchain is also using 32-bit time_t.
                 rom_linker_script("newlib-time")
 
-                # Include in newlib nano from ROM only if SPIRAM cache workaround is disabled
-                # and sizeof(time_t) == 4
                 if(CONFIG_NEWLIB_NANO_FORMAT)
+                    # nano formatting functions in ROM are also built for 32-bit time_t.
                     rom_linker_script("newlib-nano")
                 endif()
-
             endif()
         endif()
 
@@ -120,52 +123,48 @@ else() # Regular app build
         rom_linker_script("newlib-data")
         rom_linker_script("spiflash")
 
-        if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-            # If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
-            # then all time functions from the ROM memory will not be linked.
-            # Instead, those functions can be used from the toolchain by ESP-IDF.
+        if(time_t_size EQUAL 4)
+            # The ROM functions listed in this linker script depend on sizeof(time_t).
+            # Since ROM for ESP32-S2 was compiled for 32-bit time_t, only link these functions
+            # if the toolchain is also using 32-bit time_t.
+            rom_linker_script("newlib-time")
 
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
 
-
-        # descirptors used by ROM code
-        target_sources(${COMPONENT_LIB} PRIVATE "esp32s2/usb_descriptors.c")
-
     elseif(target STREQUAL "esp32s3")
         rom_linker_script("newlib")
         rom_linker_script("version")
 
-        if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-            # If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
-            # then all time functions from the ROM memory will not be linked.
-            # Instead, those functions can be used from the toolchain by ESP-IDF.
+        if(time_t_size EQUAL 4)
+            # The ROM functions listed in this linker script depend on sizeof(time_t).
+            # Since ROM for ESP32-S3 was compiled for 32-bit time_t, only link these functions
+            # if the toolchain is also using 32-bit time_t.
+            rom_linker_script("newlib-time")
 
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
 
     elseif(target STREQUAL "esp32c3")
         rom_linker_script("newlib")
         rom_linker_script("version")
 
-        if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-            # If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
-            # then all time functions from the ROM memory will not be linked.
-            # Instead, those functions can be used from the toolchain by ESP-IDF.
+        if(time_t_size EQUAL 4)
+            # The ROM functions listed in this linker script depend on sizeof(time_t).
+            # Since ROM for ESP32-C3 was compiled for 32-bit time_t, only link these functions
+            # if the toolchain is also using 32-bit time_t.
+            rom_linker_script("newlib-time")
 
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
 
         if(CONFIG_ESP32C3_REV_MIN_3)
@@ -176,10 +175,10 @@ else() # Regular app build
         rom_linker_script("newlib")
         rom_linker_script("version")
 
-        if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-            if(CONFIG_NEWLIB_NANO_FORMAT)
-                rom_linker_script("newlib-nano")
-            endif()
+        if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
+            # nano formatting functions in ROM are built for 32-bit time_t,
+            # only link them if the toolchain is also using 32-bit time_t and nano formatting was requested.
+            rom_linker_script("newlib-nano")
         endif()
 
     elseif(target STREQUAL "esp8684")
@@ -187,10 +186,10 @@ else() # Regular app build
         rom_linker_script("version")
         rom_linker_script("mbedtls")
 
-        if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
-            if(CONFIG_NEWLIB_NANO_FORMAT)
-                rom_linker_script("newlib-nano")
-            endif()
+        if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
+            # nano formatting functions in ROM are built for 32-bit time_t,
+            # only link them if the toolchain is also using 32-bit time_t and nano formatting was requested.
+            rom_linker_script("newlib-nano")
         endif()
     endif()
 

+ 3 - 3
components/newlib/test/test_time.c

@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <string.h>
 #include <math.h>
 #include "unity.h"
 #include "driver/adc.h"
@@ -446,8 +447,7 @@ TEST_CASE("test posix_timers clock_... functions", "[newlib]")
     test_posix_timers_clock();
 }
 
-#ifdef CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
-#include <string.h>
+#ifndef _USE_LONG_TIME_T
 
 static struct timeval get_time(const char *desc, char *buffer)
 {
@@ -533,7 +533,7 @@ TEST_CASE("test time functions wide 64 bits", "[newlib]")
     }
 }
 
-#endif // CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
+#endif // !_USE_LONG_TIME_T
 
 #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
 

+ 5 - 19
components/newlib/time.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
-//
-// 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
-//
-//     http://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.
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include <errno.h>
 #include <stdlib.h>
@@ -37,12 +29,6 @@
 
 #include "sdkconfig.h"
 
-#ifdef CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
-_Static_assert(sizeof(time_t) == 8, "The toolchain does not support time_t wide 64-bits");
-#else
-_Static_assert(sizeof(time_t) == 4, "The toolchain supports time_t wide 64-bits. Please enable CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS.");
-#endif
-
 #if !CONFIG_ESP_TIME_FUNCS_USE_NONE
 #define IMPL_NEWLIB_TIME_FUNCS 1
 #endif

+ 2 - 2
components/spiffs/Kconfig

@@ -133,8 +133,8 @@ menu "SPIFFS Configuration"
             If the chip already has the spiffs image with the time field = 32 bits
             then this option cannot be applied in this case.
             Erase it first before using this option.
-            To resolve the Y2K38 problem for the spiffs, use a toolchain with support
-            time_t 64 bits (see SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS).
+            To resolve the Y2K38 problem for the spiffs, use a toolchain with
+            64-bit time_t support.
 
     menu "Debug Configuration"
 

+ 15 - 0
docs/en/api-reference/system/system_time.rst

@@ -130,6 +130,21 @@ To set local timezone, use the following POSIX functions:
 Once these steps are completed, call the standard C library function ``localtime()``, and it will return correct local time taking into account the time zone offset and daylight saving time.
 
 
+64-bit ``time_t``
+-----------------
+
+ESP-IDF uses 32-bit ``time_t`` type by default. To address Y2K38 issue, you may need to use 64-bit ``time_t`` type when building the application.
+
+Currently this requires building the cross-compiler toolchain from scratch. See the instructions for building the toolchain in :doc:`/get-started/linux-setup-scratch`. To enable 64-bit ``time_t`` support in the toolchain, you need to remove the ``--enable-newlib-long-time_t`` option from the ``crosstool-NG/samples/xtensa-esp32-elf/crosstool.config`` file before building the toolchain.
+
+If you need to make the program compatible with both 32-bit and 64-bit ``time_t``, you may use the following methods:
+
+- In C or C++ source files, ``_USE_LONG_TIME_T`` preprocessor macro will be defined if 32-bit ``time_t`` is used. You need to include ``<sys/types.h>`` to make this macro available.
+- In CMake files, ``TIME_T_SIZE`` IDF build property will be set to the size of ``time_t``, in bytes. You may call ``idf_build_get_property(var TIME_T_SIZE)`` to get the value of this property into a CMake variable ``var``. See :ref:`build system API reference <cmake_buildsystem_api>` for more information about ``idf_build_get_property``.
+
+Note that the size of ``time_t`` type also affects the sizes of other types, for example ``struct timeval``, ``struct stat``, ``struct utimbuf``.
+
+
 API Reference
 -------------
 

+ 0 - 2
docs/en/get-started/linux-setup-scratch.rst

@@ -64,8 +64,6 @@ Download ``crosstool-NG`` and build it:
 
 .. include-build-file:: inc/scratch-build-code.inc
 
-.. note:: To create a toolchain with support for 64-bit time_t, you need to remove the ``--enable-newlib-long-time_t`` option from the ``crosstool-NG/samples/xtensa-esp32-elf/crosstool.config`` file in 33 and 43 lines.
-
 Build the toolchain::
 
     ./ct-ng {IDF_TARGET_TOOLCHAIN_PREFIX}

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -1396,7 +1396,6 @@ components/newlib/test/test_time.c
 components/newlib/test_apps/app_test.py
 components/newlib/test_apps/main/test_newlib_main.c
 components/newlib/test_apps/main/test_stdatomic.c
-components/newlib/time.c
 components/nvs_flash/host_test/fixtures/test_fixtures.hpp
 components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp
 components/nvs_flash/include/nvs.h