generate_BUFSIZ.sh: yet another tweak
[oweals/busybox.git] / scripts / generate_BUFSIZ.sh
1 #!/bin/sh
2 # Called from top-level directory a-la
3 #
4 # scripts/generate_BUFSIZ.sh include/common_bufsiz.h
5
6 . ./.config || exit 1
7
8 debug=false
9 #debug=true
10
11 postcompile=false
12 test x"$1" = x"--post" && { postcompile=true; shift; }
13
14 common_bufsiz_h=$1
15
16 test x"$NM" = x"" && NM="${CONFIG_CROSS_COMPILER_PREFIX}nm"
17 test x"$CC" = x"" && CC="${CONFIG_CROSS_COMPILER_PREFIX}gcc"
18
19 exitcmd="exit 0"
20
21 regenerate() {
22         cat >"$1.$$"
23         test -f "$1" && diff "$1.$$" "$1" >/dev/null && rm "$1.$$" && return
24         mv "$1.$$" "$1"
25 }
26
27 generate_std_and_exit() {
28         $debug && echo "Configuring: bb_common_bufsiz1[] in bss"
29         {
30         echo "enum { COMMON_BUFSIZE = 1024 };"
31         echo "extern char bb_common_bufsiz1[];"
32         echo "#define setup_common_bufsiz() ((void)0)"
33         } | regenerate "$common_bufsiz_h"
34         echo "std" >"$common_bufsiz_h.method"
35         $exitcmd
36 }
37
38 generate_big_and_exit() {
39         $debug && echo "Configuring: bb_common_bufsiz1[] in _end[], COMMON_BUFSIZE = $1"
40         {
41         echo "enum { COMMON_BUFSIZE = $1 };"
42         echo "extern char _end[]; /* linker-provided label */"
43         echo "#define bb_common_bufsiz1 _end"
44         echo "#define setup_common_bufsiz() ((void)0)"
45         } | regenerate "$common_bufsiz_h"
46         echo "$2" >"$common_bufsiz_h.method"
47         $exitcmd
48 }
49
50 generate_1k_and_exit() {
51         generate_big_and_exit 1024 "1k"
52 }
53
54
55 generate_malloc_and_exit() {
56         $debug && echo "Configuring: bb_common_bufsiz1[] is malloced"
57         {
58         echo "enum { COMMON_BUFSIZE = 1024 };"
59         echo "extern char *const bb_common_bufsiz1;"
60         echo "void setup_common_bufsiz(void);"
61         } | regenerate "$common_bufsiz_h"
62         echo "malloc" >"$common_bufsiz_h.method"
63         $exitcmd
64 }
65
66 round_down_COMMON_BUFSIZE() {
67         COMMON_BUFSIZE=$(( ($1-32) & 0xfffffe0 ))
68         COMMON_BUFSIZE=$(( COMMON_BUFSIZE < 1024 ? 1024 : COMMON_BUFSIZE ))
69 }
70
71 # User does not want any funky stuff?
72 test x"$CONFIG_FEATURE_USE_BSS_TAIL" = x"y" || generate_std_and_exit
73
74 # The script is run two times: before compilation, when it needs to
75 # (re)generate $common_bufsiz_h, and directly after successful build,
76 # when it needs to assess whether the build is ok to use at all (not buggy),
77 # and (re)generate $common_bufsiz_h for a future build.
78
79 if $postcompile; then
80         # Postcompile needs to create/delete OK/FAIL files
81
82         test -f busybox_unstripped || exit 1
83         test -f "$common_bufsiz_h.method" || exit 1
84
85         # How the build was done?
86         method=`cat -- "$common_bufsiz_h.method"`
87
88         # Get _end address
89         END=`$NM busybox_unstripped | grep ' . _end$'| cut -d' ' -f1`
90         test x"$END" = x"" && generate_std_and_exit
91         $debug && echo "END:0x$END $((0x$END))"
92         END=$((0x$END))
93
94         # Get PAGE_SIZE
95         {
96         echo "#include <sys/user.h>"
97         echo "#if defined(PAGE_SIZE) && PAGE_SIZE > 0"
98         echo "char page_size[PAGE_SIZE];"
99         echo "#endif"
100         } >page_size_$$.c
101         $CC -c "page_size_$$.c" || exit 1
102         PAGE_SIZE=`$NM --size-sort "page_size_$$.o" | cut -d' ' -f1`
103         rm "page_size_$$.c" "page_size_$$.o"
104         test x"$PAGE_SIZE" = x"" && exit 1
105         $debug && echo "PAGE_SIZE:0x$PAGE_SIZE $((0x$PAGE_SIZE))"
106         PAGE_SIZE=$((0x$PAGE_SIZE))
107         test $PAGE_SIZE -lt 512 && exit 1
108
109         # How much space between _end[] and next page?
110         PAGE_MASK=$((PAGE_SIZE-1))
111         TAIL_SIZE=$(( (-END) & PAGE_MASK ))
112         $debug && echo "TAIL_SIZE:$TAIL_SIZE bytes"
113
114         if test x"$method" = x"1k" || test x"$method" = x"big"; then
115                 if test $TAIL_SIZE -lt 1024; then
116                         # _end[] has no enough space for bb_common_bufsiz1[]
117                         echo "Warning! Space in _end[] is too small ($TAIL_SIZE bytes)!"
118                         echo "Rerun make to build a binary which doesn't use it!"
119                         rm -- "$common_bufsiz_h.1k.OK" 2>/dev/null
120                         { md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config; } >"$common_bufsiz_h.1k.FAIL"
121                         rm busybox_unstripped busybox 2>/dev/null
122 # Note: here we can do either a "malloc" or "std" build.
123 # "malloc" gives a bit bigger code:
124 #     text  bss filename
125 #   804355 5385 busybox.std
126 #   804618 4361 busybox.malloc
127 # but may have a smaller .bss (not guaranteed!). Use "pmap -x" to verify.
128                         exitcmd="exit 1"
129                         generate_malloc_and_exit
130                 else
131                         PREV_SIZE=1024
132                         test x"$method" = x"big" && PREV_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
133                         round_down_COMMON_BUFSIZE $PREV_SIZE
134                         PREV_BUFSIZE=$COMMON_BUFSIZE
135
136                         rm -- "$common_bufsiz_h.1k.FAIL" 2>/dev/null
137                         echo $TAIL_SIZE >"$common_bufsiz_h.1k.OK"
138                         round_down_COMMON_BUFSIZE $TAIL_SIZE
139                         # emit message only if COMMON_BUFSIZE is indeed larger
140                         test $COMMON_BUFSIZE -gt $PREV_BUFSIZE \
141                                 && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)"
142 #TODO: test $PREV_BUFSIZE -lt $TAIL_SIZE && PANIC!!!
143 #Code size with COMMON_BUFSIZE > 1024 may be bigger than code with COMMON_BUFSIZE = 1024!
144 #(currently we just hope "-32 and round down to 32" saves us)
145
146                         test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
147                         generate_big_and_exit $COMMON_BUFSIZE "big"
148                 fi
149         fi
150 fi
151
152 # Based on past success/fail of 1k build, decide next build type
153
154 if test -f "$common_bufsiz_h.1k.OK"; then
155         # Previous build succeeded fitting 1k into _end[].
156         # Try bigger COMMON_BUFSIZE if possible.
157         TAIL_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
158         round_down_COMMON_BUFSIZE $TAIL_SIZE
159         test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
160         generate_big_and_exit $COMMON_BUFSIZE "big"
161 fi
162
163 if test -f "$common_bufsiz_h.1k.FAIL"; then
164         # Previous build FAILED to fit 1k into _end[].
165         # Was it with same .config?
166         oldcfg=`cat -- "$common_bufsiz_h.1k.FAIL"`
167         curcfg=`md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config`
168         # If yes, then build a "malloced" version
169         if test x"$oldcfg" = x"$curcfg"; then
170                 echo "Will not try 1k build, it failed before. Touch .config to override"
171 # Note: here we can do either a "malloc" or "std" build.
172                 generate_malloc_and_exit
173         fi
174         # else: try 1k version
175         echo "New .config, will try 1k build"
176         rm -- "$common_bufsiz_h.1k.FAIL"
177         generate_1k_and_exit
178 fi
179
180 # There was no 1k build yet. Try it.
181 generate_1k_and_exit