1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7oe_soinstall() {
8	# Purpose: Install shared library file and
9	#          create the necessary links
10	# Example: oe_soinstall libfoo.so.1.2.3 ${D}${libdir}
11	libname=`basename $1`
12	case "$libname" in
13	    *.so)
14	        bbfatal "oe_soinstall: Shared library must haved versioned filename (e.g. libfoo.so.1.2.3)"
15	        ;;
16	esac
17	install -m 755 $1 $2/$libname
18	sonamelink=`${READELF} -d $1 |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
19	if [ -z $sonamelink ]; then
20		bbfatal "oe_soinstall: $libname is missing ELF tag 'SONAME'."
21	fi
22	solink=`echo $libname | sed -e 's/\.so\..*/.so/'`
23	ln -sf $libname $2/$sonamelink
24	ln -sf $libname $2/$solink
25}
26
27oe_libinstall() {
28	# Purpose: Install a library, in all its forms
29	# Example
30	#
31	# oe_libinstall libltdl ${STAGING_LIBDIR}/
32	# oe_libinstall -C src/libblah libblah ${D}/${libdir}/
33	dir=""
34	libtool=""
35	silent=""
36	require_static=""
37	require_shared=""
38	while [ "$#" -gt 0 ]; do
39		case "$1" in
40		-C)
41			shift
42			dir="$1"
43			;;
44		-s)
45			silent=1
46			;;
47		-a)
48			require_static=1
49			;;
50		-so)
51			require_shared=1
52			;;
53		-*)
54			bbfatal "oe_libinstall: unknown option: $1"
55			;;
56		*)
57			break;
58			;;
59		esac
60		shift
61	done
62
63	libname="$1"
64	shift
65	destpath="$1"
66	if [ -z "$destpath" ]; then
67		bbfatal "oe_libinstall: no destination path specified"
68	fi
69
70	__runcmd () {
71		if [ -z "$silent" ]; then
72			echo >&2 "oe_libinstall: $*"
73		fi
74		$*
75	}
76
77	if [ -z "$dir" ]; then
78		dir=`pwd`
79	fi
80
81	dotlai=$libname.lai
82
83	# Sanity check that the libname.lai is unique
84	number_of_files=`(cd $dir; find . -name "$dotlai") | wc -l`
85	if [ $number_of_files -gt 1 ]; then
86		bbfatal "oe_libinstall: $dotlai is not unique in $dir"
87	fi
88
89
90	dir=$dir`(cd $dir;find . -name "$dotlai") | sed "s/^\.//;s/\/$dotlai\$//;q"`
91	olddir=`pwd`
92	__runcmd cd $dir
93
94	lafile=$libname.la
95
96	# If such file doesn't exist, try to cut version suffix
97	if [ ! -f "$lafile" ]; then
98		libname1=`echo "$libname" | sed 's/-[0-9.]*$//'`
99		lafile1=$libname.la
100		if [ -f "$lafile1" ]; then
101			libname=$libname1
102			lafile=$lafile1
103		fi
104	fi
105
106	if [ -f "$lafile" ]; then
107		# libtool archive
108		eval `cat $lafile|grep "^library_names="`
109		libtool=1
110	else
111		library_names="$libname.so* $libname.dll.a $libname.*.dylib"
112	fi
113
114	__runcmd install -d $destpath/
115	dota=$libname.a
116	if [ -f "$dota" -o -n "$require_static" ]; then
117		rm -f $destpath/$dota
118		__runcmd install -m 0644 $dota $destpath/
119	fi
120	if [ -f "$dotlai" -a -n "$libtool" ]; then
121		rm -f $destpath/$libname.la
122		__runcmd install -m 0644 $dotlai $destpath/$libname.la
123	fi
124
125	for name in $library_names; do
126		files=`eval echo $name`
127		for f in $files; do
128			if [ ! -e "$f" ]; then
129				if [ -n "$libtool" ]; then
130					bbfatal "oe_libinstall: $dir/$f not found."
131				fi
132			elif [ -L "$f" ]; then
133				__runcmd cp -P "$f" $destpath/
134			elif [ ! -L "$f" ]; then
135				libfile="$f"
136				rm -f $destpath/$libfile
137				__runcmd install -m 0755 $libfile $destpath/
138			fi
139		done
140	done
141
142	if [ -z "$libfile" ]; then
143		if  [ -n "$require_shared" ]; then
144			bbfatal "oe_libinstall: unable to locate shared library"
145		fi
146	elif [ -z "$libtool" ]; then
147		# special case hack for non-libtool .so.#.#.# links
148		baselibfile=`basename "$libfile"`
149		if (echo $baselibfile | grep -qE '^lib.*\.so\.[0-9.]*$'); then
150			sonamelink=`${READELF} -d $libfile |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
151			solink=`echo $baselibfile | sed -e 's/\.so\..*/.so/'`
152			if [ -n "$sonamelink" -a x"$baselibfile" != x"$sonamelink" ]; then
153				__runcmd ln -sf $baselibfile $destpath/$sonamelink
154			fi
155			__runcmd ln -sf $baselibfile $destpath/$solink
156		fi
157	fi
158
159	__runcmd cd "$olddir"
160}
161
162create_cmdline_wrapper () {
163	# Create a wrapper script where commandline options are needed
164	#
165	# These are useful to work around relocation issues, by passing extra options
166	# to a program
167	#
168	# Usage: create_cmdline_wrapper FILENAME <extra-options>
169
170	cmd=$1
171	shift
172
173	echo "Generating wrapper script for $cmd"
174
175	mv $cmd $cmd.real
176	cmdname=`basename $cmd`
177	dirname=`dirname $cmd`
178	cmdoptions=$@
179	if [ "${base_prefix}" != "" ]; then
180		relpath=`python3 -c "import os; print(os.path.relpath('${D}${base_prefix}', '$dirname'))"`
181		cmdoptions=`echo $@ | sed -e "s:${base_prefix}:\\$realdir/$relpath:g"`
182	fi
183	cat <<END >$cmd
184#!/bin/bash
185realpath=\`readlink -fn \$0\`
186realdir=\`dirname \$realpath\`
187exec -a \$realdir/$cmdname \$realdir/$cmdname.real $cmdoptions "\$@"
188END
189	chmod +x $cmd
190}
191
192create_cmdline_shebang_wrapper () {
193	# Create a wrapper script where commandline options are needed
194	#
195	# These are useful to work around shebang relocation issues, where shebangs are too
196	# long or have arguments in them, thus preventing them from using the /usr/bin/env
197	# shebang
198	#
199	# Usage: create_cmdline_wrapper FILENAME <extra-options>
200
201	cmd=$1
202	shift
203
204	echo "Generating wrapper script for $cmd"
205
206	# Strip #! and get remaining interpreter + arg
207	argument="$(sed -ne 's/^#! *//p;q' $cmd)"
208	# strip the shebang from the real script as we do not want it to be usable anyway
209	tail -n +2 $cmd > $cmd.real
210	chown --reference=$cmd $cmd.real
211	chmod --reference=$cmd $cmd.real
212	rm -f $cmd
213	cmdname=$(basename $cmd)
214	dirname=$(dirname $cmd)
215	cmdoptions=$@
216	if [ "${base_prefix}" != "" ]; then
217		relpath=`python3 -c "import os; print(os.path.relpath('${D}${base_prefix}', '$dirname'))"`
218		cmdoptions=`echo $@ | sed -e "s:${base_prefix}:\\$realdir/$relpath:g"`
219	fi
220	cat <<END >$cmd
221#!/usr/bin/env bash
222realpath=\`readlink -fn \$0\`
223realdir=\`dirname \$realpath\`
224exec -a \$realdir/$cmdname $argument \$realdir/$cmdname.real $cmdoptions "\$@"
225END
226	chmod +x $cmd
227}
228
229create_wrapper () {
230	# Create a wrapper script where extra environment variables are needed
231	#
232	# These are useful to work around relocation issues, by setting environment
233	# variables which point to paths in the filesystem.
234	#
235	# Usage: create_wrapper FILENAME [[VAR=VALUE]..]
236
237	cmd=$1
238	shift
239
240	echo "Generating wrapper script for $cmd"
241
242	mv $cmd $cmd.real
243	cmdname=`basename $cmd`
244	dirname=`dirname $cmd`
245	exportstring=$@
246	if [ "${base_prefix}" != "" ]; then
247		relpath=`python3 -c "import os; print(os.path.relpath('${D}${base_prefix}', '$dirname'))"`
248		exportstring=`echo $@ | sed -e "s:${base_prefix}:\\$realdir/$relpath:g"`
249	fi
250	cat <<END >$cmd
251#!/bin/bash
252realpath=\`readlink -fn \$0\`
253realdir=\`dirname \$realpath\`
254export $exportstring
255exec -a "\$0" \$realdir/$cmdname.real "\$@"
256END
257	chmod +x $cmd
258}
259
260# Copy files/directories from $1 to $2 but using hardlinks
261# (preserve symlinks)
262hardlinkdir () {
263	from=$1
264	to=$2
265	(cd $from; find . -print0 | cpio --null -pdlu $to)
266}
267
268
269def check_app_exists(app, d):
270    app = d.expand(app).split()[0].strip()
271    path = d.getVar('PATH')
272    return bool(bb.utils.which(path, app))
273
274def explode_deps(s):
275    return bb.utils.explode_deps(s)
276
277def base_set_filespath(path, d):
278    filespath = []
279    extrapaths = (d.getVar("FILESEXTRAPATHS") or "")
280    # Remove default flag which was used for checking
281    extrapaths = extrapaths.replace("__default:", "")
282    # Don't prepend empty strings to the path list
283    if extrapaths != "":
284        path = extrapaths.split(":") + path
285    # The ":" ensures we have an 'empty' override
286    overrides = (":" + (d.getVar("FILESOVERRIDES") or "")).split(":")
287    overrides.reverse()
288    for o in overrides:
289        for p in path:
290            if p != "":
291                filespath.append(os.path.join(p, o))
292    return ":".join(filespath)
293
294def extend_variants(d, var, extend, delim=':'):
295    """Return a string of all bb class extend variants for the given extend"""
296    variants = []
297    whole = d.getVar(var) or ""
298    for ext in whole.split():
299        eext = ext.split(delim)
300        if len(eext) > 1 and eext[0] == extend:
301            variants.append(eext[1])
302    return " ".join(variants)
303
304def multilib_pkg_extend(d, pkg):
305    variants = (d.getVar("MULTILIB_VARIANTS") or "").split()
306    if not variants:
307        return pkg
308    pkgs = pkg
309    for v in variants:
310        pkgs = pkgs + " " + v + "-" + pkg
311    return pkgs
312
313def get_multilib_datastore(variant, d):
314    return oe.utils.get_multilib_datastore(variant, d)
315
316def all_multilib_tune_values(d, var, unique = True, need_split = True, delim = ' '):
317    """Return a string of all ${var} in all multilib tune configuration"""
318    values = []
319    variants = (d.getVar("MULTILIB_VARIANTS") or "").split() + ['']
320    for item in variants:
321        localdata = get_multilib_datastore(item, d)
322        # We need WORKDIR to be consistent with the original datastore
323        localdata.setVar("WORKDIR", d.getVar("WORKDIR"))
324        value = localdata.getVar(var) or ""
325        if value != "":
326            if need_split:
327                for item in value.split(delim):
328                    values.append(item)
329            else:
330                values.append(value)
331    if unique:
332        #we do this to keep order as much as possible
333        ret = []
334        for value in values:
335            if not value in ret:
336                ret.append(value)
337    else:
338        ret = values
339    return " ".join(ret)
340
341def all_multilib_tune_list(vars, d):
342    """
343    Return a list of ${VAR} for each variable VAR in vars from each
344    multilib tune configuration.
345    Is safe to be called from a multilib recipe/context as it can
346    figure out the original tune and remove the multilib overrides.
347    """
348    values = {}
349    for v in vars:
350        values[v] = []
351    values['ml'] = ['']
352
353    variants = (d.getVar("MULTILIB_VARIANTS") or "").split() + ['']
354    for item in variants:
355        localdata = get_multilib_datastore(item, d)
356        values[v].append(localdata.getVar(v))
357        values['ml'].append(item)
358    return values
359all_multilib_tune_list[vardepsexclude] = "OVERRIDES"
360
361# If the user hasn't set up their name/email, set some defaults
362check_git_config() {
363	if ! git config user.email > /dev/null ; then
364		git config --local user.email "${PATCH_GIT_USER_EMAIL}"
365	fi
366	if ! git config user.name > /dev/null ; then
367		git config --local user.name "${PATCH_GIT_USER_NAME}"
368	fi
369}
370