summaryrefslogtreecommitdiffstats
path: root/opkg-buildpackage
blob: b7c0e8cb63b233d184a4b137e6d78a26336cc27e (plain)
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
#!/bin/sh
#
# Author: Oliver Kurth <oliver.kurth@innominate.com>
#
# Description:
# builds an opkg package from a source tarball using opkg-build. Idea stolen
# from Debian dpkg-buildpackage.
# 
# - unpack the source tarball.
# - cd to the source distribution, change whatever you need to make the
#   package compile and work on the ipaq.
# - create a directory 'opkg'
# - put all files which go to the 'CONTROL' directory of the root of the
#   installed package into opkg.
# - the version (Version field in control) should match the version of the
#   source tarball, optionally with a digit (eg. -1) appended.
# - additionally, put a file there called 'rules' which is a shell script
#   accepting arguments 'build', 'install' and 'clean'. It can be a 
#   Makefile starting with the line '#!/usr/bin/make -f'
#   * the build target does things like ./configure and make.
#   * the install target installs to a temporary directory (make
#   DESTDIR=/tmp/package) and removes unnecessary items (eg. man pages)
#   * clean cleans ;-)
#
# You should run this with fakeroot (1) or as root.
# If all went well, you will find a diff file and an *.opk file in the
# directory above.

set -e

SCRIPTDIR=/usr/local/bin

SCRIPTNAME=`basename $0`

opkg_extract_value() {
	sed -e "s/^[^:]*:[[:space:]]*//"
}

required_field() {
	field=$1

	value=`grep "^$field:" < $CONTROL/control | opkg_extract_value`
	if [ -z "$value" ]; then
		echo "opkg-build: Error: $CONTROL/control is missing field $field" ;
		PKG_ERROR=1
	fi
	echo $value
}

pkg_appears_sane_control() {
	local pkg_dir=$1

	local owd=`pwd`
	cd $pkg_dir

	if [ ! -f "$CONTROL/control" ]; then
		echo "opkg-build: Error: Control file $pkg_dir/$CONTROL/control not found."
		cd $owd
		return 1
	fi

	pkg=`required_field Package`
	version=`required_field Version | sed 's/.*://;'`
	arch=`required_field Architecture`
	required_field Maintainer >/dev/null
	required_field Description >/dev/null

	if echo $pkg | grep '[^a-z0-9.+-]'; then
		echo "opkg-build: Error: Package name $pkg contains illegal characters, (other than [a-z0-9.+-])"
		PKG_ERROR=1;
	fi

	local bad_fields=`sed -ne 's/^\([^[:space:]][^:[:space:]]\+[[:space:]]\+\)[^:].*/\1/p' < $CONTROL/control | sed -e 's/\\n//'`
	if [ -n "$bad_fields" ]; then
		bad_fields=`echo $bad_fields`
		echo "opkg-build: Error: The following fields in $CONTROL/control are missing a ':'"
		echo "	$bad_fields"
		echo "opkg-build: This may be due to a missing initial space for a multi-line field value"
		PKG_ERROR=1
	fi

	cd $owd
	return $PKG_ERROR
}

pkg_appears_sane_scripts() {
	local pkg_dir=$1

	local owd=`pwd`
	cd $pkg_dir

	for script in $CONTROL/preinst $CONTROL/postinst $CONTROL/prerm $CONTROL/postrm; do
		if [ -f $script -a ! -x $script ]; then
			echo "opkg-build: Error: package script $script is not executable"
			PKG_ERROR=1
		fi
	done

	cd $owd
	return $PKG_ERROR
}

pkg_dir_abs=`pwd`
pkg_dir_base=`basename ${pkg_dir_abs}`

pkg_dir=.

[ -d ./CONTROL ] && CONTROL=./CONTROL
[ -d ./opkg ] && CONTROL=./opkg
if [ -z "$CONTROL" ]; then
        echo "${SCRIPT_NAME}: Error: Directory $pkg_dir has no opkg or CONTROL subdirectory."
        exit 1
fi

if ! pkg_appears_sane_control $pkg_dir && pkg_appears_sane_control $pkg_dir; then
        echo "Please fix the above errors and try again."
        exit 1
fi

echo "Package = $pkg"
echo "Version = $version"
version_up=`echo ${version} | sed "s/\-[0-9]\+//"`
echo "Upstream Version = $version_up"
pkg_upname=${pkg}-${version_up}
echo "Package Name = $pkg_upname"
pkg_tarball=${pkg_upname}.tar.gz
echo "Tarball Name = $pkg_tarball"

if [ ! -x ${CONTROL}/rules ]; then
	echo "${CONTROL}/rules not found or not executable."
	exit 1
fi

#
# unpack upstream tarball and make diff
#
if [ -e ../${pkg_tarball} ] ; then
	(
	set +e

	cd ..

	rm -rf ${pkg_upname}.tmp
	rm -rf ${pkg_upname}.orig

	mkdir ${pkg_upname}.tmp
	cd ${pkg_upname}.tmp
	echo "unpacking source tarball ${pkg_tarball}"
	tar zxf ${pkg_dir_abs}/../${pkg_tarball}
	dir=`find . -maxdepth 1 -name "*" -type d`
	cnt=`echo $dir | wc -l`
	if [ ${cnt} != 1 ] ; then
		echo "Arrghh !!!!"
		echo "upstream package contains more than one top level directory"
		echo "giving up..."
		exit 1
	fi
	mv ${dir} ${pkg_upname}.orig
	mv ${pkg_upname}.orig ..
	cd ..
	echo "creating diff"
	diff -uNr  ${pkg_upname}.orig ${pkg_dir_base} > ${pkg}-${version}.diff
	rm -f ${pkg}-${version}.diff.gz
	echo "gzipping ${pkg}-${version}.diff"
	gzip ${pkg}-${version}.diff

	echo "Removing temporary source directorys"
	rm -rf ${pkg_upname}.tmp
	rm -rf ${pkg_upname}.orig
	)
fi

# build package
if ! ${CONTROL}/rules build; then
	echo "Build failed"
	exit 1
fi

# install it to tmp directory
if ! ${CONTROL}/rules install; then
	echo "Install failed"
	exit 1
fi

# copy contents of control directory
mkdir /tmp/${pkg}/CONTROL

files_required="control"
files_optional="preinst postinst prerm postrm"

for i in ${files_required} ; do
	file=${CONTROL}/$i
	
	if [ -e ${file} ] ; then
		cp $file /tmp/${pkg}/CONTROL
	else
		echo "required file ${file} missing"
	fi
done

for i in ${files_optional} ; do
	file=${CONTROL}/$i
	
	if [ -e ${file} ] ; then
		cp $file /tmp/${pkg}/CONTROL
	fi
done

# build the opk package
owd=`pwd`
cd ..
opkg-build /tmp/${pkg} || exit 1

rm -rf /tmp/${pkg}

cd $owd
if ! ${CONTROL}/rules clean; then
	echo "Clean failed"
	exit 1
fi

# Yep. That's it!
exit 0