Ver Fonte

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 há 4 anos atrás
pai
commit
d2b894862c

+ 10 - 0
CMakeLists.txt

@@ -209,6 +209,16 @@ if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
     list(APPEND compile_options "-fno-use-cxa-atexit")
     list(APPEND compile_options "-fno-use-cxa-atexit")
 endif()
 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(COMPILE_OPTIONS "${compile_options}" APPEND)
 idf_build_set_property(C_COMPILE_OPTIONS "${c_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)
 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 0x000E if IDF_TARGET_ESP32H2_BETA_VERSION_2 # ESP32H2-TODO: IDF-3475
         default 0xFFFF
         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"
     menu "Build type"
 
 

+ 36 - 37
components/esp_rom/CMakeLists.txt

@@ -57,6 +57,8 @@ else()
     rom_linker_script("libgcc")
     rom_linker_script("libgcc")
 endif()
 endif()
 
 
+idf_build_get_property(time_t_size TIME_T_SIZE)
+
 if(BOOTLOADER_BUILD)
 if(BOOTLOADER_BUILD)
     if(target STREQUAL "esp32")
     if(target STREQUAL "esp32")
         rom_linker_script("newlib-funcs")
         rom_linker_script("newlib-funcs")
@@ -91,19 +93,20 @@ else() # Regular app build
         rom_linker_script("syscalls")
         rom_linker_script("syscalls")
 
 
         if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND)
         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")
             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")
                 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)
                 if(CONFIG_NEWLIB_NANO_FORMAT)
+                    # nano formatting functions in ROM are also built for 32-bit time_t.
                     rom_linker_script("newlib-nano")
                     rom_linker_script("newlib-nano")
                 endif()
                 endif()
-
             endif()
             endif()
         endif()
         endif()
 
 
@@ -120,52 +123,48 @@ else() # Regular app build
         rom_linker_script("newlib-data")
         rom_linker_script("newlib-data")
         rom_linker_script("spiflash")
         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)
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
                 rom_linker_script("newlib-nano")
             endif()
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
         endif()
 
 
-
-        # descirptors used by ROM code
-        target_sources(${COMPONENT_LIB} PRIVATE "esp32s2/usb_descriptors.c")
-
     elseif(target STREQUAL "esp32s3")
     elseif(target STREQUAL "esp32s3")
         rom_linker_script("newlib")
         rom_linker_script("newlib")
         rom_linker_script("version")
         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)
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
                 rom_linker_script("newlib-nano")
             endif()
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
         endif()
 
 
     elseif(target STREQUAL "esp32c3")
     elseif(target STREQUAL "esp32c3")
         rom_linker_script("newlib")
         rom_linker_script("newlib")
         rom_linker_script("version")
         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)
             if(CONFIG_NEWLIB_NANO_FORMAT)
+                # nano formatting functions in ROM are also built for 32-bit time_t.
                 rom_linker_script("newlib-nano")
                 rom_linker_script("newlib-nano")
             endif()
             endif()
-
-            rom_linker_script("newlib-time")
         endif()
         endif()
 
 
         if(CONFIG_ESP32C3_REV_MIN_3)
         if(CONFIG_ESP32C3_REV_MIN_3)
@@ -176,10 +175,10 @@ else() # Regular app build
         rom_linker_script("newlib")
         rom_linker_script("newlib")
         rom_linker_script("version")
         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()
         endif()
 
 
     elseif(target STREQUAL "esp8684")
     elseif(target STREQUAL "esp8684")
@@ -187,10 +186,10 @@ else() # Regular app build
         rom_linker_script("version")
         rom_linker_script("version")
         rom_linker_script("mbedtls")
         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()
     endif()
     endif()
 
 

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

@@ -1,4 +1,5 @@
 #include <stdio.h>
 #include <stdio.h>
+#include <string.h>
 #include <math.h>
 #include <math.h>
 #include "unity.h"
 #include "unity.h"
 #include "driver/adc.h"
 #include "driver/adc.h"
@@ -446,8 +447,7 @@ TEST_CASE("test posix_timers clock_... functions", "[newlib]")
     test_posix_timers_clock();
     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)
 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 )
 #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 <errno.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -37,12 +29,6 @@
 
 
 #include "sdkconfig.h"
 #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
 #if !CONFIG_ESP_TIME_FUNCS_USE_NONE
 #define IMPL_NEWLIB_TIME_FUNCS 1
 #define IMPL_NEWLIB_TIME_FUNCS 1
 #endif
 #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
             If the chip already has the spiffs image with the time field = 32 bits
             then this option cannot be applied in this case.
             then this option cannot be applied in this case.
             Erase it first before using this option.
             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"
     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.
 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
 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
 .. 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::
 Build the toolchain::
 
 
     ./ct-ng {IDF_TARGET_TOOLCHAIN_PREFIX}
     ./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/app_test.py
 components/newlib/test_apps/main/test_newlib_main.c
 components/newlib/test_apps/main/test_newlib_main.c
 components/newlib/test_apps/main/test_stdatomic.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/fixtures/test_fixtures.hpp
 components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp
 components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp
 components/nvs_flash/include/nvs.h
 components/nvs_flash/include/nvs.h