Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to version 4.4.0 of newlib ? #598

Closed
Laur59 opened this issue Dec 13, 2024 · 11 comments
Closed

Move to version 4.4.0 of newlib ? #598

Laur59 opened this issue Dec 13, 2024 · 11 comments

Comments

@Laur59
Copy link

Laur59 commented Dec 13, 2024

I have seen that the patch for newlib was recently updated.

I wonder how much effort could take to update this patch so that the version of newlib used by the project is the latest, i.e. 4.4.0.

I know support of newlib is experimental. Just would be nice if the version of newlib can be more recent one.

@voltur01
Copy link
Contributor

Hi, I expect newlib-4.5.0 will be tagged soon, so we will try to update before the LLVM 20 based release. We are looking into upstreaming some of the uncontroversial changes as well to make the patch smaller.

@voltur01
Copy link
Contributor

voltur01 commented Jan 3, 2025

newlib was updated to 4.5.0 with #618

Unfortunately, newlib does not provide any tests, so feedback is welcome.

@Laur59
Copy link
Author

Laur59 commented Jan 3, 2025

Hi! Thanks!
A first quick feedback. I have built a toolchain with:

cmake -S ${SRC} -B ${BUILD} -GNinja \
    -DFETCHCONTENT_SOURCE_DIR_LLVMPROJECT=${SRC}/repos/llvm-project \
    -DFETCHCONTENT_SOURCE_DIR_PICOLIBC=${SRC}/repos/picolibc \
    -DLLVM_VERSION_SUFFIX=" (upstream $commithash)" \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_INSTALL_PREFIX=${PREFIX} -DLLVM_TOOLCHAIN_C_LIBRARY=newlib
cd ${BUILD}
ninja -j 15 llvm-toolchain
ninja install-llvm-toolchain

With this toolchain I could build binaries of our test platforms:

Using make and LLVM clang
Building all the systems with USER=1  ...
Alastor_H743/Variant_Test PASS
Nucleo_F207/Variant_Test PASS
Nucleo_H743/Variant_Test PASS
Nucleo_L4R5/Variant_Test PASS
Nucleo_U5A5/Variant_Test PASS
Discovery_U5A9/Variant_Test PASS
Discovery_U5A9/Variant_Test_Video PASS
Discovery_U5G9/Variant_Test PASS
Discovery_U5G9/Variant_Test_Video PASS
Longan_Nano_F103/Variant_Test PASS
Asmodee_H747/Variant_Test_CM4 PASS
Asmodee_H747/Variant_Test_CM7 PASS
Asmodee_H747/Variant_Test_CM7_Video PASS
DevKit_nRF5340/Variant_Test_Net PASS
DevKit_nRF5340/Variant_Test_App PASS
MAiXDUiNO_K210/Variant_Test PASS

Terminated!

Unfortunately there is some debugging needed as the binaries are core dumping. But as the code is building and running fine using gcc-14 and newlib-4.5.0 I presume should not be too hard to debug the building process. The binaries built with clang and picolibc are running fine.

I hope to update soon this comment with a running firmware.

@Laur59
Copy link
Author

Laur59 commented Jan 4, 2025

Follow-up on my trials.
In the process of building the elf file to be loaded on the board, I kept LLVM tools (clang, llvm-ar, llvm-objcopy) to compile the C source files and produce the required object files (.o) and libraries (.a). And I used arm-none-eabi-gcc (built from gcc-14.2.0, binutils-2.43.1, newlib-4.5.0) for the linking. The elf file that is built this way is running on the board.
I am now trying to find what is different in building the multilib newlib between gcc and LLVM.

@Laur59
Copy link
Author

Laur59 commented Jan 6, 2025

I checked that the problem is not due to patching newlib. I rebuilt my arm-none-eabi-gcc toolchain with newlib-4.5.0 patched with and adapted version of newlib patch of this project. This new gcc toolchain builds elf files that runs on the boards.
Now I have to check with the configure options used to build newlib.

@Laur59
Copy link
Author

Laur59 commented Jan 7, 2025

Here is my next trial

I built the toolchain with newlib as library.

Then using this toolchain I built again newlib with

export prefix=${CROSS}/${MACHINE}-newlib-LLVM

export CC_FOR_TARGET="${PATH_CROSS_COMPILER}/bin/clang"
export CXX_FOR_TARGET="${PATH_CROSS_COMPILER}/bin/clang++"
export AR_FOR_TARGET=${PATH_CROSS_COMPILER}/bin/llvm-ar
export NM_FOR_TARGET=${PATH_CROSS_COMPILER}/bin/llvm-nm
export RANLIB_FOR_TARGET=${PATH_CROSS_COMPILER}/bin/llvm-ranlib
export READELF_FOR_TARGET=${PATH_CROSS_COMPILER}/bin/llvm-readelf
export STRIP_FOR_TARGET=${PATH_CROSS_COMPILER}/bin/llvm-strip

