summaryrefslogtreecommitdiffstats
path: root/meta/classes-global
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes-global')
-rw-r--r--meta/classes-global/base.bbclass40
-rw-r--r--meta/classes-global/insane.bbclass54
-rw-r--r--meta/classes-global/package_rpm.bbclass39
-rw-r--r--meta/classes-global/sanity.bbclass5
-rw-r--r--meta/classes-global/sstate.bbclass56
-rw-r--r--meta/classes-global/utils.bbclass4
6 files changed, 97 insertions, 101 deletions
diff --git a/meta/classes-global/base.bbclass b/meta/classes-global/base.bbclass
index 0999b42daa..b6940bbb6f 100644
--- a/meta/classes-global/base.bbclass
+++ b/meta/classes-global/base.bbclass
@@ -153,20 +153,38 @@ python base_do_fetch() {
}
addtask unpack after do_fetch
-do_unpack[dirs] = "${WORKDIR}"
-
-do_unpack[cleandirs] = "${@d.getVar('S') if os.path.normpath(d.getVar('S')) != os.path.normpath(d.getVar('WORKDIR')) else os.path.join('${S}', 'patches')}"
+do_unpack[cleandirs] = "${UNPACKDIR}"
python base_do_unpack() {
+ import shutil
+
+ sourcedir = d.getVar('S')
+ # Intentionally keep SOURCE_BASEDIR internal to the task just for SDE
+ d.setVar("SOURCE_BASEDIR", sourcedir)
+
src_uri = (d.getVar('SRC_URI') or "").split()
if not src_uri:
return
+ basedir = None
+ unpackdir = d.getVar('UNPACKDIR')
+ workdir = d.getVar('WORKDIR')
+ if sourcedir.startswith(workdir) and not sourcedir.startswith(unpackdir):
+ basedir = sourcedir.replace(workdir, '').strip("/").split('/')[0]
+ if basedir:
+ bb.utils.remove(workdir + '/' + basedir, True)
+ d.setVar("SOURCE_BASEDIR", workdir + '/' + basedir)
+
try:
fetcher = bb.fetch2.Fetch(src_uri, d)
- fetcher.unpack(d.getVar('WORKDIR'))
+ fetcher.unpack(d.getVar('UNPACKDIR'))
except bb.fetch2.BBFetchException as e:
bb.fatal("Bitbake Fetcher Error: " + repr(e))
+
+ if basedir and os.path.exists(unpackdir + '/' + basedir):
+ # Compatibility magic to ensure ${WORKDIR}/git and ${WORKDIR}/${BP}
+ # as often used in S work as expected.
+ shutil.move(unpackdir + '/' + basedir, workdir + '/' + basedir)
}
SSTATETASKS += "do_deploy_source_date_epoch"
@@ -199,8 +217,8 @@ addtask do_deploy_source_date_epoch_setscene
addtask do_deploy_source_date_epoch before do_configure after do_patch
python create_source_date_epoch_stamp() {
- # Version: 1
- source_date_epoch = oe.reproducible.get_source_date_epoch(d, d.getVar('S'))
+ # Version: 2
+ source_date_epoch = oe.reproducible.get_source_date_epoch(d, d.getVar('SOURCE_BASEDIR') or d.getVar('S'))
oe.reproducible.epochfile_write(source_date_epoch, d.getVar('SDE_FILE'), d)
}
do_unpack[postfuncs] += "create_source_date_epoch_stamp"
@@ -410,16 +428,6 @@ python () {
oe.utils.features_backfill("DISTRO_FEATURES", d)
oe.utils.features_backfill("MACHINE_FEATURES", d)
- if d.getVar("S")[-1] == '/':
- bb.warn("Recipe %s sets S variable with trailing slash '%s', remove it" % (d.getVar("PN"), d.getVar("S")))
- if d.getVar("B")[-1] == '/':
- bb.warn("Recipe %s sets B variable with trailing slash '%s', remove it" % (d.getVar("PN"), d.getVar("B")))
-
- if os.path.normpath(d.getVar("WORKDIR")) != os.path.normpath(d.getVar("S")):
- d.appendVar("PSEUDO_IGNORE_PATHS", ",${S}")
- if os.path.normpath(d.getVar("WORKDIR")) != os.path.normpath(d.getVar("B")):
- d.appendVar("PSEUDO_IGNORE_PATHS", ",${B}")
-
# To add a recipe to the skip list , set:
# SKIP_RECIPE[pn] = "message"
pn = d.getVar('PN')
diff --git a/meta/classes-global/insane.bbclass b/meta/classes-global/insane.bbclass
index e963001d09..345196eeb3 100644
--- a/meta/classes-global/insane.bbclass
+++ b/meta/classes-global/insane.bbclass
@@ -58,7 +58,7 @@ enabled tests are listed here, the do_package_qa task will run under fakeroot."
ALL_QA = "${WARN_QA} ${ERROR_QA}"
-UNKNOWN_CONFIGURE_OPT_IGNORE ?= "--enable-nls --disable-nls --disable-silent-rules --disable-dependency-tracking --with-libtool-sysroot --disable-static"
+UNKNOWN_CONFIGURE_OPT_IGNORE ?= "--enable-nls --disable-nls --disable-silent-rules --disable-dependency-tracking --disable-static"
# This is a list of directories that are expected to be empty.
QA_EMPTY_DIRS ?= " \
@@ -298,7 +298,7 @@ def package_qa_check_libdir(d):
try:
elf.open()
messages.append("%s: found library in wrong location: %s" % (package, rel_path))
- except (oe.qa.NotELFFileError):
+ except (oe.qa.NotELFFileError, FileNotFoundError):
pass
if exec_re.match(rel_path):
if libdir not in rel_path and libexecdir not in rel_path:
@@ -307,7 +307,7 @@ def package_qa_check_libdir(d):
try:
elf.open()
messages.append("%s: found library in wrong location: %s" % (package, rel_path))
- except (oe.qa.NotELFFileError):
+ except (oe.qa.NotELFFileError, FileNotFoundError):
pass
if messages:
@@ -334,21 +334,16 @@ def package_qa_check_arch(path,name,d, elf, messages):
if not elf:
return
- target_os = d.getVar('HOST_OS')
- target_arch = d.getVar('HOST_ARCH')
+ host_os = d.getVar('HOST_OS')
+ host_arch = d.getVar('HOST_ARCH')
provides = d.getVar('PROVIDES')
bpn = d.getVar('BPN')
- if target_arch == "allarch":
+ if host_arch == "allarch":
pn = d.getVar('PN')
oe.qa.add_message(messages, "arch", pn + ": Recipe inherits the allarch class, but has packaged architecture-specific binaries")
return
- # FIXME: Cross package confuse this check, so just skip them
- for s in ['cross', 'nativesdk', 'cross-canadian']:
- if bb.data.inherits_class(s, d):
- return
-
# avoid following links to /usr/bin (e.g. on udev builds)
# we will check the files pointed to anyway...
if os.path.islink(path):
@@ -356,12 +351,12 @@ def package_qa_check_arch(path,name,d, elf, messages):
#if this will throw an exception, then fix the dict above
(machine, osabi, abiversion, littleendian, bits) \
- = oe.elf.machine_dict(d)[target_os][target_arch]
+ = oe.elf.machine_dict(d)[host_os][host_arch]
# Check the architecture and endiannes of the binary
is_32 = (("virtual/kernel" in provides) or bb.data.inherits_class("module", d)) and \
- (target_os == "linux-gnux32" or target_os == "linux-muslx32" or \
- target_os == "linux-gnu_ilp32" or re.match(r'mips64.*32', d.getVar('DEFAULTTUNE')))
+ (host_os == "linux-gnux32" or host_os == "linux-muslx32" or \
+ host_os == "linux-gnu_ilp32" or re.match(r'mips64.*32', d.getVar('DEFAULTTUNE')))
is_bpf = (oe.qa.elf_machine_to_string(elf.machine()) == "BPF")
if not ((machine == elf.machine()) or is_32 or is_bpf):
oe.qa.add_message(messages, "arch", "Architecture did not match (%s, expected %s) in %s" % \
@@ -464,8 +459,8 @@ def package_qa_check_buildpaths(path, name, d, elf, messages):
with open(path, 'rb') as f:
file_content = f.read()
if tmpdir in file_content:
- trimmed = path.replace(os.path.join (d.getVar("PKGDEST"), name), "")
- oe.qa.add_message(messages, "buildpaths", "File %s in package %s contains reference to TMPDIR" % (trimmed, name))
+ path = package_qa_clean_path(path, d, name)
+ oe.qa.add_message(messages, "buildpaths", "File %s in package %s contains reference to TMPDIR" % (path, name))
QAPATHTEST[xorg-driver-abi] = "package_qa_check_xorg_driver_abi"
@@ -494,7 +489,7 @@ def package_qa_check_infodir(path, name, d, elf, messages):
infodir = d.expand("${infodir}/dir")
if infodir in path:
- oe.qa.add_message(messages, "infodir", "The /usr/share/info/dir file is not meant to be shipped in a particular package.")
+ oe.qa.add_message(messages, "infodir", "The %s file is not meant to be shipped in a particular package." % infodir)
QAPATHTEST[symlink-to-sysroot] = "package_qa_check_symlink_to_sysroot"
def package_qa_check_symlink_to_sysroot(path, name, d, elf, messages):
@@ -506,8 +501,8 @@ def package_qa_check_symlink_to_sysroot(path, name, d, elf, messages):
if os.path.isabs(target):
tmpdir = d.getVar('TMPDIR')
if target.startswith(tmpdir):
- trimmed = path.replace(os.path.join (d.getVar("PKGDEST"), name), "")
- oe.qa.add_message(messages, "symlink-to-sysroot", "Symlink %s in %s points to TMPDIR" % (trimmed, name))
+ path = package_qa_clean_path(path, d, name)
+ oe.qa.add_message(messages, "symlink-to-sysroot", "Symlink %s in %s points to TMPDIR" % (path, name))
QAPATHTEST[32bit-time] = "check_32bit_symbols"
def check_32bit_symbols(path, packagename, d, elf, messages):
@@ -840,10 +835,6 @@ def prepopulate_objdump_p(elf, d):
# Walk over all files in a directory and call func
def package_qa_walk(warnfuncs, errorfuncs, package, d):
- #if this will throw an exception, then fix the dict above
- target_os = d.getVar('HOST_OS')
- target_arch = d.getVar('HOST_ARCH')
-
warnings = {}
errors = {}
elves = {}
@@ -1399,7 +1390,7 @@ python do_qa_patch() {
oe.qa.handle_error("unimplemented-ptest", "%s: autotools-based tests detected" % d.getVar('PN'), d)
# Last resort, detect a test directory in sources
- elif any(filename.lower() in ["test", "tests"] for filename in os.listdir(srcdir)):
+ elif os.path.exists(srcdir) and any(filename.lower() in ["test", "tests"] for filename in os.listdir(srcdir)):
oe.qa.handle_error("unimplemented-ptest", "%s: test subdirectory detected" % d.getVar('PN'), d)
oe.qa.exit_if_errors(d)
@@ -1602,6 +1593,21 @@ python () {
if prog.search(pn):
oe.qa.handle_error("uppercase-pn", 'PN: %s is upper case, this can result in unexpected behavior.' % pn, d)
+ sourcedir = d.getVar("S")
+ builddir = d.getVar("B")
+ workdir = d.getVar("WORKDIR")
+ unpackdir = d.getVar("UNPACKDIR")
+ if sourcedir == workdir:
+ bb.fatal("Using S = ${WORKDIR} is no longer supported")
+ if builddir == workdir:
+ bb.fatal("Using B = ${WORKDIR} is no longer supported")
+ if unpackdir == workdir:
+ bb.fatal("Using UNPACKDIR = ${WORKDIR} is not supported")
+ if sourcedir[-1] == '/':
+ bb.warn("Recipe %s sets S variable with trailing slash '%s', remove it" % (d.getVar("PN"), d.getVar("S")))
+ if builddir[-1] == '/':
+ bb.warn("Recipe %s sets B variable with trailing slash '%s', remove it" % (d.getVar("PN"), d.getVar("B")))
+
# Some people mistakenly use DEPENDS:${PN} instead of DEPENDS and wonder
# why it doesn't work.
if (d.getVar(d.expand('DEPENDS:${PN}'))):
diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/package_rpm.bbclass
index 2e3e4e8c79..474d2491eb 100644
--- a/meta/classes-global/package_rpm.bbclass
+++ b/meta/classes-global/package_rpm.bbclass
@@ -38,6 +38,7 @@ def filter_nativesdk_deps(srcname, var):
# Construct per file dependencies file
def write_rpm_perfiledata(srcname, d):
+ import oe.package
workdir = d.getVar('WORKDIR')
packages = d.getVar('PACKAGES')
pkgd = d.getVar('PKGD')
@@ -53,12 +54,7 @@ def write_rpm_perfiledata(srcname, d):
key = "FILE" + varname + ":" + dfile + ":" + pkg
deps = filter_nativesdk_deps(srcname, d.getVar(key) or "")
depends_dict = bb.utils.explode_dep_versions(deps)
- file = dfile.replace("@underscore@", "_")
- file = file.replace("@closebrace@", "]")
- file = file.replace("@openbrace@", "[")
- file = file.replace("@tab@", "\t")
- file = file.replace("@space@", " ")
- file = file.replace("@at@", "@")
+ file = oe.package.file_reverse_translate(dfile)
outfile.write('"' + pkgd + file + '" : "')
for dep in depends_dict:
ver = depends_dict[dep]
@@ -191,7 +187,7 @@ python write_specfile () {
if not len(depends_dict[dep]):
array.append("%s: %s" % (tag, dep))
- def walk_files(walkpath, target, conffiles, dirfiles):
+ def walk_files(walkpath, target, conffiles):
# We can race against the ipk/deb backends which create CONTROL or DEBIAN directories
# when packaging. We just ignore these files which are created in
# packages-split/ and not package/
@@ -233,22 +229,12 @@ python write_specfile () {
return False
dirs[:] = [dir for dir in dirs if not move_to_files(dir)]
- # Directory handling can happen in two ways, either DIRFILES is not set at all
- # in which case we fall back to the older behaviour of packages owning all their
- # directories
- if dirfiles is None:
- for dir in dirs:
- if dir == "CONTROL" or dir == "DEBIAN":
- continue
- p = path + '/' + dir
- # All packages own the directories their files are in...
- target.append(get_attr(dir) + '%dir "' + escape_chars(p) + '"')
- elif path:
- # packages own only empty directories or explict directory.
- # This will prevent the overlapping of security permission.
- attr = get_attr(path)
- if (not files and not dirs) or path in dirfiles:
- target.append(attr + '%dir "' + escape_chars(path) + '"')
+ for dir in dirs:
+ if dir == "CONTROL" or dir == "DEBIAN":
+ continue
+ p = path + '/' + dir
+ # All packages own the directories their files are in...
+ target.append(get_attr(dir) + '%dir "' + escape_chars(p) + '"')
for file in files:
if file == "CONTROL" or file == "DEBIAN":
@@ -363,9 +349,6 @@ python write_specfile () {
localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + pkg)
conffiles = oe.package.get_conffiles(pkg, d)
- dirfiles = localdata.getVar('DIRFILES')
- if dirfiles is not None:
- dirfiles = dirfiles.split()
splitname = pkgname
@@ -430,7 +413,7 @@ python write_specfile () {
srcrpostrm = splitrpostrm
file_list = []
- walk_files(root, file_list, conffiles, dirfiles)
+ walk_files(root, file_list, conffiles)
if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
bb.note("Not creating empty RPM package for %s" % splitname)
else:
@@ -522,7 +505,7 @@ python write_specfile () {
# Now process files
file_list = []
- walk_files(root, file_list, conffiles, dirfiles)
+ walk_files(root, file_list, conffiles)
if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
bb.note("Not creating empty RPM package for %s" % splitname)
else:
diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
index bbbc41ddae..1d242f0f0a 100644
--- a/meta/classes-global/sanity.bbclass
+++ b/meta/classes-global/sanity.bbclass
@@ -40,7 +40,7 @@ BBLAYERS_CONF_UPDATE_FUNCS += " \
conf/site.conf:SCONF_VERSION:SITE_CONF_VERSION:oecore_update_siteconf \
"
-SANITY_DIFF_TOOL ?= "meld"
+SANITY_DIFF_TOOL ?= "diff -u"
SANITY_LOCALCONF_SAMPLE ?= "${COREBASE}/meta*/conf/templates/default/local.conf.sample"
python oecore_update_localconf() {
@@ -495,12 +495,15 @@ def check_gcc_version(sanity_data):
# Tar version 1.24 and onwards handle overwriting symlinks correctly
# but earlier versions do not; this needs to work properly for sstate
# Version 1.28 is needed so opkg-build works correctly when reproducible builds are enabled
+# Gtar is assumed at to be used as tar in poky
def check_tar_version(sanity_data):
import subprocess
try:
result = subprocess.check_output(["tar", "--version"], stderr=subprocess.STDOUT).decode('utf-8')
except subprocess.CalledProcessError as e:
return "Unable to execute tar --version, exit code %d\n%s\n" % (e.returncode, e.output)
+ if not "GNU" in result:
+ return "Your version of tar is not gtar. Please install gtar (you could use the project's buildtools-tarball from our last release or use scripts/install-buildtools).\n"
version = result.split()[3]
if bb.utils.vercmp_string_op(version, "1.28", "<"):
return "Your version of tar is older than 1.28 and does not have the support needed to enable reproducible builds. Please install a newer version of tar (you could use the project's buildtools-tarball from our last release or use scripts/install-buildtools).\n"
diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
index 96655ff24f..beb22f424e 100644
--- a/meta/classes-global/sstate.bbclass
+++ b/meta/classes-global/sstate.bbclass
@@ -4,7 +4,7 @@
# SPDX-License-Identifier: MIT
#
-SSTATE_VERSION = "11"
+SSTATE_VERSION = "12"
SSTATE_ZSTD_CLEVEL ??= "8"
@@ -189,7 +189,6 @@ def sstate_state_fromvars(d, task = None):
plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
- interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
if not task or len(inputs) != len(outputs):
bb.fatal("sstate variables not setup correctly?!")
@@ -205,7 +204,6 @@ def sstate_state_fromvars(d, task = None):
ss['lockfiles'] = lockfiles
ss['lockfiles-shared'] = lockfilesshared
ss['plaindirs'] = plaindirs
- ss['interceptfuncs'] = interceptfuncs
ss['fixmedir'] = fixmedir
return ss
@@ -225,12 +223,23 @@ def sstate_install(ss, d):
import oe.sstatesig
import subprocess
+ def prepdir(dir):
+ # remove dir if it exists, ensure any parent directories do exist
+ if os.path.exists(dir):
+ oe.path.remove(dir)
+ bb.utils.mkdirhier(dir)
+ oe.path.remove(dir)
+
+ sstateinst = d.getVar("SSTATE_INSTDIR")
+
+ for state in ss['dirs']:
+ prepdir(state[1])
+ bb.utils.rename(sstateinst + state[0], state[1])
+
sharedfiles = []
shareddirs = []
bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
- sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
-
manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
if os.access(manifest, os.R_OK):
@@ -329,6 +338,17 @@ def sstate_install(ss, d):
if os.path.exists(state[1]):
oe.path.copyhardlinktree(state[1], state[2])
+ for plain in ss['plaindirs']:
+ workdir = d.getVar('WORKDIR')
+ sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
+ src = sstateinst + "/" + plain.replace(workdir, '')
+ if sharedworkdir in plain:
+ src = sstateinst + "/" + plain.replace(sharedworkdir, '')
+ dest = plain
+ bb.utils.mkdirhier(src)
+ prepdir(dest)
+ bb.utils.rename(src, dest)
+
for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
# All hooks should run in the SSTATE_INSTDIR
bb.build.exec_func(postinst, d, (sstateinst,))
@@ -393,29 +413,8 @@ def sstate_installpkgdir(ss, d):
# All hooks should run in the SSTATE_INSTDIR
bb.build.exec_func(f, d, (sstateinst,))
- def prepdir(dir):
- # remove dir if it exists, ensure any parent directories do exist
- if os.path.exists(dir):
- oe.path.remove(dir)
- bb.utils.mkdirhier(dir)
- oe.path.remove(dir)
-
- for state in ss['dirs']:
- prepdir(state[1])
- bb.utils.rename(sstateinst + state[0], state[1])
sstate_install(ss, d)
- for plain in ss['plaindirs']:
- workdir = d.getVar('WORKDIR')
- sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
- src = sstateinst + "/" + plain.replace(workdir, '')
- if sharedworkdir in plain:
- src = sstateinst + "/" + plain.replace(sharedworkdir, '')
- dest = plain
- bb.utils.mkdirhier(src)
- prepdir(dest)
- bb.utils.rename(src, dest)
-
return True
python sstate_hardcode_path_unpack () {
@@ -790,9 +789,6 @@ sstate_task_prefunc[dirs] = "${WORKDIR}"
python sstate_task_postfunc () {
shared_state = sstate_state_fromvars(d)
- for intercept in shared_state['interceptfuncs']:
- bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
-
omask = os.umask(0o002)
if omask != 0o002:
bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
@@ -1115,7 +1111,7 @@ def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True,
bb.parse.siggen.checkhashes(sq_data, missed, found, d)
return found
-setscene_depvalid[vardepsexclude] = "SSTATE_EXCLUDEDEPS_SYSROOT"
+setscene_depvalid[vardepsexclude] = "SSTATE_EXCLUDEDEPS_SYSROOT _SSTATE_EXCLUDEDEPS_SYSROOT"
BB_SETSCENE_DEPVALID = "setscene_depvalid"
diff --git a/meta/classes-global/utils.bbclass b/meta/classes-global/utils.bbclass
index 8d797ff126..957389928f 100644
--- a/meta/classes-global/utils.bbclass
+++ b/meta/classes-global/utils.bbclass
@@ -15,7 +15,7 @@ oe_soinstall() {
;;
esac
install -m 755 $1 $2/$libname
- sonamelink=`${HOST_PREFIX}readelf -d $1 |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
+ sonamelink=`${READELF} -d $1 |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
if [ -z $sonamelink ]; then
bbfatal "oe_soinstall: $libname is missing ELF tag 'SONAME'."
fi
@@ -147,7 +147,7 @@ oe_libinstall() {
# special case hack for non-libtool .so.#.#.# links
baselibfile=`basename "$libfile"`
if (echo $baselibfile | grep -qE '^lib.*\.so\.[0-9.]*$'); then
- sonamelink=`${HOST_PREFIX}readelf -d $libfile |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
+ sonamelink=`${READELF} -d $libfile |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
solink=`echo $baselibfile | sed -e 's/\.so\..*/.so/'`
if [ -n "$sonamelink" -a x"$baselibfile" != x"$sonamelink" ]; then
__runcmd ln -sf $baselibfile $destpath/$sonamelink