1{
2 stdenv,
3 fetchurl,
4 buildPackages,
5 lib,
6 fetchpatch,
7 texinfo,
8 # "newlib-nano" is what the official ARM embedded toolchain calls this build
9 # configuration that prioritizes low space usage. We include it as a preset
10 # for embedded projects striving for a similar configuration.
11 nanoizeNewlib ? false,
12}:
13
14stdenv.mkDerivation (finalAttrs: {
15 pname = "newlib";
16 version = "4.5.0.20241231";
17
18 src = fetchurl {
19 url = "ftp://sourceware.org/pub/newlib/newlib-${finalAttrs.version}.tar.gz";
20 sha256 = "sha256-M/EmBeAFSWWZbCXBOCs+RjsK+ReZAB9buMBjDy7IyFI=";
21 };
22
23 patches =
24 [
25 (fetchpatch {
26 name = "0001-newlib-Fix-mips-libgloss-support.patch";
27 url = "https://sourceware.org/git/?p=newlib-cygwin.git;a=patch;h=8a8fb570d7c5310a03a34b3dd6f9f8bb35ee9f40";
28 hash = "sha256-hWS/X0jf/ZFXIR39NvNDVhkR8F81k9UWpsqDhZFxO5o=";
29 })
30 ]
31 ++ lib.optionals nanoizeNewlib [
32 # https://bugs.gentoo.org/723756
33 (fetchpatch {
34 name = "newlib-3.3.0-no-nano-cxx.patch";
35 url = "https://gitweb.gentoo.org/repo/gentoo.git/plain/sys-libs/newlib/files/newlib-3.3.0-no-nano-cxx.patch?id=9ee5a1cd6f8da6d084b93b3dbd2e8022a147cfbf";
36 sha256 = "sha256-S3mf7vwrzSMWZIGE+d61UDH+/SK/ao1hTPee1sElgco=";
37 })
38 ];
39
40 depsBuildBuild = [
41 buildPackages.stdenv.cc
42 texinfo # for makeinfo
43 ];
44
45 # newlib expects CC to build for build platform, not host platform
46 preConfigure =
47 ''
48 export CC=cc
49 ''
50 +
51 # newlib tries to disable itself when building for Linux *except*
52 # when native-compiling. Unfortunately the check for "is cross
53 # compiling" was written when newlib was part of GCC and newlib
54 # was built along with GCC (therefore newlib was built to execute
55 # on the targetPlatform, not the hostPlatform). Unfortunately
56 # when newlib was extracted from GCC, this "is cross compiling"
57 # logic was not fixed. So we must disable it.
58 ''
59 substituteInPlace configure --replace 'noconfigdirs target-newlib target-libgloss' 'noconfigdirs'
60 substituteInPlace configure --replace 'cross_only="target-libgloss target-newlib' 'cross_only="'
61 '';
62
63 configurePlatforms = [
64 "build"
65 "target"
66 ];
67 # flags copied from https://community.arm.com/support-forums/f/compilers-and-libraries-forum/53310/gcc-arm-none-eabi-what-were-the-newlib-compilation-options
68 # sort alphabetically
69 configureFlags =
70 [
71 "--with-newlib"
72
73 # The newlib configury uses `host` to refer to the platform
74 # which is being used to compile newlib. Ugh. It does this
75 # because of its history: newlib used to be distributed with and
76 # built as part of gcc.
77 #
78 # To prevent nixpkgs from going insane, this package presents the
79 # "normal" view to the outside world: the binaries in $out will
80 # execute on `stdenv.hostPlatform`. We then fool newlib's build
81 # process into doing the right thing.
82 "--host=${stdenv.targetPlatform.config}"
83
84 ]
85 ++ (
86 if !nanoizeNewlib then
87 [
88 "--disable-newlib-supplied-syscalls"
89 "--disable-nls"
90 "--enable-newlib-io-c99-formats"
91 "--enable-newlib-io-long-long"
92 "--enable-newlib-reent-check-verify"
93 "--enable-newlib-register-fini"
94 "--enable-newlib-retargetable-locking"
95 ]
96 else
97 [
98 "--disable-newlib-fseek-optimization"
99 "--disable-newlib-fvwrite-in-streamio"
100 "--disable-newlib-supplied-syscalls"
101 "--disable-newlib-unbuf-stream-opt"
102 "--disable-newlib-wide-orient"
103 "--disable-nls"
104 "--enable-lite-exit"
105 "--enable-newlib-global-atexit"
106 "--enable-newlib-nano-formatted-io"
107 "--enable-newlib-nano-malloc"
108 "--enable-newlib-reent-check-verify"
109 "--enable-newlib-reent-small"
110 "--enable-newlib-retargetable-locking"
111 ]
112 );
113
114 enableParallelBuilding = true;
115 dontDisableStatic = true;
116
117 # apply necessary nano changes from https://developer.arm.com/-/media/Files/downloads/gnu/12.2.rel1/manifest/copy_nano_libraries.sh?rev=4c50be6ccb9c4205a5262a3925317073&hash=1375A7B0A1CD0DB9B9EB0D2B574ADF66
118 postInstall =
119 lib.optionalString nanoizeNewlib ''
120 mkdir -p $out${finalAttrs.passthru.incdir}/newlib-nano
121 cp $out${finalAttrs.passthru.incdir}/newlib.h $out${finalAttrs.passthru.incdir}/newlib-nano/
122
123 (
124 cd $out${finalAttrs.passthru.libdir}
125
126 for f in librdimon.a libc.a libm.a libg.a libgloss.a; do
127 # Some libraries are only available for specific architectures.
128 # For example, librdimon.a is only available on ARM.
129 if [ -f "$f" ]; then
130 dst="''${f%%\.a}_nano.a"
131 >&2 echo "$f -> $dst"
132 cp "$f" "$dst"
133 fi
134 done
135 )
136 ''
137 + ''[ "$(find $out -type f | wc -l)" -gt 0 ] || (echo '$out is empty' 1>&2 && exit 1)'';
138
139 passthru = {
140 incdir = "/${stdenv.targetPlatform.config}/include";
141 libdir = "/${stdenv.targetPlatform.config}/lib";
142 };
143
144 meta = with lib; {
145 description = "C library intended for use on embedded systems";
146 homepage = "https://sourceware.org/newlib/";
147 # arch has "bsd" while gentoo has "NEWLIB LIBGLOSS GPL-2" while COPYING has "gpl2"
148 # there are 5 copying files in total
149 # COPYING
150 # COPYING.LIB
151 # COPYING.LIBGLOSS
152 # COPYING.NEWLIB
153 # COPYING3
154 license = licenses.gpl2Plus;
155 };
156})