rm -fr ${prefix}
cd ${BUILD}/${MACHINE}/newlib-${NLB_VER}
${PACKS_NLB}/configure \
    --target=${TARGET} \
    --prefix=${prefix} \
    --enable-multilib \
    --disable-werror \
    --disable-nls \
    --disable-libssp \
    ${NLB_CONFIG}   || { echo "Error configuring newlib"; exit 1; }
VERBOSE=1 make -j 4           || { echo "Error building newlib";    exit 1; }
make install        || { echo "Error installing newlib";  exit 1; }

I renamed the folder of the toolchain lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti to lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti_orig.
I created an new empty folder lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti. In this folder I copied the folder ${prefix}/arm-none-eabi/include that was created in the second build of newlib.
I copied the folder lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti_orig/lib in lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti.
Then I copied (replace mode) the contents of the folder ${prefix}arm-none-eabi/lib/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti into lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti_orig/lib.

With this hack I am able to compile/link/burn the code for a Nucleo_L4R5.

@voltur01
Copy link
Contributor

voltur01 commented Jan 7, 2025

Hi, thank you for looking into this!

I am afraid, I do not see what may have fixed the issue.

  1. I assume that building the whole toolchain with newlib as the library and building newlib as an overlay package should result in the same newlib headers and binaries - could you please confirm this from your build that they match?
  2. Do you introduce deliberate changes in your build steps above from what CMake is using, i.e. do you suggest that we need to update any newlib options in CMake?
  3. It looks like ${prefix}/arm-none-eabi/include folder is not created in the LLVM ET build, i.e. it is special to the build steps above. Is this correct? Presumably, it contains newlib headers, i.e. same or similar to one of lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti/include. Could you see what is the difference in the header files compared to ones generated by LLVM ET build?
  4. Following the multilib selection logic, the combination of headers from the build following instructions above and binaries form LLVM ET build works (the last step of copying files into the *_orig folder should not have had impact).

So if my understanding is correct, there is a difference in header files somewhere that if we know what it is we should try to eliminate, e.g. reusing some of the options form the build instructions above.

@Laur59
Copy link
Author

Laur59 commented Jan 7, 2025

  • I assume that building the whole toolchain with newlib as the library and building newlib as an overlay package should result in the same newlib headers and binaries - could you please confirm this from your build that they match?

From what I see all armv*/include folder are identical. The standalone build of newlib as a unique include folder which is quite identical to those folders:

diff -r ${prefix}/arm-none-eabi/include armv5te/include 
Only in armv5te/include: __libunwind_config.h
Only in armv5te/include: c++
Only in armv5te/include: libunwind.h
Only in armv5te/include: libunwind.modulemap
Only in armv5te/include: mach-o
diff -r /Users/scratch/todelete/embedded/cross/v-14.2.0-2.43.1-4.5.0-15.2/cortex-M-newlib-LLVM/arm-none-eabi/include/newlib.h armv5te/include/newlib.h
358c358
< /* #undef _LITE_EXIT */
---
> #define _LITE_EXIT 1
378c378
< /* #undef _RETARGETABLE_LOCKING */
---
> #define _RETARGETABLE_LOCKING 1
385c385
< /* #undef _WANT_IO_C99_FORMATS */
---
> #define _WANT_IO_C99_FORMATS 1
410c410
< /* #undef _WANT_REGISTER_FINI */
---
> #define _WANT_REGISTER_FINI 1
Only in armv5te/include: unwind.h
Only in armv5te/include: unwind_arm_ehabi.h
Only in armv5te/include: unwind_itanium.h

It is more difficult about the binaries. They are *.a files that cannot be compared directly (they surely will not match as usually there is a timestamp in the file). But a quick look with ls -l shows that they look quite different.

