-
Notifications
You must be signed in to change notification settings - Fork 0
/
p44b
executable file
·2140 lines (1941 loc) · 73.5 KB
/
p44b
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
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# p44b: host script for managing OpenWrt based product builds
# usage
command:usage() {
notice "Usage:"
echo " ${SCRIPTNAME} <command> --help - show help for <command>"
info "Setup and cleanup"
echo " ${SCRIPTNAME} new <p44build_dir> - create a fresh p44build directory as a starting point for a new project"
echo " ${SCRIPTNAME} init <p44build_dir> - initialize buildroot from a an existing p44build directory"
echo " ${SCRIPTNAME} switch <p44build_dir> - (try to) switch to a p44build source directory w/o changing buildroot (possible if patches are equal)"
echo " ${SCRIPTNAME} prepare - prepare (patch) tree from ${ALIAS} info"
echo " ${SCRIPTNAME} instpkg - install those packages from feeds that were present at last ${ALIAS} save"
echo " ${SCRIPTNAME} restore [opts] <what>... - restore saved state, --apply to actually modify"
echo " ${SCRIPTNAME} cleanup - clean up buildroot from all p44b stuff (patches, extra files)"
echo " ${SCRIPTNAME} tidy - remove debris such as macOS .DS_Store files from buildroot"
info "Build commands (in usual sequence)"
echo " ${SCRIPTNAME} target [<target>] - list targets or switch to specified target configuration"
echo " ${SCRIPTNAME} build [<args>...] - call build.sh script if existing, otherwise just call (g)make, with optional args"
echo " ${SCRIPTNAME} package [<args>...] - call package.sh script with with optional args"
echo " ${SCRIPTNAME} deploy [<args>...] - call deploy.sh script with optional args"
echo " ${SCRIPTNAME} flash [<args>...] - call flash.sh script with optional args"
echo " ${SCRIPTNAME} save - save current build's SHAs of buildroot and tracked packages"
echo " ${SCRIPTNAME} commitversion [-f|--freeze] - commit the currently saved version to the feed the p44build directory is in"
echo " ${SCRIPTNAME} tagversion [-p|--packages] - tag the currently saved and committed version"
echo " ${SCRIPTNAME} pushversion <remote> - push the currently checked out branch and the version tag to remote"
info "Automated build of multiple targets"
echo " ${SCRIPTNAME} buildtargets [opts] <targets>... - switch to, build, package, save, commit, tag, deploy <targets>"
info "Testing and debugging"
echo " ${SCRIPTNAME} send [opts] <file> [<remote>] - send file/executable/package/debuggable to target"
echo " ${SCRIPTNAME} debug [<executable>] - start debugging <executable> with gdb"
echo " ${SCRIPTNAME} get <file> [<remote>] - get <remote file> to local <dir> (default: /tmp) from \$TARGET_HOST via scp"
echo " ${SCRIPTNAME} login [<host>] - connect to specified host or TARGET_HOST via ssh w/o identity checking"
echo " ${SCRIPTNAME} run <script> [<args>...] - run script from ${ALIAS} scripts folder"
echo " ${SCRIPTNAME} buildshell - start new shell with environment and PATH to directly work with compiler (in target build dir)"
# echo " source ${SCRIPTNAME} buildenv - set environment variables and PATH to directly work with compiler in build dirs"
echo " ${SCRIPTNAME} intenv - start new shell with environment set for p44b internal development / snippets trying"
echo " ${SCRIPTNAME} metapatch - 'meta'-patch (patch package, tool, kernel and record added patches in p44 global_patches)"
echo ""
}
help:buildenv() {
cat >&2 <<ENDHELP
Usage: source $0 buildenv
NOP AT THIS TIME
ENDHELP
}
include:buildenv() {
echo "NOP - Not yet implemented"
return
}
# Check if script is sourced
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
# script is being sourced
if [[ $# -lt 1 ]]; then
command:usage
return
fi
# global options
for OPT in $@ ; do
case "$OPT" in
"-h"|"--help") command:usage; return;;
*) break 2;;
esac
done
COMMAND="$1"
shift 1
# run includes
if [[ $SHELL == */zsh ]]; then
whence -w include:${COMMAND} >/dev/null;
else
type -t include:${COMMAND} | grep -q function;
fi
if [[ $? == 0 ]]; then
include:${COMMAND} "$@"
else
echo "Unknown subcommand ${COMMAND} for sourcing 'p44b'"
echo "${BASH_SOURCE[0]} --help # for more information"
fi
return
fi
# ssh options (needed to connect to old/unknown units with old crypto and maybe re-used IP/host address)
SSH_OPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-rsa"
# Helpers
err()
{
echo -e "$_ERR$@$_N"
}
warn()
{
echo -e "$_WARN$@$_N"
}
notice()
{
echo -e "$_NOTICE$@$_N"
}
info()
{
echo -e "$_INFO$@$_N"
}
plain()
{
echo -e "$_N$@"
}
die() {
err "*** Error:" $@
exit 1
}
starting() {
notice "=== starting" $@ "at $(date +%Y-%m-%d_%H:%M:%S)"
}
finished() {
if [[ "$?" == "0" ]]; then
notice "=== succeeded" $@ "at $(date +%Y-%m-%d_%H:%M:%S)"
return 0
else
err "=== failed" $@ "at $(date +%Y-%m-%d_%H:%M:%S)"
return 1
fi
}
syntax() {
# calling function
CMD="${FUNCNAME[1]##command:}"
err "Syntax error:" $@
help:$CMD
exit 1
}
has() {
# eg. has command update
local kind=$1
local name=$2
type -t $kind:$name | grep -q function
}
# colorisation
if [ -t 1 ]; then
if [ -z "$NO_COLOR" ]; then
_INFO='\033[90m' # info: gray (bright black)
_NOTICE='\033[92m' # notice: bright green
_ERR='\033[91m' # error: bright red
_WARN='\033[93m' # warning: bright yellow
_N='\033[m' # normal
fi
fi
findquilt() {
# DO NOT prefer self-built quilt over external one
QUILT=$(which quilt)
# # prefer self-built quilt over external one
# QUILT="${BUILDROOT}/staging_dir/host/bin/quilt"
# if [ ! -x $QUILT ]; then
# QUILT=$(which quilt)
# if [[ $? -ne 0 ]]; then
# die "need quilt to be installed externally"
# fi
# fi
}
# handle special internal commands
internal:quiltwrapper() {
findquilt
info "quiltwrapper $@"
info "- QUILT=$_N$QUILT"
info "- QUILTTARGET=$_N$QUILTTARGET"
info "- BUILDROOT=$_N$BUILDROOT"
info "- PACKAGEMAKEPATH=$_N$PACKAGEMAKEPATH"
info "- PACKAGEFILESPATH=$_N$PACKAGEFILESPATH"
case "$1" in
"import")
notice "to be implemented: handle 'import' in metapatch:$_N quilt $@"
# just forward to quilt for now
${QUILT} $@
;;
"new"|"import")
local PATCHPATH=$2
local PATCHNAME="${PATCHPATH}"
if [[ ${PATCHNAME} != *.patch ]]; then
die "patch name must have .patch file extension"
fi
if [[ $1 == "import" ]]; then
# extract patchname
PATCHNAME="${PATCHNAME##*/}"
fi
# make sure the (future) patch file is added to metapatch
pushd ${BUILDROOT} >/dev/null
${QUILT} add "${PACKAGEFILESPATH}/patches/${PATCHNAME}"
popd >/dev/null
# now forward to quilt
${QUILT} $@
;;
*)
# just forward to quilt
${QUILT} $@
;;
esac
}
case "${_p44_internal_cmd}" in
"_quiltwrapper") internal:quiltwrapper $@; exit 0;;
esac
# normal processing
# need extglob matching
shopt -s extglob
# must always be started from buildroot
BUILDROOT="$(pwd -P)"
if [ ! -f "${BUILDROOT}/feeds.conf.default" ]; then
error "${BUILDROOT} does not contain a feeds.conf.default -> not an openwrt buildroot"
die "Must be started from a openwrt buildroot"
fi
# the alias name to be used for referring to the script
ALIAS="p44b"
# find quilt for internal use
findquilt
# prefer gmake over make (because latter is usually outdated on macOS, while former - from brew - is ok)
MAKE=$(which gmake)
if [[ $? -ne 0 ]]; then
MAKE=$(which make)
fi
GMAKE_VERS_MAJ=$(${MAKE} --version | sed -E -n -e "/GNU Make/s/GNU Make ([0-9]+).*$/\1/p")
if (( ${GMAKE_VERS_MAJ} < 4 )); then
die "need a GNU gmake or make with Version >=4.0"
fi
#info "using ${MAKE}"
# create a temp diffconfig script that takes the right make version
DIFFCONFIG="/tmp/p44-diffconfig"
sed -E -e "s#make#${MAKE}#g" ./scripts/diffconfig.sh >${DIFFCONFIG}
chmod a+x ${DIFFCONFIG}
# defaults
if [ -z ${P44B_IMAGETYPE+x} ]; then
P44B_IMAGETYPE="squashfs-sysupgrade"
fi
# actual script location and file
SCRIPTDIR="$(dirname $0)"
pushd ${SCRIPTDIR} >/dev/null
SCRIPTDIR="$(pwd -P)"
popd >/dev/null
SCRIPTNAME="$(basename $0)"
SCRIPTFILE="${SCRIPTDIR}/${SCRIPTNAME}"
# derived
P44B_STATE_DIR="${BUILDROOT}/.p44build"
# from state, if existing
if [ -f "${P44B_STATE_DIR}/p44b_src_dir" ]; then
P44B_SRC_DIR=$(cat "${P44B_STATE_DIR}/p44b_src_dir")
if [ ! -d "${P44B_SRC_DIR}" ]; then
warn "Warning: ${ALIAS} source dir does not exist: '${P44B_SRC_DIR}'"
P44B_SRC_DIR=
fi
fi
if [ -f "${P44B_STATE_DIR}/target_id" ]; then
TARGET_ID=$(cat "${P44B_STATE_DIR}/target_id")
fi
# well-known subdirs of P44B_SRC_DIR
CONFIGS_DIR="configs"
TRACKING_DIR="tracking"
SCRIPTS_DIR="scripts"
GLOBAL_PATCHES_DIR="global-patches"
GLOB_TOOLS_PATH="${BUILDROOT}/staging_dir/host/bin:${BUILDROOT}/staging_dir/hostpkg/bin"
read_config()
{
pushd ${BUILDROOT} >/dev/null
# import .config:
if [[ $# -eq 0 ]]; then
local DOT_CONFIG_LOCATION="${P44B_SRC_DIR}/${CONFIGS_DIR}/.config-${TARGET_ID}"
else
if [[ "${1:0:1}" != "/" ]]; then
local DOT_CONFIG_LOCATION="${BUILDROOT}/$1"
else
local DOT_CONFIG_LOCATION="$1"
fi
fi
source "${DOT_CONFIG_LOCATION}" 2>/dev/null
# define derived vars
VERSION_TAG="${CONFIG_VERSION_NUMBER}"
if [ ! -z "${CONFIG_P44_FEED_NAME}" ]; then
VERSION_TAG="${CONFIG_P44_FEED_NAME}/${VERSION_TAG}"
fi
VERSION_TAG="${CONFIG_VERSION_PRODUCT}/${VERSION_TAG}/${TARGET_ID}"
# musl suffix
MUSL_SUFFIX=""
if [[ "${CONFIG_TARGET_SUFFIX#muslgnu}" == "eabi" ]]; then
MUSL_SUFFIX="_eabi"
fi
LIBCID="${CONFIG_LIBC}"
if [ ! -z "${CONFIG_LIBC_VERSION}" ]; then
LIBCID="${LIBCID}-${CONFIG_LIBC_VERSION}${MUSL_SUFFIX}"
else
LIBCID="${LIBCID}${MUSL_SUFFIX}"
fi
# target/toolchain identifying string
TARGETID="target-${CONFIG_ARCH}_${CONFIG_CPU_TYPE}_${LIBCID}"
TOOLCHAINID="toolchain-${CONFIG_ARCH}_${CONFIG_CPU_TYPE}_gcc-${CONFIG_GCC_VERSION}_${LIBCID}"
# build dir
BUILD_DIR="${BUILDROOT}/build_dir/${TARGETID}"
# toolchain root
TOOLCHAIN_ROOT="${BUILDROOT}/build_dir/${TOOLCHAINID}"
# staging dir and rootfs dir
STAGING_DIR="${BUILDROOT}/staging_dir/${TARGETID}"
STAGING_ROOTFS="${STAGING_DIR}/root-${CONFIG_TARGET_BOARD}"
STAGING_TOOLCHAIN="${BUILDROOT}/staging_dir/${TOOLCHAINID}"
# target bin dir
TARGET_BIN="${BUILDROOT}/bin/targets/${CONFIG_TARGET_BOARD}/${CONFIG_TARGET_SUBTARGET}"
# architecture bin dir
ARCH_BIN="${BUILDROOT}/bin/packages/${CONFIG_TARGET_ARCH_PACKAGES}"
# dist name
IMG_DIST_NAME="${CONFIG_VERSION_DIST}"
IMG_DIST_NAME_LC=$(echo "$IMG_DIST_NAME" | awk '{print tolower($0)}')
popd >/dev/null
}
set_script_env()
{
# publish some environment variables for called scripts
# - most recently built image
read_config ".config" # current settings, not saved ones
local SRCIMGS=$(ls -1t ${TARGET_BIN}/${IMG_DIST_NAME_LC}-${CONFIG_VERSION_NUMBER}*-${CONFIG_TARGET_BOARD}-${CONFIG_TARGET_SUBTARGET}-${CONFIG_TARGET_PROFILE##DEVICE_}-${P44B_IMAGETYPE}* 2>/dev/null);
if [[ $? -eq 0 ]]; then
set -- $SRCIMGS
export BUILT_IMAGE=$1
# determine the base name
export BUILT_IMAGE_BASENAME="${BUILT_IMAGE%-${P44B_IMAGETYPE}*}"
fi
# - also publish some dirs with P44B_ prefix for convenience in called scripts/commands
export BUILDROOT
export P44B_TARGET_ID="${TARGET_ID}"
export P44B_IMAGETYPE
export P44B_SRC_DIR
export P44B_CONFIGS_DIR="${P44B_SRC_DIR}/${CONFIGS_DIR}"
export P44B_TRACKING_DIR="${P44B_SRC_DIR}/${TRACKING_DIR}"
export P44B_SCRIPTS_DIR="${P44B_SRC_DIR}/${SCRIPTS_DIR}"
export P44B_GLOBAL_PATCHES_DIR="${P44B_SRC_DIR}/${GLOBAL_PATCHES_DIR}"
}
# echo "SCRIPTDIR=$SCRIPTDIR"
# echo "SCRIPTNAME=$SCRIPTNAME"
# echo "SCRIPTFILE=$SCRIPTFILE"
# echo "P44B_STATE_DIR=$P44B_STATE_DIR"
# echo "P44B_SRC_DIR=$P44B_SRC_DIR"
#
# exit 0
help:new() {
cat >&2 <<ENDHELP
Usage: [<path/to/script>]${SCRIPTNAME} ${FUNCNAME[0]##help:} <path to new p44build directory to create>
Create a new p44build directory with minimal/template files for managing a openwrt project
Does the following
- creates the specified directory and standard subdirectories as the p44build directory
- creates some standard global-patches needed for p44b operation
- creates dummy/example scripts for build/package/deploy/flash commands
- creates a template for tracking packages (tracked_packages)
- saves the current openwrt version as buildroot_checkout marker (using git describe)
- saves a diffconfig of the current openwrt .config as a default target config
ENDHELP
}
command:new() {
local NEW_P44B_DIR="$1"
if [[ $# -ne 1 ]]; then
syntax "must specify a path where to create new p44build directory"
fi
if [ -e "${NEW_P44B_DIR}" ]; then
die "'${NEW_P44B_DIR}' already exists"
fi
notice "creating new p44build default setup in ${NEW_P44B_DIR}"
# create and enter new p44build directory
info "creating new p44build dir"
if ! mkdir "${NEW_P44B_DIR}"; then
die "cannot create ${NEW_P44B_DIR}"
fi
pushd "${NEW_P44B_DIR}" >/dev/null
mkdir "${CONFIGS_DIR}"
mkdir "${SCRIPTS_DIR}"
mkdir "${GLOBAL_PATCHES_DIR}"
# create standard global patches
info "creating standard global patch to .gitignore p44b temprorary dirs/files in openwrt tree"
cat >"$GLOBAL_PATCHES_DIR/001-gitignore.diff" <<'ENDPATCH'
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,7 @@
/logs
/feeds
/feeds.conf
-/files
+#/files
/overlay
/package/feeds
/package/openwrt-packages
@@ -29,3 +29,8 @@ git-src
.project
.cproject
.ccache
+# p44build additions
+/patches
+/.pc
+/.p44build
+p44b
ENDPATCH
info "creating standard global patch to save git checkout markers in build dirs"
cat >"$GLOBAL_PATCHES_DIR/002-download-save-gitrev.diff" <<'ENDPATCH'
--- a/include/download.mk
+++ b/include/download.mk
@@ -205,7 +205,10 @@ define DownloadMethod/rawgit
[ \! -d $(SUBDIR) ] && \
git clone $(OPTS) $(URL) $(SUBDIR) && \
(cd $(SUBDIR) && git checkout $(VERSION) && \
- git submodule update --init --recursive) && \
+ git submodule update --init --recursive && \
+ echo "$(URL)" >.gitdownload_url && \
+ echo "$(VERSION)" >.gitdownload_version && \
+ git rev-parse HEAD >.gitdownload_rev) && \
echo "Packing checkout..." && \
export TAR_TIMESTAMP=`cd $(SUBDIR) && git log -1 --format='@%ct'` && \
rm -rf $(SUBDIR)/.git && \
ENDPATCH
# create tracking templates
info "creating tracked_packages template"
cat >"tracked_packages" <<'ENDTRACK'
# Specify packages for which git revision SHA/name should be recorded with each p44b save
# One package per line in the form: feedname/packagename, e.g. (without the #):
#plan44/serialfwd
ENDTRACK
# create script templates
info "creating script templates/examples for custom build/package/deploy/flash operations"
cat >"$SCRIPTS_DIR/build.sh" <<'ENDSCRIPT'
# Speed up make world
echo "Note: using all but one of the available processors/cores for building"
# prefer gmake over make (because latter might be outdated on Apple)
MAKE=$(which gmake)
if [[ $? -ne 0 ]]; then
MAKE=$(which make)
fi
${MAKE} -j$(($(nproc)-1))
ENDSCRIPT
cat >"$SCRIPTS_DIR/package.sh" <<'ENDSCRIPT'
# here you could perform steps to package (e.g. sign, rename, compress etc.) a built image
# The BUILT_IMAGE environment variable is set to the full path of the most recently built image
echo "No implementation for packaging"
exit 1
ENDSCRIPT
cat >"$SCRIPTS_DIR/deploy.sh" <<'ENDSCRIPT'
# here you could perform steps to deploy a built image (e.g. transfer it to a web server)
# The BUILT_IMAGE environment variable is set to the full path of the most recently built image
echo "No implementation for deploying"
exit 1
ENDSCRIPT
cat >"$SCRIPTS_DIR/flash.sh" <<'ENDSCRIPT'
# here you could perform steps to flash a target with the freshly built image
# The BUILT_IMAGE environment variable is set to the full path of the most recently built image
echo "No implementation for flashing"
exit 1
ENDSCRIPT
cat >"$SCRIPTS_DIR/buildprep.inc" <<'ENDSCRIPT'
# Here you can set environment variables and perform other preparation steps for a 'buildtargets' run.
# This file is sourced into the buildtargets run. If it does not return success, buildtargets is aborted.
# Example: when running commitversion, make sure not only changes in the p44build dir, but also
# in the enclosing dir (which is usually the "umbrella" openwrt package for the project) are committed,
# so stage these in advance now:
#pushd ${P44B_SRC_DIR}/.. >/dev/null
#git add .
#popd >/dev/null
# Example: get a user input needed for building and store it in a environment variable
# for a buildtargets step, for example a passphrase for a signing key etc.
#if [ -z "${NEEDEDVAR}" ]; then
# read -s -p "Need a user input: " NEEDEDVAR; echo
# export NEEDEDVAR
#fi
ENDSCRIPT
popd >/dev/null
# now back in dir from where we've been called (usually: openwrt buildroot)
if [[ -f ".config" ]]; then
# we are in a openwrt buildroot
# - save current openwrt checkout
local BUILDROOT_CHECKOUT=$(git describe HEAD)
info "recording current Openwrt checkout (${BUILDROOT_CHECKOUT}) in buildroot_checkout file"
echo "${BUILDROOT_CHECKOUT}" >"${NEW_P44B_DIR}/buildroot_checkout"
# - save current openwrt (diff)config
local TARGET_ID=$(sed -n -E -e 's/CONFIG_TARGET_PROFILE="DEVICE_([^"]*)"/\1/p' .config)
info "saving diffconfig of current openwrt .config as default target config named ${TARGET_ID}"
${DIFFCONFIG} >"${NEW_P44B_DIR}/${CONFIGS_DIR}/diffconfig-${TARGET_ID}"
cp .config "${NEW_P44B_DIR}/${CONFIGS_DIR}/.config-${TARGET_ID}"
else
warn "current directory does not seem to be a openwrt buildroot -> cannot save checkout/create default target"
fi
# done
notice "done creating p44build default setup in ${NEW_P44B_DIR}"
info "to start working with this you might want to run:"
plain " ${ALIAS} cleanup # to revert tree changes from current p44b project, if any"
plain " ${ALIAS} init ${NEW_P44B_DIR} # to start using the new project"
plain " ${ALIAS} prepare # to apply the patches"
plain " ${ALIAS} target ${TARGET_ID} # to apply the target config"
return 0
}
help:init() {
cat >&2 <<ENDHELP
Usage: [<path/to/script>]${SCRIPTNAME} ${FUNCNAME[0]##help:} <path to p44build source directory of a product>
Initialize a buildroot tree for p44b operation
Does the following
- put a softlink called "$ALIAS" pointing to the script itself into buildroot
(to allow easy calling with just ./${ALIAS})
- creates a .p44build directory in the buildroot
- remembers the product's p44build source directory in .p44build/p44b_src_dir
- sets a softlink to the P44B_SRC dir
ENDHELP
}
command:init() {
local NEW_P44B_DIR="$1"
if [[ $# -ne 1 ]]; then
syntax "must specify a path to a p44build directory"
fi
if [ ! -d "${NEW_P44B_DIR}" ]; then
die "'${NEW_P44B_DIR}' is not a directory"
fi
# create state directory
if [ -e "${P44B_STATE_DIR}" ]; then
die "p44build apparently already initialized - if not, please cleanup first"
fi
mkdir "${P44B_STATE_DIR}"
# expand and save the directory
pushd "${NEW_P44B_DIR}" >/dev/null
P44B_SRC_DIR="$(pwd -P)"
popd >/dev/null
echo -n "${P44B_SRC_DIR}" > "${P44B_STATE_DIR}/p44b_src_dir"
# find patches directory
local PATCHES_DIR="${GLOBAL_PATCHES_DIR}"
if [ ! -d "${P44B_SRC_DIR}/${PATCHES_DIR}" ]; then
# fall back to old name
PATCHES_DIR="lede-patches"
fi
# create soft link into buildroot to patch dir within sources
if [ -f "${BUILDROOT}/patches" ]; then
die "non-softlink '${BUILDROOT}/patches' already exists"
fi
ln -sfn "${P44B_SRC_DIR}/${PATCHES_DIR}" "${BUILDROOT}/patches"
# create convenience soft link to script itself in buildroot (but do not replace regular file, should there be one)
if [ ! -f "${BUILDROOT}/${ALIAS}" ]; then
ln -sfn "${SCRIPTFILE}" "${BUILDROOT}/${ALIAS}"
fi
# check for matching tracking info and warn if there are differences
local CURRENT=$(git rev-parse HEAD)
local SAVED=$(cat "${P44B_SRC_DIR}/${TRACKING_DIR}/buildroot_SHA")
if [[ "${CURRENT}" != "${SAVED}" ]]; then
warn "*** Warning: last buildroot saved was '${SAVED}', but is now at '${CURRENT}'"
warn " MOST PROBABLY, feeds.conf needs to be updated and"
warn " ./scripts/feeds update <feednames> should be applied!"
info "=== Diff between distribution's (recommended) feeds.conf.default and current feeds.conf"
diff feeds.conf.default feeds.conf;
info "=== end diff"
fi
info "=== Diff between last saved feeds.conf snapshot and current feeds.conf"
if ! diff ${P44B_SRC_DIR}/${TRACKING_DIR}/feeds.conf-snapshot feeds.conf; then
warn "*** Warning: current feeds.conf differs from snapshot -> maybe root was updated?"
fi
info "=== end diff"
notice "Successfully initialized p44build using directory: ${P44B_SRC_DIR}"
return 0
}
help:switch() {
cat >&2 <<ENDHELP
Usage: ${SCRIPTNAME} ${FUNCNAME[0]##help:} <path to p44build source directory of a product>
Switch to a different p44b directory without re-patching the buildroot tree.
This is only possible if the two p44b directories share the same tree checkout SHA
and the same set of patches in ${GLOBAL_PATCHES_DIR}
This makes switching between very similar projects faster, as keeping the patches in place
prevents triggering expensive rebuilds.
ENDHELP
}
command:switch() {
local NEW_P44B_DIR="$1"
if [[ $# -ne 1 ]]; then
syntax "must specify a path to a p44build directory"
fi
if [ ! -d "${NEW_P44B_DIR}" ]; then
die "'${NEW_P44B_DIR}' is not a directory"
fi
# state directory must exist
if [ ! -e "${P44B_STATE_DIR}" ]; then
die "p44build apparently not initialized, cannot switch - use 'init' first"
fi
# expand new name
pushd "${NEW_P44B_DIR}" >/dev/null
NEW_P44B_DIR="$(pwd -P)"
popd >/dev/null
# check for same openwrt tree state
local OLD_CHECKOUT=$(cat "${P44B_SRC_DIR}/buildroot_checkout")
local NEW_CHECKOUT=$(cat "${NEW_P44B_DIR}/buildroot_checkout")
if [[ "${OLD_CHECKOUT}" != "${NEW_CHECKOUT}" ]]; then
die "to-be-switched to directory is based on different buildroot checkout ('${NEW_CHECKOUT}' rather than '${OLD_CHECKOUT}') - use 'cleanup'/'init'"
fi
# clean feeds from MacOS folder state files (there could be some in the patches, too)
command:tidy
# check for same set of global patches (note: no check for legacy "lede-patches" here!)
local OLD_PATCHES="${P44B_SRC_DIR}/${GLOBAL_PATCHES_DIR}"
local NEW_PATCHES="${NEW_P44B_DIR}/${GLOBAL_PATCHES_DIR}"
if ! diff "${OLD_PATCHES}" "${NEW_PATCHES}"; then
die "global set of patches is not equal, cannot switch - use 'cleanup'/'init'"
fi
# make sure patches is a softlink
if [ ! -h "${BUILDROOT}/patches" ]; then
die "Error: '${BUILDROOT}/patches' is not a softlink!"
fi
# echo "patches dirs are equal: $OLD_PATCHES <-> $NEW_PATCHES"
# echo "P44B_STATE_DIR = $P44B_STATE_DIR"
# echo "NEW_P44B_DIR = $NEW_P44B_DIR"
# echo "BUILDROOT = $BUILDROOT"
# return 1
# switch is possible
# - un-target
rm "${P44B_STATE_DIR}/target_id" 2>/dev/null
rm "${BUILDROOT}/.config" 2>/dev/null
# - save the new p44build directory
echo -n "${NEW_P44B_DIR}" > "${P44B_STATE_DIR}/p44b_src_dir"
# - set the soft link in buildroot to the new (but identical) patch dir
ln -sfn "${NEW_P44B_DIR}/${GLOBAL_PATCHES_DIR}" "${BUILDROOT}/patches"
notice "Successfully switched to new p44build directory: ${NEW_P44B_DIR}"
return 0
}
help:cleanup() {
cat >&2 <<ENDHELP
Usage: ${SCRIPTNAME} ${FUNCNAME[0]##help:}
cleans up all changes made by init/prepare to the openwrt tree
In particular:
- the project specific .config is removed
- all patches applied to the tree (with ${SCRIPTNAME} prepare) are removed
(this is done with quilt pop -af in the buildroot)
- p44b specific softlinks and state is removed
Note: if state is not clean, the command will warn, but not reset the git checkout
(only recommend it)
ENDHELP
}
command:cleanup() {
if [[ $# -ne 0 ]]; then
syntax "no argument expected"
fi
# Cleanup buildroot
# - remove project specific config
rm "${BUILDROOT}/.config" 2>/dev/null
# - make sure patches are removed
pushd "${BUILDROOT}" >/dev/null
${QUILT} pop -af
# - remove the quilt working dir
rm -rf "${BUILDROOT}/.pc"
# - remove the softlink to the actual patches (but only softlink!)
if [ -h "${BUILDROOT}/patches" ]; then
rm "${BUILDROOT}/patches"
fi
# - remove the p44build state dir
if [ -d "${P44B_STATE_DIR}" ]; then
rm -rf "${P44B_STATE_DIR}"
fi
git status
info "# if status is not clean, you might want to use..."
plain "git reset --hard"
info "# ...here to bring the tree back into clean state"
popd >/dev/null
# Note: do not remove the convenience link (will be updated in case another version of the script is used explicitly)
return 0
}
help:prepare() {
cat >&2 <<ENDHELP
Usage: ${SCRIPTNAME} ${FUNCNAME[0]##help:}
Prepares (patches) the buildroot tree with project specific patches from ${GLOBAL_PATCHES_DIR}
In particular:
- removes current patches
- discards previous changes to the tree (if some are present, these will be stashed first)
- checks if buildroot checkoutr is as recorded in $P44B_SRC_DIR/buildroot_checkout
- applies all buildroot patches
- cleans feeds/ directory from macOS .DS_Store files which can interfere with builds
ENDHELP
}
# Prepare the tree
command:prepare() {
if [[ $# -ne 0 ]]; then
syntax "no argument expected"
fi
# checkout the buildroot checkout
if [ -f "${P44B_SRC_DIR}/buildroot_checkout" ]; then
local BUILDROOT_CHECKOUT=$(cat "${P44B_SRC_DIR}/buildroot_checkout")
pushd ${BUILDROOT} >/dev/null
# check current checkout
# - sha-wise
if git rev-parse HEAD | grep -q ${BUILDROOT_CHECKOUT}; then
# SHA matches
info "At correct SHA according to buildroot_checkout: ${BUILDROOT_CHECKOUT}"
elif git log -n1 --oneline --decorate=short HEAD | grep -q ${BUILDROOT_CHECKOUT}; then
# ref (branch, tag) matches
info "At correct ref according to buildroot_checkout: ${BUILDROOT_CHECKOUT}"
else
err "Error: buildroot must be at ${BUILDROOT_CHECKOUT}"
info "might want to use:"
plain " git checkout ${BUILDROOT_CHECKOUT}"
return 1
fi
# remove patches that might be there
${QUILT} pop -af
# stash just in case, to avoid loosing data
git stash
# switch to correct buildroot state
git reset --hard
# apply the patches
if ! ${QUILT} push -a; then
err "Error: applying global patches not completely successful"
info "(just use quilt manually to review, fix and apply all remaining patches to complete the 'prepare' operation)"
fi
# clean feeds from MacOS folder state files
command:tidy
# set flag
touch "${P44B_STATE_DIR}/prepared"
else
err "Error: no buildroot_checkout"
info "(might want to use ${TRACKING_DIR}/buildroot_SHA or ${TRACKING_DIR}/buildroot_VERS)"
exit 1
fi
}
help:instpkg() {
cat >&2 <<ENDHELP
Usage: ${SCRIPTNAME} ${FUNCNAME[0]##help:}
Installs all packages that were present at last ${SCRIPTNAME} save
(this is done by executing ${TRACKING_DIR}/install_packages.sh)
ENDHELP
}
command:instpkg() {
# checkout the buildroot checkout
if [ -f "${P44B_SRC_DIR}/${TRACKING_DIR}/install_packages.sh" ]; then
bash ${P44B_SRC_DIR}/${TRACKING_DIR}/install_packages.sh
else
warn "Warning: no install_packages.sh found."
info "You might want to install all packages instead with"
plain "./scripts/feeds install -a"
fi
}
help:target() {
cat >&2 <<ENDHELP
Usage:
${SCRIPTNAME} ${FUNCNAME[0]##help:} - list all targets
${SCRIPTNAME} ${FUNCNAME[0]##help:} <target> - configure for specified target
Applies configuration for the specified target to the buildroot from diffconfig saved
for the target (in ${CONFIGS_DIR}/diffconfig-<target>)
In particular:
- updates the package indices
- expands the saved diffconfig to a full .config (make defconfig)
ENDHELP
}
command:target() {
if [ ! -f "${P44B_STATE_DIR}/prepared" ]; then
die "buildroot is not yet prepared (global patches not applied) -> use ${SCRIPTNAME} prepare"
fi
if [[ $# -eq 0 ]]; then
# list targets
TARGETS="${P44B_SRC_DIR}/${CONFIGS_DIR}/diffconfig"*
notice "Available targets:"
for TG in ${TARGETS}; do
plain "- ${TG##*/diffconfig-}"
done
return 0
fi
if [[ $# -ne 1 ]]; then
syntax "specify single target"
fi
local NEW_TARGET_ID="$1"
local DIFFCONFIG="${P44B_SRC_DIR}/${CONFIGS_DIR}/diffconfig-${NEW_TARGET_ID}"
if [ ! -f "${DIFFCONFIG}" ]; then
die "buildroot configuration file '${DIFFCONFIG}' not found"
fi
# remember the target identifier
TARGET_ID="${NEW_TARGET_ID}"
echo -n "${TARGET_ID}" > "${P44B_STATE_DIR}/target_id"
# update the package indices
info "Updating package indices"
rm -rf ${BUILDROOT}/tmp 2>/dev/null
pushd ${BUILDROOT} >/dev/null
./scripts/feeds update -i
# copy the config and expand
info "Expanding diffconfig-${NEW_TARGET_ID} into full .config"
cp "${DIFFCONFIG}" "${BUILDROOT}/.config"
${MAKE} defconfig
popd >/dev/null
# show the status
command:status
}
help:restore() {
cat >&2 <<ENDHELP
Usage:
${SCRIPTNAME} ${FUNCNAME[0]##help:} [--apply] <restore operations>
Restore operations are:
root : checkout the saved buildroot tree version (never automatically, not even with --apply)
feeds : checkout the saved feed versions
packages : modify makefiles of tracked packages to point at the specific version in use at last save
target : apply diffconfig (as with ${SCRIPTNAME} target)
Options:
--apply : actually perform the restore (without --apply, needed changes are displayed only)
--sha : use exact SHA for buildroot, package feeds and tracked packages (rather than references/tags/branches)
ENDHELP
}
command:restore() {
if [[ $# -lt 1 ]]; then
syntax "need to specify what to restore"
fi
local BYSHA=0
local APPLY=0
local DO_ROOT=0
local DO_FEEDS=0
local DO_PACKAGES=0
local DO_TARGET=0
for OPT in $@ ; do
case "$OPT" in
"--sha") BYSHA=1;;
"--apply") APPLY=1;;
"root") DO_ROOT=1;;
"feeds") DO_FEEDS=1;;
"packages") DO_PACKAGES=1;;
"target") DO_TARGET=1;;
*) die "unknown option $OPT";;
esac
done
if [[ -z "${TARGET_ID}" || -z "${P44B_SRC_DIR}" ]]; then
die "No target selected, cannot restore"
fi
# diffconfig for current target
local CONFIGDIR="${P44B_SRC_DIR}/${CONFIGS_DIR}"
# check if buildroot matches
if [[ ${DO_ROOT} -ne 0 ]]; then
pushd "${BUILDROOT}" >/dev/null
local CONFIGDIR="${P44B_SRC_DIR}/${CONFIGS_DIR}"
if [[ ${BYSHA} -ne 0 ]]; then
local CURRENT=$(git rev-parse HEAD)
local SAVED=$(cat "${P44B_SRC_DIR}/${TRACKING_DIR}/buildroot_SHA")
else
local CURRENT=$(git rev-parse --abbrev-ref HEAD)
local SAVED=$(cat "${P44B_SRC_DIR}/${TRACKING_DIR}/buildroot_VERS")
fi
if [[ "${CURRENT}" != "${SAVED}" ]]; then
warn "Buildroot originally saved from was at '${SAVED}', but is now at '${CURRENT}'"
if [[ ${APPLY} -ne 0 ]]; then
die "Cannot continue, please manually checkout the correct buildroot commit"
fi
fi
notice "Buildroot state is correct: '${CURRENT}'"
# current feeds.conf
if ! cmp -s "${P44B_SRC_DIR}/${TRACKING_DIR}/feeds.conf-snapshot" feeds.conf; then
if [[ ${APPLY} -ne 0 ]]; then
warn "feeds.conf has changed: moving original to feeds.conf_ORIG and putting new one in place"
mv feeds.conf "feeds.conf_ORIG_$(date +%Y-%m-%d_%H:%M:%S)"
cp "${P44B_SRC_DIR}/${TRACKING_DIR}/feeds.conf-snapshot" feeds.conf
info "Updating and reindexing feeds"
./scripts/feeds update
else
warn "feeds.conf has changed:"
diff "${P44B_SRC_DIR}/${TRACKING_DIR}/feeds.conf-snapshot" feeds.conf
plain ""
fi
else
info "feeds.conf is unchanged"
fi
popd >/dev/null
fi
# check feed states
if [[ ${DO_FEEDS} -ne 0 ]]; then
if [[ ${BYSHA} -ne 0 ]]; then
local FEEDSTATES="${P44B_SRC_DIR}/${TRACKING_DIR}/feeds_SHA"
else
local FEEDSTATES="${P44B_SRC_DIR}/${TRACKING_DIR}/feeds_VERS"
fi
while IFS='' read -r line || [[ -n "$line" ]]; do
if [[ "${line:0:1}" != "#" ]]; then
local FEED="${line/ *}"
local spec="${line:((${#FEED}+1))}"
local URL="${spec%:*}"
local SAVED="${spec:((${#URL}+1))}"
pushd "${BUILDROOT}/feeds/${FEED}" >/dev/null
if [[ ${BYSHA} -ne 0 ]]; then
local CURRENT=$(git rev-parse HEAD)
else
local CURRENT=$(git rev-parse --abbrev-ref HEAD)
fi
popd >/dev/null
if [[ "${CURRENT}" != "${SAVED}" ]]; then
if [[ ${APPLY} -ne 0 ]]; then
notice "restoring feed '${FEED}' checkout from current '${CURRENT}' to saved '${SAVED}'"
pushd "${BUILDROOT}/feeds/${FEED}"; git stash; git checkout ${SAVED}; popd
else
warn "***** feed ${FEED} should be at '${SAVED}' but is at '${CURRENT}'"
info "You might want to checkout the correct version:"
plain "pushd ${BUILDROOT}/feeds/${FEED}; git stash; git checkout ${SAVED}; popd"
fi
fi
fi
done < "${FEEDSTATES}"
fi
# modify makefiles of tracked packages to point to saved versions
if [[ ${DO_PACKAGES} -ne 0 ]]; then
if [[ ${BYSHA} -ne 0 ]]; then
local PACKAGESTATES="${P44B_SRC_DIR}/${TRACKING_DIR}/packages_SHA"
else
local PACKAGESTATES="${P44B_SRC_DIR}/${TRACKING_DIR}/packages_VERS"
fi
while IFS='' read -r line || [[ -n "$line" ]]; do
if [[ "${line:0:1}" != "#" ]]; then
local pspec="${line/ *}"
local FEED="${pspec/\/*}"
local PNAME="${pspec:((${#FEED}+1))}"
local spec="${line:((${#pspec}+1))}"
local URL="${spec%:*}"
local SAVED="${spec:((${#URL}+1))}"
#echo "FEED=${FEED}, PNAME=${PNAME}, URL=${URL}, SAVED=${SAVED}"
pushd "${BUILDROOT}/feeds/${FEED}/${PNAME}" >/dev/null
local mfn="Makefile_ORIG_$(date +%Y-%m-%d_%H:%M:%S)"
sed -E \
-e "/PKG_SOURCE_URL:=/s|PKG_SOURCE_URL:=(.*)$|PKG_SOURCE_URL:=${URL}|" \
-e "/PKG_SOURCE_VERSION:=/s|PKG_SOURCE_VERSION:=(.*)$|PKG_SOURCE_VERSION:=${SAVED}|" \
Makefile > "/tmp/${mfn}"
if cmp -s Makefile "/tmp/${mfn}"; then
info "${FEED}/${PNAME}: Makefile unchanged"
else
if [[ ${APPLY} -ne 0 ]]; then
notice "${FEED}/${PNAME}: Makefile updated: PKG_SOURCE_URL='${URL}', PKG_SOURCE_VERSION='${SAVED}' - original: ${mfn}"
mv Makefile "${mfn}"
cp "/tmp/${mfn}" Makefile
else
warn "${FEED}/${PNAME}: Makefile needs to update: PKG_SOURCE_URL='${URL}', PKG_SOURCE_VERSION='${SAVED}'"
diff Makefile "/tmp/${mfn}"