Merge branch 'master' of github.com:sylware/cinitramfs
[cinitramfs.git] / make
blobbce2c176d577ca28f7acbd25102b02410a355f12
1 #!/bin/sh
3 #this script is brutal and verbose, has no tricks and is quite linear, then
4 #quite easy to deal with
5 #for the moment, it's hardcoded for a gcc toolchain... BAD! Since now
6 #gcc is a c++ piece of shit
8 # stolen from ffmpeg configure like a pig
9 set -e
11 # Prevent locale nonsense from breaking basic text processing.
12 LC_ALL=C
13 export LC_ALL
15 init_file_name=init
17 init_ulinux_src_files='
18 ulinux/utils/ascii/string/vsprintf.c
19 ulinux/utils/mem.c
20 ulinux/utils/ascii/string/conv/decimal/decimal.c
23 init_src_files="
24 uevents.c
25 modules.c
26 uevent.c
27 init.c
28 ramfs.c
29 $init_ulinux_src_files
32 clean_do()
34 rm -f static_modules.h
35 rm -f *.cpio.xz
36 rm -f *.cpio
37 rm -f cpio
38 rm -f $init_file_name
39 for init_src_file in $init_src_files
41 rm -f ${init_src_file/\.c/.pp.c}
42 rm -f ${init_src_file/\.c/.o}
43 #clean directories, but keep root of build tree
44 tgt_dir=$(dirname $init_src_file)
45 if test -d $tgt_dir -a "$tgt_dir" != "."; then
46 rmdir --ignore-fail-on-non-empty -p $tgt_dir
48 done
49 exit 0
52 sep_start()
54 echo '###############################################################################'
57 sep_end()
59 echo -e '###############################################################################\n'
62 subsep_start()
64 echo -e '*******************************************************************************'
67 subsep_end()
69 echo -e '*******************************************************************************'
71 ################################################################################
73 is_in(){
74 value=$1
75 shift
76 for var in $*; do
77 [ $var = $value ] && return 0
78 done
79 return 1
82 die_unknown(){
83 echo "Unknown option \"$1\"."
84 echo "See $0 --help for available options."
85 exit 1
88 set_default(){
89 for opt; do
90 eval : \${$opt:=\$${opt}_default}
91 done
94 CMDLINE_SET='
95 linux_src_dir
96 kernel_modules_base_dir
97 init_cpp
98 init_cc
99 init_ld
100 init_ulinux_arch
101 uevents_timeout
102 root_uuid
103 gen_init_cpio
104 kernel_release
105 extra_modules
106 pkg_config
107 readelf
108 elf_interpreter
110 #command line set defaults
111 #if the root is not around in less than 4s, something is really wrong
112 uevents_timeout_default=4000
113 root_uuid_default=00000000-0000-0000-0000-000000000000
114 gen_init_cpio_default='$linux_src_dir/usr/gen_init_cpio'
115 linux_src_dir_default=/usr/src/linux
116 #-------------------------------------------------------------------------------
117 #This defaults are for gcc, tested with version 4.7.3. You will need to
118 #override those for you compiler (tinycc/open64/pcc...). Additionnally, source
119 #support for different toolchains is not done.
120 #Since we use standard C runtime libs, be nice with the C runtime.
121 #The right way to do it is to have a toolchain abstraction layer since there are
122 #no standards for some
123 init_cpp_default='gcc -E -Wall -Wextra'
124 init_cc_default="gcc -Wall -Wextra -std=gnu99 -O0 \
125 -Wl,--dynamic-linker=/lib/ld.so -c"
126 init_ld_default='gcc -Wl,-O10,-s'
127 #-------------------------------------------------------------------------------
128 kernel_modules_base_dir_default=/
129 kernel_release_default=$(uname -r)
130 init_ulinux_arch_default=$(uname -m | sed -e s/i.86/i386/ -e s/parisc64/parisc/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
131 extra_modules_default=
132 pkg_config_default=pkg-config
133 readelf_default=readelf
134 elf_interpreter_default=
136 set_default $CMDLINE_SET
138 show_help(){
139 cat <<EOF
140 Usage: make [options] [operations]
142 Operations: [default is to build the the initramfs xz compressed cpio archive]:
143 clean clean build products
145 Options: [defaults in brackets after descriptions]
147 Help options:
148 --help print this message
150 Standard options:
151 --root-uuid=ROOT_UUID the uuid or the root filesystem to mount [$root_uuid_default]
152 --lib-path-list=LIB_PATH_LIST colon separated paths to look for target libraries
153 --uevents-timeout=UEVENTS_TIMEOUT uevents timeout in ms looking up for root block device to go online [$uevents_timeout]
154 --quiet init will be silenced (output code compiled out)
155 --no-tty init won't respawn login processes on ttys
156 --linux-src-dir=DIR where to find the target linux source tree [$linux_src_dir_default]
157 --kernel-release=RELEASE the linux releases version [$kernel_release]
158 --kernel-modules-base-dir=DIR the base dir for linux modules and support files [$kernel_modules_base_dir]
159 --extra-modules=EXTRA_MODULES coma separated list of extra module to probe
161 Advanced options:
162 --gen-init-cpio=GEN_INIT_CPIO_PATH use this linux host tool to build the linux cpio initramfs [$gen_init_cpio_default]
163 --pkg-config=PKG_CONFIG use PKG_CONFIG pkg-config command for target libraries [$pkg_config_default]
164 --readelf=READELF use READELF readelf command for target readelf [$readelf_default]
165 --elf-interpreter=ELF_INTERPRETER copy target ELF_INTERPRETER in cpio archive [will use the interpreter from the generated init elf binary]
166 --init-cpp=CPP use CPP compiler command line CPP for target init process [$init_cpp_default]
167 --init-cc=CC use C compiler command line CC for target init process objects [$init_cc_default]
168 --init-ld=LD use linker command line LD for target init process [$init_ld_default]
169 --init-ulinux-arch=ARCH use ulinux ARCH for target init process [$init_ulinux_arch]
171 exit 0
174 ################################################################################
176 for opt do
177 optval="${opt#*=}"
178 case "$opt" in
179 clean) clean_do
181 --help|-h) show_help
183 --quiet) CPPFLAGS="$CPPFLAGS -DQUIET"
185 --no_tty) CPPFLAGS="$CPPFLAGS -DNO_TTY"
188 optname=${opt%%=*}
189 optname=${optname#--}
190 optname=$(echo "$optname" | sed 's/-/_/g')
191 if is_in $optname $CMDLINE_SET; then
192 eval $optname='$optval'
193 else
194 die_unknown $opt
197 esac
198 done
200 ################################################################################
202 sep_start;echo 'looking for source path:'
203 if test -f make; then
204 src_path=.
205 else
206 src_path=$(cd $(dirname "$0"); pwd)
207 echo "$src_path" | grep -q '[[:blank:]]' &&
208 die "out of tree builds are impossible with whitespace in source path."
209 test -e "$src_path/config.h" &&
210 die "out of tree builds are impossible with config.h in source dir."
212 echo "source path is $src_path";sep_end
214 ################################################################################
216 sep_start;echo 'checking libkmod and libblkid pkgconfig support:'
217 if $pkg_config --exists libkmod blkid; then
218 echo "found pkg-config files for libkmod and libblkid"
219 else
220 echo "missing pkg-config file for libkmod or libblkid"
221 exit 1
223 sep_end
225 ################################################################################
227 #define variable in source
228 CPPFLAGS="$CPPFLAGS -DUEVENTS_TIMEOUT=$uevents_timeout"
229 CPPFLAGS="$CPPFLAGS -DROOT_UUID="$root_uuid""
230 CPPFLAGS="$CPPFLAGS $($pkg_config --cflags-only-I libkmod blkid)"
231 CFLAGS="$CFLAGS $($pkg_config --cflags-only-other libkmod blkid)"
232 LDFLAGS="$LDFLAGS $($pkg_config --libs libkmod blkid)"
234 ################################################################################
236 sep_start;echo 'configure ulinux src tree for target arch:'
237 rm -f $src_path/ulinux/arch
238 ln -s archs/$init_ulinux_arch $src_path/ulinux/arch
239 echo "init ulinux arch is $init_ulinux_arch"
240 sep_end
242 ################################################################################
244 #generated some code/headers
246 sep_start
247 revision=$(uname -r | egrep -o '^[[:digit:]]+\.[[:digit:]]+')
248 source $src_path/$revision
249 echo -e "linux revision is $revision, $src_path/$revision was sourced:\n--------"
250 cat $src_path/$revision
251 echo '--------'
252 sep_end
254 sep_start;echo 'generate static module list:'
255 $src_path/script/static_modules_h.sh $extra_modules $DISK_MODULES \
256 >./static_modules.h
257 cat ./static_modules.h
258 sep_end
260 ################################################################################
262 sep_start;echo 'C preprocess init src files:'
263 for init_src_file in $init_src_files
265 init_pp_c_file=${init_src_file/\.c/.pp.c}
266 echo "INIT_CPP $init_src_file->$init_pp_c_file"
267 mkdir -p $(dirname $init_pp_c_file)
268 $init_cpp $CPPFLAGS -I. -I$src_path -o $init_pp_c_file \
269 $src_path/$init_src_file
270 init_pp_c_files="$init_pp_c_file $init_pp_c_files"
271 done
272 sep_end
274 ################################################################################
276 sep_start;echo 'compile init preprocessed src files:'
277 for init_pp_c_file in $init_pp_c_files
279 init_obj_file=${init_pp_c_file/\.pp.c/.o}
280 echo "INIT_CC $init_pp_c_file-->$init_obj_file"
281 $init_cc $CFLAGS -o $init_obj_file $init_pp_c_file
282 init_obj_files="$init_obj_file $init_obj_files"
283 done
284 sep_end
286 ################################################################################
288 sep_start;echo 'link the init objects to produce the init binary:'
289 echo "INIT_LD $init_file_name"
290 $init_ld -o $init_file_name $init_obj_files $LDFLAGS
291 sep_end
293 ################################################################################
295 #build the library path used by the gcc toolchain. We will need it to lookup
296 #for the dynamic shared libraries and copy them into the cpio
297 sep_start;echo "computing gcc library path:"
298 #in gcc search paths, the sysroot uses '='
299 lib_path_nosysroot=$($init_ld $LDFLAGS -print-search-dirs | egrep '^libraries' \
300 | sed -r 's/libraries:[[:space:]]+(.+)/\1/')
301 echo "gcc library path is $lib_path_nosysroot"
302 gcc_sysroot=$($init_ld -print-sysroot)
303 echo "gcc_sysroot (can be empty) is $gcc_sysroot"
305 IFS=:
306 #replace the sysroot marker, '=', in gcc library path
307 if test -n "$gcc_sysroot"; then
308 for p in $lib_path_nosysroot; do
309 lib_path_norealpath="$lib_path_norealpath:$(echo $p | sed -r "s:^=:$gcc_sysroot:")"
310 done
311 else
312 for p in $lib_path_nosysroot; do
313 lib_path_norealpath="$lib_path_norealpath:$(echo $p | sed -r 's/^=//')"
314 done
316 for p in $lib_path_norealpath; do
317 if realpath -q "$p" &>/dev/null; then
318 lib_path="$lib_path:$(realpath "$p")"
320 done
321 lib_path=${lib_path#:}
322 echo "final LIB_PATH=$lib_path"
323 sep_end
325 ################################################################################
327 #locate the target elf interpreter which will be copied in the cpio archive
328 sep_start
329 if test -z "$elf_interpreter"; then
330 elf_interpreter=$($readelf -l ./init | egrep 'Requesting program interpreter' | sed -r 's/^.+interpreter:[[:space:]]*(.+)\]/\1/')
332 echo "will copy $elf_interpreter elf interpreter in cpio archive"
333 sep_end
335 ################################################################################
337 sep_start;echo 'generate the cpio source file:'
338 sed -e "s:@INIT_PATH@:$(realpath $init_file_name):" "$src_path/cpio.in" >cpio
339 echo "dir /lib/modules/$kernel_release 0755 0 0">>cpio
341 modules=$HW_MODULES,$DISK_MODULES,$FS_MODULES
342 if test -n $"extra_modules";then
343 modules=$modules,$extra_modules
346 subsep_start
347 #add proper entries in the cpio definition file related to linux modules
348 $src_path/script/cpio_modules_add.sh $kernel_modules_base_dir $kernel_release \
349 $modules ./cpio
350 subsep_end
352 subsep_start
353 #add proper entries in the cpio definition file related to shared elf libs
354 $src_path/script/cpio_libs_add.sh "$readelf" "$lib_path" ./init \
355 "$elf_interpreter" ./cpio
356 subsep_end
358 echo -e 'cpio source file is:\n--------'
359 cat cpio
360 echo '--------'
361 sep_end
363 ################################################################################
365 e_gen_init_cpio=$(eval echo "$gen_init_cpio")
366 $e_gen_init_cpio cpio >${kernel_release}.cpio
367 xz --force --check=crc32 --extreme --stdout ${kernel_release}.cpio >${kernel_release}.cpio.xz