$ ls -l arm-none-eabi/lib/arm-none-eabi/armv4t/*.a
-rw-r--r--  2 lva  staff  4888072 Jan  7 11:33 libc.a
-rw-r--r--  2 lva  staff  4888072 Jan  7 11:33 libg.a
-rw-r--r--  1 lva  staff    15468 Jan  7 11:34 libgloss-linux.a
-rw-r--r--  1 lva  staff  1548054 Jan  7 11:33 libm.a
-rw-r--r--  1 lva  staff    85202 Jan  7 11:34 libnosys.a
-rw-r--r--  1 lva  staff    54326 Jan  7 11:34 librdimon-v2m.a
-rw-r--r--  1 lva  staff    54298 Jan  7 11:34 librdimon.a
-rw-r--r--  1 lva  staff    48294 Jan  7 11:34 librdpmon.a
$ ls -l lib/clang-runtimes/arm-none-eabi/armv4t/lib/*.a       
-rw-r--r--  1 lva  staff  1106344 Jan  7 15:03 libc.a
-rw-r--r--  1 lva  staff  1106344 Jan  7 15:03 libg.a
-rw-r--r--  1 lva  staff     7604 Jan  7 15:03 libgloss-linux.a
-rw-r--r--  1 lva  staff   555298 Jan  7 15:03 libm.a
-rw-r--r--  1 lva  staff    26826 Jan  7 15:03 libnosys.a
-rw-r--r--  1 lva  staff    15182 Jan  7 15:03 librdimon-v2m.a
-rw-r--r--  1 lva  staff    15154 Jan  7 15:03 librdimon.a
-rw-r--r--  1 lva  staff    12994 Jan  7 15:03 librdpmon.a
-rw-r--r--  1 lva  staff    45620 Jan  7 15:03 libunwind.a
-rw-r--r--  1 lva  staff  1139690 Jan  7 15:03 libc++.a
-rw-r--r--  1 lva  staff   461288 Jan  7 15:03 libc++abi.a
-rw-r--r--  1 lva  staff      696 Jan  7 15:03 libc++experimental.a
-rw-r--r--  1 lva  staff   142304 Jan  7 15:03 libclang_rt.builtins.a
-rw-r--r--  1 lva  staff     1392 Jan  7 15:03 libcrt0-nosys.a
-rw-r--r--  1 lva  staff     2210 Jan  7 15:03 libcrt0-rdimon.a

@Laur59
Copy link
Author

Laur59 commented Jan 7, 2025

  • Do you introduce deliberate changes in your build steps above from what CMake is using, i.e. do you suggest that we need to update any newlib options in CMake?

This was not deliberate changes. I just used the same configuration as we use when building newlib for gcc.
I will try now to use the same configuration as in CMakeLists.txt to build the standalone newlib.
Therefore, the answer is "no" I do not suggest any update for newlib in CMake.

@Laur59
Copy link
Author

Laur59 commented Jan 7, 2025

Check CMake config for newlib

Toolchain

Build the toolchain with -DLLVM_TOOLCHAIN_C_LIBRARY=newlib and install it in ${LLVM_ET_Arm}.

Standalone newlib

Using this toolchain to perform standalone build of newlib with same parameters as in CMakeLists.txt.

export CC_FOR_TARGET="${LLVM_ET_Arm}/bin/clang"
export CXX_FOR_TARGET="${LLVM_ET_Arm}/bin/clang++"
export AR_FOR_TARGET=${LLVM_ET_Arm}/bin/llvm-ar
export NM_FOR_TARGET=${LLVM_ET_Arm}/bin/llvm-nm
export RANLIB_FOR_TARGET=${LLVM_ET_Arm}/bin/llvm-ranlib
export READELF_FOR_TARGET=${LLVM_ET_Arm}/bin/llvm-readelf
export STRIP_FOR_TARGET=${LLVM_ET_Arm}/bin/llvm-strip
export CFLAGS_FOR_TARGET="-Wno-error=implicit-function-declaration -D__USES_INITFINI__ -UHAVE_INIT_FINI__ -U_HAVE_INIT_FINI__ -UHAVE_INIT_FINI --sysroot ${prefix}"
export CCASFLAGS="-Wno-error=implicit-function-declaration -D__USES_INITFINI__ -UHAVE_INIT_FINI__ -U_HAVE_INIT_FINI__ -UHAVE_INIT_FINI --sysroot ${prefix}"

rm -fr ${prefix}
cd ${BUILD}/${MACHINE}/newlib-${NLB_VER}
${PACKS_NLB}/configure \
    --target=${TARGET} \
    --prefix=${prefix} \
    --enable-newlib-io-long-long \
    --enable-newlib-register-fini \
    --disable-newlib-supplied-syscalls \
    --enable-newlib-io-c99-formats \
    --disable-nls \
    --enable-lite-exit \
    --enable-multilib \
    --enable-newlib-retargetable-locking   || { echo "Error configuring newlib"; exit 1; }
make -j 4           || { echo "Error building newlib";    exit 1; }
make install        || { echo "Error installing newlib";  exit 1; }

Compare include folders

cd ${LLVM_ET_Arm}/lib/clang-runtimes/arm-none-eabi
diff -r armv7m_hard_fpv4_sp_d16_exn_rtti/include ${prefix}/arm-none-eabi/include 
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: __libunwind_config.h
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: c++
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: libunwind.h
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: libunwind.modulemap
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: mach-o
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: unwind.h
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: unwind_arm_ehabi.h
Only in armv7m_hard_fpv4_sp_d16_exn_rtti/include: unwind_itanium.h

Include from standalone build is a subset of toolchain build. Therefore just keep it as is.

Replace binaries

Copy contents (replace mode) of ${prefix}/arm-none-eabi/lib/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti into ${LLVM_ET_Arm}/lib/clang-runtimes/arm-none-eabi/armv7m_hard_fpv4_sp_d16_exn_rtti/lib.

Build is running now on the board.

Conclusion

The config parameters in arm-runtimes/CMakeLists.txt look alright.

NOTE: building of standalone newlib was not using ${flags} because if my understanding is correct the value change at each iteration of the variants.

Sample of files for comparison

@Laur59
Copy link
Author

Laur59 commented Jan 25, 2025

I close this issue as (#630) is solving the problem.

@Laur59 Laur59 closed this as completed Jan 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants