-
Notifications
You must be signed in to change notification settings - Fork 104
/
zproject_rpi.gsl
428 lines (357 loc) · 12.1 KB
/
zproject_rpi.gsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# Generate cross compile environment for the Raspberry Pi
#
# This is a code generator built using the iMatix GSL code generation
# language. See https://github.com/zeromq/gsl for details.
#
# Copyright (c) the Contributors as noted in the AUTHORS file.
# This file is part of zproject.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
register_target ("rpi", "Raspberry Pi cross build system")
.macro target_rpi
.directory.create('builds/rpi')
.output "builds/rpi/build.sh"
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
# Set this to enable verbose profiling
[ -n "${CI_TIME-}" ] || CI_TIME=""
case "$CI_TIME" in
[Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee])
CI_TIME="time -p " ;;
[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee])
CI_TIME="" ;;
esac
# Set this to enable verbose tracing
[ -n "${CI_TRACE-}" ] || CI_TRACE="no"
case "$CI_TRACE" in
[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee])
set +x ;;
[Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee])
set -x ;;
esac
# Parse parameters
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-i|--incremental)
INCREMENTAL=0
;;
-u|--update)
UPDATE=0
;;
*)
# unknown option
;;
esac
shift # past argument or value
done
if [ $INCREMENTAL ] && [ $UPDATE ]; then
echo Error: Incremental and update are exclusiv!
exit -1
fi
# Download cross compiler and sysroot
if [ ! -d $PWD/tools ]; then
git clone --depth 1 https://github.com/raspberrypi/tools
fi
if [ $UPDATE ]; then
( cd tools && git pull --rebase ) || exit 1
fi
# Cross build for the Raspberry Pi
if [ -d "./tmp" ]; then
# Proto installation area for this project and its deps
rm -rf ./tmp
fi
if [ -d "./tmp-deps" ]; then
# Checkout/unpack and build area for dependencies
rm -rf ./tmp-deps
fi
mkdir -p tmp tmp-deps
BUILD_PREFIX=$PWD/tmp
TOOLCHAIN_HOST="arm-linux-gnueabihf"
TOOLCHAIN_PATH="${PWD}/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin"
SYSROOT=$PWD/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot
CFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
CPPFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
CXXFLAGS="--sysroot=${SYSROOT} -I${BUILD_PREFIX}/include"
LDFLAGS="-L${BUILD_PREFIX}/lib"
CONFIG_OPTS=()
CONFIG_OPTS+=("CFLAGS=${CFLAGS}")
CONFIG_OPTS+=("CPPFLAGS=${CPPFLAGS}")
CONFIG_OPTS+=("CXXFLAGS=${CXXFLAGS}")
CONFIG_OPTS+=("LDFLAGS=${LDFLAGS}")
CONFIG_OPTS+=("PKG_CONFIG_DIR=")
CONFIG_OPTS+=("PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/share/pkgconfig")
CONFIG_OPTS+=("PKG_CONFIG_SYSROOT=${SYSROOT}")
CONFIG_OPTS+=("PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig")
CONFIG_OPTS+=("--prefix=${BUILD_PREFIX}")
CONFIG_OPTS+=("--host=${TOOLCHAIN_HOST}")
CONFIG_OPTS+=("--with-docs=no")
CPP="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-cpp"
CC="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-gcc"
CXX="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-g++"
LD="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ld"
AS="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-as"
AR="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ar"
RANLIB="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ranlib"
CONFIG_OPTS+=("CPP=${CPP}")
CONFIG_OPTS+=("CC=${CC}")
CONFIG_OPTS+=("CXX=${CXX}")
CONFIG_OPTS+=("LD=${LD}")
CONFIG_OPTS+=("AS=${AS}")
CONFIG_OPTS+=("AR=${AR}")
CONFIG_OPTS+=("RANLIB=${RANLIB}")
if [ ! $INCREMENTAL ]; then
# Clone and build dependencies
. for use where defined (use.tarball)
BASE_PWD=${PWD}
cd tmp-deps
if [ ! -e \$(basename "$(use.tarball)") ]; then
$CI_TIME wget $(use.tarball)
tar -xzf \$(basename "$(use.tarball)")
fi
pushd \$(basename "$(use.tarball)" .tar.gz)
(
. if count(use.add_config_opts) > 0
( # Custom additional options for $(use.project)
. for use.add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
)
. else
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
. endif
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
cd ${BASE_PWD}
. endfor
. for use where defined (use.repository) & ! defined (use.tarball)
BASE_PWD=${PWD}
cd tmp-deps
if [ ! -e $(use.project) ]; then
. if defined (use.release)
$CI_TIME git clone --quiet --depth 1 -b $(use.release:) $(use.repository) $(use.project)
. else
$CI_TIME git clone --quiet --depth 1 $(use.repository) $(use.project)
. endif
fi
pushd $(use.project)
(
if [ $UPDATE ]; then
$CI_TIME git pull --rebase
fi
git --no-pager log --oneline -n1
if [ -e autogen.sh ]; then
$CI_TIME ./autogen.sh 2> /dev/null
fi
if [ -e buildconf ]; then
$CI_TIME ./buildconf 2> /dev/null
fi
if [ ! -e autogen.sh ] && [ ! -e buildconf ] && [ ! -e ./configure ] && [ -s ./configure.ac ]; then
$CI_TIME libtoolize --copy --force && \\
$CI_TIME aclocal -I . && \\
$CI_TIME autoheader && \\
$CI_TIME automake --add-missing --copy && \\
$CI_TIME autoconf || \\
$CI_TIME autoreconf -fiv
fi
. if count(use.add_config_opts) > 0
( # Custom additional options for $(use.project)
. for use.add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
)
. else
$CI_TIME ./configure "${CONFIG_OPTS[@]}"
. endif
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
cd ${BASE_PWD}
. endfor
fi
# Cross build this project
pushd ../..
(
. if count(add_config_opts) > 0
# Custom additional options for this project
. for add_config_opts as add_cfgopt
CONFIG_OPTS+=("$(add_cfgopt)")
. endfor
. endif
$CI_TIME ./autogen.sh 2> /dev/null
$CI_TIME ./configure --enable-drafts=yes "${CONFIG_OPTS[@]}"
$CI_TIME make -j4
$CI_TIME make install
) || exit 1
popd
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/build.sh")
.output "builds/rpi/build_image.sh"
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
# Cross compile this project and its dependencies
\./build.sh
# Get the latest Raspbian image and enlarge it so there is enough space to
# install to it.
sudo ./prepare_img.sh
# Sync with image
sudo rsync -avz --no-p --no-g --chmod=ugo=rwX tmp/ raspbian-root/usr
sudo proot -Q qemu-arm -B -r raspbian-root -b raspbian-boot:/boot sudo ldconfig
# Umount image
sync; sudo umount ./raspbian-boot ./raspbian-root
# Make sure all allocated loop devices are free'd
for i in {0..7};
do
sudo sudo dmsetup clear loop${i}p1 &&
sudo sudo dmsetup clear loop${i}p2 &&
sudo sudo dmsetup remove loop${i}p1 &&
sudo sudo dmsetup remove loop${i}p2 &&
sudo sudo losetup -d /dev/loop$i
done
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/build_image.sh")
.output("builds/rpi/prepare_img.sh")
#!/usr/bin/env bash
$(project.GENERATED_WARNING_HEADER:)
if [ ! -f $PWD/raspbian_lite_latest.zip ]; then
wget --connect-timeout=10 https://downloads.raspberrypi.org/raspbian_lite_latest -O raspbian_lite_latest.zip
fi
RASPBIAN_IMG=\$(unzip -Z1 raspbian_lite_latest.zip)
if [ ! -f $PWD/$RASPBIAN_IMG ]; then
unzip raspbian_lite_latest.zip
fi
if [ ! -f $PWD/raspbian_$(project.name:c).img ]; then
# Allocate disk space for extended image
truncate -s 1536M raspbian_$(project.name:c).img
# Begin partitioning disk image.
# Creating two partitions:
# BOOT = 100 MB
# ROOT = 1536 MB
fdisk raspbian_$(project.name).img <<EOF
o
n
p
1
+100M
t
c
n
p
2
w
EOF
# Create a loop device and mount the extended image's partitions
export LOOPDEV_EX="\$(losetup --show --find raspbian_$(project.name).img)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_EX
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Create file systems for the partitions
mkfs.vfat $BOOTPARTION_EX
mkfs.ext4 $ROOTPARTION_EX
# Create a loop device and mount the original image's partitions
export LOOPDEV_ORIG="\$(losetup --show --find $RASPBIAN_IMG)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_ORIG
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_ORIG=\$(echo $LOOPDEV_ORIG | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_ORIG=\$(echo $LOOPDEV_ORIG | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Copy data from original image to extended image
dd if=$BOOTPARTION_ORIG of=$BOOTPARTION_EX bs=64K conv=noerror,sync
dd if=$ROOTPARTION_ORIG of=$ROOTPARTION_EX bs=64K conv=noerror,sync
# Remove loop devices for original image
dmsetup clear $BOOTPARTION_ORIG
dmsetup clear $ROOTPARTION_ORIG
dmsetup remove $BOOTPARTION_ORIG
dmsetup remove $ROOTPARTION_ORIG
losetup -d $LOOPDEV_ORIG
fi
# Try to mount extended image
if [ -z "\$(mount|grep raspbian-boot)" ] && [ -z "\$(mount|grep raspbian-root)" ]; then
# Create a loop device and mount the disk image
export LOOPDEV_EX="\$(losetup --show --find ./raspbian_$(project.name).img)"
# Use sudo kpartx to create partitions in /dev/mapper
kpartx -av $LOOPDEV_EX
dmsetup --noudevsync mknodes
# Create partition names to mount
export BOOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p1
export ROOTPARTION_EX=\$(echo $LOOPDEV_EX | sed 's|'/dev'/|'/dev/mapper/'|')p2
# Make sure mount points exist and are clean
mkdir -p raspbian-boot
mkdir -p raspbian-root
rm -rf raspbian-boot/*
rm -rf raspbian-root/*
# Mount partitions
mount $BOOTPARTION_EX -t vfat raspbian-boot
mount $ROOTPARTION_EX -t ext4 raspbian-root
else
echo "Image already mounted!"
fi
$(project.GENERATED_WARNING_HEADER:)
.close
.chmod_x ("builds/rpi/prepare_img.sh")
.output "builds/rpi/README.md"
# Raspberry Pi
Cross compile environment for the Raspberry Pi (all models)
## Cross compile for Raspbian
Simply run
./build.sh
Once the build script finishes the installation data is located at `tmp/`.
To copy those files to your Raspberry Pi you can use `rsync`. Therefore
you'll have to make sure rsync is installed on the Raspberry Pi
apt-get install rsync
Next make sure your Pi user has sufficient access rights to copy data to
`/usr/local`. To force this you can use the following command to change
the ownership of the directory accordingly.
chown -R root:users /usr/local/
And finally sync your libraries to the Pi
rsync -avz tmp/ <pi-user>@<pi-ip>:/usr/local
The first time you install a library onto the Raspberry Pi you'll need to run
sudo ldconfig
During development running the build script with all dependencies just to test
a minor change is overkill. To run an incremental build use the option
`-i|--incremental` which will only build this project.
./build.sh --incremental
Once in a while you might want to update the dependencies. You can do this by
adding the option `-u|--update`.
./build.sh --update
Note that incremental and update are exclusiv options.
## Cross compile and install to Raspbian image
This requires sudo access rights on your local maschine. Also make sure
you have `kpartx`, `qemu-user` and `proot` installed.
To cross compile and install this project to an raspbian image run
./build_image.sh
This script will download the latest Raspbian image extend it so we can install
software into it and finally copy the cross compiled stuff to it. Once it's done
simple copy the image to a SD card and plug it into your Raspberry Pi.
```
$(project.GENERATED_WARNING_HEADER:)
```
.close
.output "builds/rpi/.gitignore"
. for use where defined (use.tarball)
$(use.project)*
. endfor
. for use where defined (use.repository) & ! defined (use.tarball)
$(use.project)
. endfor
raspbian-boot
raspbian-root
tmp/
tools/
*.img
*.zip
.close
.endmacro