diff options
Diffstat (limited to 'classes/base.bbclass')
| -rw-r--r-- | classes/base.bbclass | 957 |
1 files changed, 766 insertions, 191 deletions
diff --git a/classes/base.bbclass b/classes/base.bbclass index 249a25a218..e6cfeccc46 100644 --- a/classes/base.bbclass +++ b/classes/base.bbclass @@ -1,23 +1,190 @@ -BB_DEFAULT_TASK = "build" +BB_DEFAULT_TASK ?= "build" + +# like os.path.join but doesn't treat absolute RHS specially +def base_path_join(a, *p): + path = a + for b in p: + if path == '' or path.endswith('/'): + path += b + else: + path += '/' + b + return path + +def base_path_relative(src, dest): + """ Return a relative path from src to dest. + + >>> base_path_relative("/usr/bin", "/tmp/foo/bar") + ../../tmp/foo/bar + + >>> base_path_relative("/usr/bin", "/usr/lib") + ../lib + + >>> base_path_relative("/tmp", "/tmp/foo/bar") + foo/bar + """ + from os.path import sep, pardir, normpath, commonprefix + + destlist = normpath(dest).split(sep) + srclist = normpath(src).split(sep) + + # Find common section of the path + common = commonprefix([destlist, srclist]) + commonlen = len(common) + + # Climb back to the point where they differentiate + relpath = [ pardir ] * (len(srclist) - commonlen) + if commonlen < len(destlist): + # Add remaining portion + relpath += destlist[commonlen:] + + return sep.join(relpath) + +def base_path_out(path, d): + """ Prepare a path for display to the user. """ + rel = base_path_relative(d.getVar("TOPDIR", 1), path) + if len(rel) > len(path): + return path + else: + return rel + +# for MD5/SHA handling +def base_chk_load_parser(config_paths): + import ConfigParser + parser = ConfigParser.ConfigParser() + if len(parser.read(config_paths)) < 1: + raise ValueError("no ini files could be found") + + return parser + +def base_chk_file_vars(parser, localpath, params, data): + try: + name = params["name"] + except KeyError: + return False + flagName = "%s.md5sum" % name + want_md5sum = bb.data.getVarFlag("SRC_URI", flagName, data) + flagName = "%s.sha256sum" % name + want_sha256sum = bb.data.getVarFlag("SRC_URI", flagName, data) + + if (want_sha256sum == None and want_md5sum == None): + # no checksums to check, nothing to do + return False + + if not os.path.exists(localpath): + localpath = base_path_out(localpath, data) + bb.note("The localpath does not exist '%s'" % localpath) + raise Exception("The path does not exist '%s'" % localpath) + + if want_md5sum: + try: + md5pipe = os.popen('PATH=%s md5sum %s' % (bb.data.getVar('PATH', data, True), localpath)) + md5data = (md5pipe.readline().split() or [ "" ])[0] + md5pipe.close() + except OSError, e: + raise Exception("Executing md5sum failed") + if want_md5sum != md5data: + bb.note("The MD5Sums did not match. Wanted: '%s' and Got: '%s'" % (want_md5sum, md5data)) + raise Exception("MD5 Sums do not match. Wanted: '%s' Got: '%s'" % (want_md5sum, md5data)) + + if want_sha256sum: + try: + shapipe = os.popen('PATH=%s oe_sha256sum %s' % (bb.data.getVar('PATH', data, True), localpath)) + sha256data = (shapipe.readline().split() or [ "" ])[0] + shapipe.close() + except OSError, e: + raise Exception("Executing shasum failed") + if want_sha256sum != sha256data: + bb.note("The SHA256Sums did not match. Wanted: '%s' and Got: '%s'" % (want_sha256sum, sha256data)) + raise Exception("SHA256 Sums do not match. Wanted: '%s' Got: '%s'" % (want_sha256sum, sha256data)) + + return True + + +def base_chk_file(parser, pn, pv, src_uri, localpath, data): + no_checksum = False + # Try PN-PV-SRC_URI first and then try PN-SRC_URI + # we rely on the get method to create errors + pn_pv_src = "%s-%s-%s" % (pn,pv,src_uri) + pn_src = "%s-%s" % (pn,src_uri) + if parser.has_section(pn_pv_src): + md5 = parser.get(pn_pv_src, "md5") + sha256 = parser.get(pn_pv_src, "sha256") + elif parser.has_section(pn_src): + md5 = parser.get(pn_src, "md5") + sha256 = parser.get(pn_src, "sha256") + elif parser.has_section(src_uri): + md5 = parser.get(src_uri, "md5") + sha256 = parser.get(src_uri, "sha256") + else: + no_checksum = True + + # md5 and sha256 should be valid now + if not os.path.exists(localpath): + localpath = base_path_out(localpath, data) + bb.note("The localpath does not exist '%s'" % localpath) + raise Exception("The path does not exist '%s'" % localpath) + + + # call md5(sum) and shasum + try: + md5pipe = os.popen('PATH=%s md5sum %s' % (bb.data.getVar('PATH', data, True), localpath)) + md5data = (md5pipe.readline().split() or [ "" ])[0] + md5pipe.close() + except OSError: + raise Exception("Executing md5sum failed") + + try: + shapipe = os.popen('PATH=%s oe_sha256sum %s' % (bb.data.getVar('PATH', data, True), localpath)) + shadata = (shapipe.readline().split() or [ "" ])[0] + shapipe.close() + except OSError: + raise Exception("Executing shasum failed") + + if no_checksum == True: # we do not have conf/checksums.ini entry + try: + file = open("%s/checksums.ini" % bb.data.getVar("TMPDIR", data, 1), "a") + except: + return False + + if not file: + raise Exception("Creating checksums.ini failed") + + file.write("[%s]\nmd5=%s\nsha256=%s\n\n" % (src_uri, md5data, shadata)) + file.close() + if not bb.data.getVar("OE_STRICT_CHECKSUMS",data, True): + bb.note("This package has no entry in checksums.ini, please add one") + bb.note("\n[%s]\nmd5=%s\nsha256=%s" % (src_uri, md5data, shadata)) + return True + else: + bb.note("Missing checksum") + return False + + if not md5 == md5data: + bb.note("The MD5Sums did not match. Wanted: '%s' and Got: '%s'" % (md5,md5data)) + raise Exception("MD5 Sums do not match. Wanted: '%s' Got: '%s'" % (md5, md5data)) + + if not sha256 == shadata: + bb.note("The SHA256 Sums do not match. Wanted: '%s' Got: '%s'" % (sha256,shadata)) + raise Exception("SHA256 Sums do not match. Wanted: '%s' Got: '%s'" % (sha256, shadata)) + + return True + def base_dep_prepend(d): - import bb; # # Ideally this will check a flag so we will operate properly in # the case where host == build == target, for now we don't work in # that case though. # - deps = "" + deps = "shasum-native coreutils-native" + if bb.data.getVar('PN', d, True) == "shasum-native" or bb.data.getVar('PN', d, True) == "stagemanager-native": + deps = "" + if bb.data.getVar('PN', d, True) == "coreutils-native": + deps = "shasum-native" # INHIBIT_DEFAULT_DEPS doesn't apply to the patch command. Whether or not # we need that built is the responsibility of the patch function / class, not # the application. - patchdeps = bb.data.getVar("PATCHTOOL", d, 1) - if patchdeps: - patchdeps = "%s-native" % patchdeps - if not patchdeps in bb.data.getVar("PROVIDES", d, 1): - deps = patchdeps - if not bb.data.getVar('INHIBIT_DEFAULT_DEPS', d): if (bb.data.getVar('HOST_SYS', d, 1) != bb.data.getVar('BUILD_SYS', d, 1)): @@ -25,7 +192,6 @@ def base_dep_prepend(d): return deps def base_read_file(filename): - import bb try: f = file( filename, "r" ) except IOError, reason: @@ -34,41 +200,70 @@ def base_read_file(filename): return f.read().strip() return None +def base_ifelse(condition, iftrue = True, iffalse = False): + if condition: + return iftrue + else: + return iffalse + def base_conditional(variable, checkvalue, truevalue, falsevalue, d): - import bb if bb.data.getVar(variable,d,1) == checkvalue: return truevalue else: return falsevalue -def base_contains(variable, checkvalue, truevalue, falsevalue, d): - import bb - if bb.data.getVar(variable,d,1).find(checkvalue) != -1: - return truevalue - else: - return falsevalue +def base_less_or_equal(variable, checkvalue, truevalue, falsevalue, d): + if float(bb.data.getVar(variable,d,1)) <= float(checkvalue): + return truevalue + else: + return falsevalue + +def base_version_less_or_equal(variable, checkvalue, truevalue, falsevalue, d): + result = bb.vercmp(bb.data.getVar(variable,d,True), checkvalue) + if result <= 0: + return truevalue + else: + return falsevalue + +def base_contains(variable, checkvalues, truevalue, falsevalue, d): + matches = 0 + if type(checkvalues).__name__ == "str": + checkvalues = [checkvalues] + for value in checkvalues: + if bb.data.getVar(variable,d,1).find(value) != -1: + matches = matches + 1 + if matches == len(checkvalues): + return truevalue + return falsevalue def base_both_contain(variable1, variable2, checkvalue, d): - import bb if bb.data.getVar(variable1,d,1).find(checkvalue) != -1 and bb.data.getVar(variable2,d,1).find(checkvalue) != -1: return checkvalue else: return "" DEPENDS_prepend="${@base_dep_prepend(d)} " +DEPENDS_virtclass-native_prepend="${@base_dep_prepend(d)} " +DEPENDS_virtclass-nativesdk_prepend="${@base_dep_prepend(d)} " + +def base_prune_suffix(var, suffixes, d): + # See if var ends with any of the suffixes listed and + # remove it if found + for suffix in suffixes: + if var.endswith(suffix): + return var.replace(suffix, "") + return var def base_set_filespath(path, d): - import os, bb + bb.note("base_set_filespath usage is deprecated, %s should be fixed" % d.getVar("P", 1)) filespath = [] + # The ":" ensures we have an 'empty' override + overrides = (bb.data.getVar("OVERRIDES", d, 1) or "") + ":" for p in path: - overrides = bb.data.getVar("OVERRIDES", d, 1) or "" - overrides = overrides + ":" for o in overrides.split(":"): filespath.append(os.path.join(p, o)) return ":".join(filespath) -FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", "${FILE_DIRNAME}/${P}", "${FILE_DIRNAME}/${PN}", "${FILE_DIRNAME}/files", "${FILE_DIRNAME}" ], d)}" - def oe_filter(f, str, d): from re import match return " ".join(filter(lambda x: match(f, x, 0), str.split())) @@ -187,7 +382,16 @@ oe_libinstall() { if [ -z "$dir" ]; then dir=`pwd` fi + dotlai=$libname.lai + + # Sanity check that the libname.lai is unique + number_of_files=`(cd $dir; find . -name "$dotlai") | wc -l` + if [ $number_of_files -gt 1 ]; then + oefatal "oe_libinstall: $dotlai is not unique in $dir" + fi + + dir=$dir`(cd $dir;find . -name "$dotlai") | sed "s/^\.//;s/\/$dotlai\$//;q"` olddir=`pwd` __runcmd cd $dir @@ -196,8 +400,12 @@ oe_libinstall() { # If such file doesn't exist, try to cut version suffix if [ ! -f "$lafile" ]; then - libname=`echo "$libname" | sed 's/-[0-9.]*$//'` - lafile=$libname.la + libname1=`echo "$libname" | sed 's/-[0-9.]*$//'` + lafile1=$libname.la + if [ -f "$lafile1" ]; then + libname=$libname1 + lafile=$lafile1 + fi fi if [ -f "$lafile" ]; then @@ -219,7 +427,10 @@ oe_libinstall() { # stop libtool using the final directory name for libraries # in staging: __runcmd rm -f $destpath/$libname.la - __runcmd sed -e 's/^installed=yes$/installed=no/' -e '/^dependency_libs=/s,${WORKDIR}[[:alnum:]/\._+-]*/\([[:alnum:]\._+-]*\),${STAGING_LIBDIR}/\1,g' $dotlai >$destpath/$libname.la + __runcmd sed -e 's/^installed=yes$/installed=no/' \ + -e '/^dependency_libs=/s,${WORKDIR}[[:alnum:]/\._+-]*/\([[:alnum:]\._+-]*\),${STAGING_LIBDIR}/\1,g' \ + -e "/^dependency_libs=/s,\([[:space:]']\)${libdir},\1${STAGING_LIBDIR},g" \ + $dotlai >$destpath/$libname.la else __runcmd install -m 0644 $dotlai $destpath/$libname.la fi @@ -261,6 +472,24 @@ oe_libinstall() { __runcmd cd "$olddir" } +def package_stagefile(file, d): + + if bb.data.getVar('PSTAGING_ACTIVE', d, True) == "1": + destfile = file.replace(bb.data.getVar("TMPDIR", d, 1), bb.data.getVar("PSTAGE_TMPDIR_STAGE", d, 1)) + bb.mkdirhier(os.path.dirname(destfile)) + #print "%s to %s" % (file, destfile) + bb.copyfile(file, destfile) + +package_stagefile_shell() { + if [ "$PSTAGING_ACTIVE" = "1" ]; then + srcfile=$1 + destfile=`echo $srcfile | sed s#${TMPDIR}#${PSTAGE_TMPDIR_STAGE}#` + destdir=`dirname $destfile` + mkdir -p $destdir + cp -dp $srcfile $destfile + fi +} + oe_machinstall() { # Purpose: Install machine dependent files, if available # If not available, check if there is a default @@ -291,18 +520,6 @@ oe_machinstall() { fi } -addtask showdata -do_showdata[nostamp] = "1" -python do_showdata() { - import sys - # emit variables and shell functions - bb.data.emit_env(sys.__stdout__, d, True) - # emit the metadata which isnt valid shell - for e in d.keys(): - if bb.data.getVarFlag(e, 'python', d): - sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1))) -} - addtask listtasks do_listtasks[nostamp] = "1" python do_listtasks() { @@ -318,44 +535,95 @@ python do_listtasks() { addtask clean do_clean[dirs] = "${TOPDIR}" do_clean[nostamp] = "1" -do_clean[bbdepcmd] = "" python base_do_clean() { """clear the build and temp directories""" dir = bb.data.expand("${WORKDIR}", d) if dir == '//': raise bb.build.FuncFailed("wrong DATADIR") - bb.note("removing " + dir) + bb.note("removing " + base_path_out(dir, d)) os.system('rm -rf ' + dir) dir = "%s.*" % bb.data.expand(bb.data.getVar('STAMP', d), d) - bb.note("removing " + dir) + bb.note("removing " + base_path_out(dir, d)) os.system('rm -f '+ dir) } -addtask rebuild +python do_cleanall() { + pass +} +do_cleanall[recrdeptask] = "do_clean" +addtask cleanall after do_clean + +addtask rebuild after do_${BB_DEFAULT_TASK} do_rebuild[dirs] = "${TOPDIR}" do_rebuild[nostamp] = "1" -do_rebuild[bbdepcmd] = "" python base_do_rebuild() { """rebuild a package""" - bb.build.exec_task('do_clean', d) - bb.build.exec_task('do_' + bb.data.getVar('BB_DEFAULT_TASK', d, 1), d) } addtask mrproper do_mrproper[dirs] = "${TOPDIR}" do_mrproper[nostamp] = "1" -do_mrproper[bbdepcmd] = "" python base_do_mrproper() { """clear downloaded sources, build and temp directories""" dir = bb.data.expand("${DL_DIR}", d) if dir == '/': bb.build.FuncFailed("wrong DATADIR") bb.debug(2, "removing " + dir) os.system('rm -rf ' + dir) - bb.build.exec_task('do_clean', d) + bb.build.exec_func('do_clean', d) +} + +addtask distclean +do_distclean[dirs] = "${TOPDIR}" +do_distclean[nostamp] = "1" +python base_do_distclean() { + """clear downloaded sources, build and temp directories""" + + bb.build.exec_func('do_clean', d) + + src_uri = bb.data.getVar('SRC_URI', d, 1) + if not src_uri: + return + + for uri in src_uri.split(): + if bb.decodeurl(uri)[0] == "file": + continue + + try: + local = bb.data.expand(bb.fetch.localpath(uri, d), d) + except bb.MalformedUrl, e: + bb.debug(1, 'Unable to generate local path for malformed uri: %s' % e) + else: + bb.note("removing %s" % base_path_out(local, d)) + try: + if os.path.exists(local + ".md5"): + os.remove(local + ".md5") + if os.path.exists(local): + os.remove(local) + except OSError, e: + bb.note("Error in removal: %s" % e) +} + +SCENEFUNCS += "base_scenefunction" + +python base_do_setscene () { + for f in (bb.data.getVar('SCENEFUNCS', d, 1) or '').split(): + bb.build.exec_func(f, d) + if not os.path.exists(bb.data.getVar('STAMP', d, 1) + ".do_setscene"): + bb.build.make_stamp("do_setscene", d) +} +do_setscene[selfstamp] = "1" +addtask setscene before do_fetch + +python base_scenefunction () { + stamp = bb.data.getVar('STAMP', d, 1) + ".needclean" + if os.path.exists(stamp): + bb.build.exec_func("do_clean", d) } + addtask fetch do_fetch[dirs] = "${DL_DIR}" +do_fetch[depends] = "shasum-native:do_populate_staging" python base_do_fetch() { import sys @@ -371,6 +639,9 @@ python base_do_fetch() { except bb.fetch.NoMethodError: (type, value, traceback) = sys.exc_info() raise bb.build.FuncFailed("No method: %s" % value) + except bb.MalformedUrl: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("Malformed URL: %s" % value) try: bb.fetch.go(localdata) @@ -380,6 +651,49 @@ python base_do_fetch() { except bb.fetch.FetchError: (type, value, traceback) = sys.exc_info() raise bb.build.FuncFailed("Fetch failed: %s" % value) + except bb.fetch.MD5SumError: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("MD5 failed: %s" % value) + except: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("Unknown fetch Error: %s" % value) + + + # Verify the SHA and MD5 sums we have in OE and check what do + # in + checksum_paths = bb.data.getVar('BBPATH', d, True).split(":") + + # reverse the list to give precedence to directories that + # appear first in BBPATH + checksum_paths.reverse() + + checksum_files = ["%s/conf/checksums.ini" % path for path in checksum_paths] + try: + parser = base_chk_load_parser(checksum_files) + except ValueError: + bb.note("No conf/checksums.ini found, not checking checksums") + return + except: + bb.note("Creating the CheckSum parser failed: %s:%s" % (sys.exc_info()[0], sys.exc_info()[1])) + return + + pv = bb.data.getVar('PV', d, True) + pn = bb.data.getVar('PN', d, True) + + # Check each URI + for url in src_uri.split(): + localpath = bb.data.expand(bb.fetch.localpath(url, localdata), localdata) + (type,host,path,_,_,params) = bb.decodeurl(url) + uri = "%s://%s%s" % (type,host,path) + try: + if type in [ "http", "https", "ftp", "ftps" ]: + if not (base_chk_file_vars(parser, localpath, params, d) or base_chk_file(parser, pn, pv,uri, localpath, d)): + if not bb.data.getVar("OE_ALLOW_INSECURE_DOWNLOADS", d, True): + bb.fatal("%s-%s: %s has no checksum defined, cannot check archive integrity" % (pn,pv,uri)) + else: + bb.note("%s-%s: %s has no checksum defined, archive integrity not checked" % (pn,pv,uri)) + except Exception: + raise bb.build.FuncFailed("Checksum of '%s' failed" % uri) } addtask fetchall after do_fetch @@ -388,8 +702,59 @@ base_do_fetchall() { : } +addtask checkuri +do_checkuri[nostamp] = "1" +python do_checkuri() { + import sys + + localdata = bb.data.createCopy(d) + bb.data.update_data(localdata) + + src_uri = bb.data.getVar('SRC_URI', localdata, 1) + + try: + bb.fetch.init(src_uri.split(),d) + except bb.fetch.NoMethodError: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("No method: %s" % value) + + try: + bb.fetch.checkstatus(localdata) + except bb.fetch.MissingParameterError: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("Missing parameters: %s" % value) + except bb.fetch.FetchError: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("Fetch failed: %s" % value) + except bb.fetch.MD5SumError: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("MD5 failed: %s" % value) + except: + (type, value, traceback) = sys.exc_info() + raise bb.build.FuncFailed("Unknown fetch Error: %s" % value) +} + +addtask checkuriall after do_checkuri +do_checkuriall[recrdeptask] = "do_checkuri" +do_checkuriall[nostamp] = "1" +base_do_checkuriall() { + : +} + +addtask buildall after do_build +do_buildall[recrdeptask] = "do_build" +base_do_buildall() { + : +} + +def subprocess_setup(): + import signal + # Python installs a SIGPIPE handler by default. This is usually not what + # non-Python subprocesses expect. + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + def oe_unpack_file(file, data, url = None): - import bb, os + import subprocess if not url: url = "file://%s" % file dots = file.split(".") @@ -402,28 +767,31 @@ def oe_unpack_file(file, data, url = None): cmd = 'tar x --no-same-owner -f %s' % file elif file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'): cmd = 'tar xz --no-same-owner -f %s' % file - elif file.endswith('.tbz') or file.endswith('.tar.bz2'): + elif file.endswith('.tbz') or file.endswith('.tbz2') or file.endswith('.tar.bz2'): cmd = 'bzip2 -dc %s | tar x --no-same-owner -f -' % file elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'): cmd = 'gzip -dc %s > %s' % (file, efile) elif file.endswith('.bz2'): cmd = 'bzip2 -dc %s > %s' % (file, efile) - elif file.endswith('.zip'): - cmd = 'unzip -q' + elif file.endswith('.zip') or file.endswith('.jar'): + cmd = 'unzip -q -o' (type, host, path, user, pswd, parm) = bb.decodeurl(url) if 'dos' in parm: cmd = '%s -a' % cmd cmd = '%s %s' % (cmd, file) elif os.path.isdir(file): - filesdir = os.path.realpath(bb.data.getVar("FILESDIR", data, 1)) destdir = "." - if file[0:len(filesdir)] == filesdir: - destdir = file[len(filesdir):file.rfind('/')] - destdir = destdir.strip('/') - if len(destdir) < 1: - destdir = "." - elif not os.access("%s/%s" % (os.getcwd(), destdir), os.F_OK): - os.makedirs("%s/%s" % (os.getcwd(), destdir)) + filespath = bb.data.getVar("FILESPATH", data, 1).split(":") + for fp in filespath: + if file[0:len(fp)] == fp: + destdir = file[len(fp):file.rfind('/')] + destdir = destdir.strip('/') + if len(destdir) < 1: + destdir = "." + elif not os.access("%s/%s" % (os.getcwd(), destdir), os.F_OK): + os.makedirs("%s/%s" % (os.getcwd(), destdir)) + break + cmd = 'cp -pPR %s %s/%s/' % (file, os.getcwd(), destdir) else: (type, host, path, user, pswd, parm) = bb.decodeurl(url) @@ -445,15 +813,26 @@ def oe_unpack_file(file, data, url = None): if os.path.samefile(file, dest): return True + # Change to subdir before executing command + save_cwd = os.getcwd(); + parm = bb.decodeurl(url)[5] + if 'subdir' in parm: + newdir = ("%s/%s" % (os.getcwd(), parm['subdir'])) + bb.mkdirhier(newdir) + os.chdir(newdir) + cmd = "PATH=\"%s\" %s" % (bb.data.getVar('PATH', data, 1), cmd) - bb.note("Unpacking %s to %s/" % (file, os.getcwd())) - ret = os.system(cmd) + bb.note("Unpacking %s to %s/" % (base_path_out(file, data), base_path_out(os.getcwd(), data))) + ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True) + + os.chdir(save_cwd) + return ret == 0 addtask unpack after do_fetch do_unpack[dirs] = "${WORKDIR}" python base_do_unpack() { - import re, os + import re localdata = bb.data.createCopy(d) bb.data.update_data(localdata) @@ -466,63 +845,121 @@ python base_do_unpack() { try: local = bb.data.expand(bb.fetch.localpath(url, localdata), localdata) except bb.MalformedUrl, e: - raise FuncFailed('Unable to generate local path for malformed uri: %s' % e) - # dont need any parameters for extraction, strip them off - local = re.sub(';.*$', '', local) + raise bb.build.FuncFailed('Unable to generate local path for malformed uri: %s' % e) + if not local: + raise bb.build.FuncFailed('Unable to locate local file for %s' % url) local = os.path.realpath(local) ret = oe_unpack_file(local, localdata, url) if not ret: raise bb.build.FuncFailed() } +METADATA_SCM = "${@base_get_scm(d)}" +METADATA_REVISION = "${@base_get_scm_revision(d)}" +METADATA_BRANCH = "${@base_get_scm_branch(d)}" + +def base_get_scm(d): + from bb import which + baserepo = os.path.dirname(os.path.dirname(which(d.getVar("BBPATH", 1), "classes/base.bbclass"))) + for (scm, scmpath) in {"svn": ".svn", + "git": ".git", + "monotone": "_MTN"}.iteritems(): + if os.path.exists(os.path.join(baserepo, scmpath)): + return "%s %s" % (scm, baserepo) + return "<unknown> %s" % baserepo + +def base_get_scm_revision(d): + (scm, path) = d.getVar("METADATA_SCM", 1).split() + try: + if scm != "<unknown>": + return globals()["base_get_metadata_%s_revision" % scm](path, d) + else: + return scm + except KeyError: + return "<unknown>" + +def base_get_scm_branch(d): + (scm, path) = d.getVar("METADATA_SCM", 1).split() + try: + if scm != "<unknown>": + return globals()["base_get_metadata_%s_branch" % scm](path, d) + else: + return scm + except KeyError: + return "<unknown>" + +def base_get_metadata_monotone_branch(path, d): + monotone_branch = "<unknown>" + try: + monotone_branch = file( "%s/_MTN/options" % path ).read().strip() + if monotone_branch.startswith( "database" ): + monotone_branch_words = monotone_branch.split() + monotone_branch = monotone_branch_words[ monotone_branch_words.index( "branch" )+1][1:-1] + except: + pass + return monotone_branch + +def base_get_metadata_monotone_revision(path, d): + monotone_revision = "<unknown>" + try: + monotone_revision = file( "%s/_MTN/revision" % path ).read().strip() + if monotone_revision.startswith( "format_version" ): + monotone_revision_words = monotone_revision.split() + monotone_revision = monotone_revision_words[ monotone_revision_words.index( "old_revision" )+1][1:-1] + except IOError: + pass + return monotone_revision + +def base_get_metadata_svn_revision(path, d): + revision = "<unknown>" + try: + revision = file( "%s/.svn/entries" % path ).readlines()[3].strip() + except IOError: + pass + return revision + +def base_get_metadata_git_branch(path, d): + branch = os.popen('cd %s; PATH=%s git symbolic-ref HEAD 2>/dev/null' % (path, d.getVar("PATH", 1))).read().rstrip() + + if len(branch) != 0: + return branch.replace("refs/heads/", "") + return "<unknown>" + +def base_get_metadata_git_revision(path, d): + rev = os.popen("cd %s; PATH=%s git show-ref HEAD 2>/dev/null" % (path, d.getVar("PATH", 1))).read().split(" ")[0].rstrip() + if len(rev) != 0: + return rev + return "<unknown>" + addhandler base_eventhandler python base_eventhandler() { from bb import note, error, data from bb.event import Handled, NotHandled, getName - import os - messages = {} - messages["Completed"] = "completed" - messages["Succeeded"] = "completed" - messages["Started"] = "started" - messages["Failed"] = "failed" name = getName(e) - msg = "" - if name.startswith("Pkg"): - msg += "package %s: " % data.getVar("P", e.data, 1) - msg += messages.get(name[3:]) or name[3:] - elif name.startswith("Task"): - msg += "package %s: task %s: " % (data.getVar("PF", e.data, 1), e.task) - msg += messages.get(name[4:]) or name[4:] - elif name.startswith("Build"): - msg += "build %s: " % e.name - msg += messages.get(name[5:]) or name[5:] + if name == "TaskCompleted": + msg = "package %s: task %s is complete." % (data.getVar("PF", e.data, 1), e.task) elif name == "UnsatisfiedDep": - msg += "package %s: dependency %s %s" % (e.pkg, e.dep, name[:-3].lower()) - if msg: - note(msg) + msg = "package %s: dependency %s %s" % (e.pkg, e.dep, name[:-3].lower()) + else: + return NotHandled + + # Only need to output when using 1.8 or lower, the UI code handles it + # otherwise + if (int(bb.__version__.split(".")[0]) <= 1 and int(bb.__version__.split(".")[1]) <= 8): + if msg: + note(msg) if name.startswith("BuildStarted"): bb.data.setVar( 'BB_VERSION', bb.__version__, e.data ) - path_to_bbfiles = bb.data.getVar( 'BBFILES', e.data, 1 ) - path_to_packages = path_to_bbfiles[:path_to_bbfiles.rindex( "packages" )] - monotone_revision = "<unknown>" - try: - monotone_revision = file( "%s/_MTN/revision" % path_to_packages ).read().strip() - if monotone_revision.startswith( "format_version" ): - monotone_revision_words = monotone_revision.split() - monotone_revision = monotone_revision_words[ monotone_revision_words.index( "old_revision" )+1][1:-1] - except IOError: - pass - bb.data.setVar( 'OE_REVISION', monotone_revision, e.data ) - statusvars = ['BB_VERSION', 'OE_REVISION', 'TARGET_ARCH', 'TARGET_OS', 'MACHINE', 'DISTRO', 'DISTRO_VERSION','TARGET_FPU'] - statuslines = ["%-14s = \"%s\"" % (i, bb.data.getVar(i, e.data, 1) or '') for i in statusvars] - statusmsg = "\nOE Build Configuration:\n%s\n" % '\n'.join(statuslines) + statusvars = bb.data.getVar("BUILDCFG_VARS", e.data, 1).split() + statuslines = ["%-17s = \"%s\"" % (i, bb.data.getVar(i, e.data, 1) or '') for i in statusvars] + statusmsg = "\n%s\n%s\n" % (bb.data.getVar("BUILDCFG_HEADER", e.data, 1), "\n".join(statuslines)) print statusmsg - needed_vars = [ "TARGET_ARCH", "TARGET_OS" ] + needed_vars = bb.data.getVar("BUILDCFG_NEEDEDVARS", e.data, 1).split() pesteruser = [] for v in needed_vars: val = bb.data.getVar(v, e.data, 1) @@ -531,6 +968,18 @@ python base_eventhandler() { if pesteruser: bb.fatal('The following variable(s) were not set: %s\nPlease set them directly, or choose a MACHINE or DISTRO that sets them.' % ', '.join(pesteruser)) + # + # Handle removing stamps for 'rebuild' task + # + if name.startswith("StampUpdate"): + for (fn, task) in e.targets: + #print "%s %s" % (task, fn) + if task == "do_rebuild": + dir = "%s.*" % e.stampPrefix[fn] + bb.note("Removing stamps: " + dir) + os.system('rm -f '+ dir) + os.system('touch ' + e.stampPrefix[fn] + '.needclean') + if not data in e.__dict__: return NotHandled @@ -545,7 +994,6 @@ python base_eventhandler() { addtask configure after do_unpack do_patch do_configure[dirs] = "${S} ${B}" -do_configure[bbdepcmd] = "do_populate_staging" do_configure[deptask] = "do_populate_staging" base_do_configure() { : @@ -553,7 +1001,6 @@ base_do_configure() { addtask compile after do_configure do_compile[dirs] = "${S} ${B}" -do_compile[bbdepcmd] = "do_populate_staging" base_do_compile() { if [ -e Makefile -o -e makefile ]; then oe_runmake || die "make failed" @@ -562,25 +1009,156 @@ base_do_compile() { fi } -base_do_stage () { - : + +sysroot_stage_dir() { + src="$1" + dest="$2" + # This will remove empty directories so we can ignore them + rmdir "$src" 2> /dev/null || true + if [ -d "$src" ]; then + mkdir -p "$dest" + cp -fpPR "$src"/* "$dest" + fi } -do_populate_staging[dirs] = "${STAGING_DIR}/${TARGET_SYS}/bin ${STAGING_DIR}/${TARGET_SYS}/lib \ - ${STAGING_DIR}/${TARGET_SYS}/include \ - ${STAGING_DIR}/${BUILD_SYS}/bin ${STAGING_DIR}/${BUILD_SYS}/lib \ - ${STAGING_DIR}/${BUILD_SYS}/include \ +sysroot_stage_libdir() { + src="$1" + dest="$2" + + olddir=`pwd` + cd $src + las=$(find . -name \*.la -type f) + cd $olddir + echo "Found la files: $las" + for i in $las + do + sed -e 's/^installed=yes$/installed=no/' \ + -e '/^dependency_libs=/s,${WORKDIR}[[:alnum:]/\._+-]*/\([[:alnum:]\._+-]*\),${STAGING_LIBDIR}/\1,g' \ + -e "/^dependency_libs=/s,\([[:space:]']\)${libdir},\1${STAGING_LIBDIR},g" \ + -i $src/$i + done + sysroot_stage_dir $src $dest +} + +sysroot_stage_dirs() { + from="$1" + to="$2" + + sysroot_stage_dir $from${includedir} $to${STAGING_INCDIR} + if [ "${BUILD_SYS}" = "${HOST_SYS}" ]; then + sysroot_stage_dir $from${bindir} $to${STAGING_DIR_HOST}${bindir} + sysroot_stage_dir $from${sbindir} $to${STAGING_DIR_HOST}${sbindir} + sysroot_stage_dir $from${base_bindir} $to${STAGING_DIR_HOST}${base_bindir} + sysroot_stage_dir $from${base_sbindir} $to${STAGING_DIR_HOST}${base_sbindir} + sysroot_stage_dir $from${libexecdir} $to${STAGING_DIR_HOST}${libexecdir} + if [ "${prefix}/lib" != "${libdir}" ]; then + # python puts its files in here, make sure they are staged as well + autotools_stage_dir $from/${prefix}/lib $to${STAGING_DIR_HOST}${prefix}/lib + fi + fi + if [ -d $from${libdir} ] + then + sysroot_stage_libdir $from/${libdir} $to${STAGING_LIBDIR} + fi + if [ -d $from${base_libdir} ] + then + sysroot_stage_libdir $from${base_libdir} $to${STAGING_DIR_HOST}${base_libdir} + fi + sysroot_stage_dir $from${datadir} $to${STAGING_DATADIR} +} + +sysroot_stage_all() { + sysroot_stage_dirs ${D} ${SYSROOT_DESTDIR} +} + +def is_legacy_staging(d): + stagefunc = bb.data.getVar('do_stage', d, True) + legacy = True + if stagefunc is None: + legacy = False + elif stagefunc.strip() == "autotools_stage_all": + legacy = False + elif stagefunc.strip() == "do_stage_native" and bb.data.getVar('AUTOTOOLS_NATIVE_STAGE_INSTALL', d, 1) == "1": + legacy = False + elif bb.data.getVar('NATIVE_INSTALL_WORKS', d, 1) == "1": + legacy = False + if bb.data.getVar('PSTAGE_BROKEN_DESTDIR', d, 1) == "1": + legacy = True + if bb.data.getVar('FORCE_LEGACY_STAGING', d, 1) == "1": + legacy = True + return legacy + +do_populate_staging[dirs] = "${STAGING_DIR_TARGET}/${bindir} ${STAGING_DIR_TARGET}/${libdir} \ + ${STAGING_DIR_TARGET}/${includedir} \ + ${STAGING_BINDIR_NATIVE} ${STAGING_LIBDIR_NATIVE} \ + ${STAGING_INCDIR_NATIVE} \ ${STAGING_DATADIR} \ ${S} ${B}" -addtask populate_staging after do_package_write +# Could be compile but populate_staging and do_install shouldn't run at the same time +addtask populate_staging after do_install + +SYSROOT_PREPROCESS_FUNCS ?= "" +SYSROOT_DESTDIR = "${WORKDIR}/sysroot-destdir/" +SYSROOT_LOCK = "${STAGING_DIR}/staging.lock" + +python populate_staging_prehook () { + return +} + +python populate_staging_posthook () { + return +} + +packagedstaging_fastpath () { + : +} python do_populate_staging () { - bb.build.exec_func('do_stage', d) + # + # if do_stage exists, we're legacy. In that case run the do_stage, + # modify the SYSROOT_DESTDIR variable and then run the staging preprocess + # functions against staging directly. + # + # Otherwise setup a destdir, copy the results from do_install + # and run the staging preprocess against that + # + pstageactive = (bb.data.getVar("PSTAGING_ACTIVE", d, True) == "1") + lockfile = bb.data.getVar("SYSROOT_LOCK", d, True) + stagefunc = bb.data.getVar('do_stage', d, True) + legacy = is_legacy_staging(d) + if legacy: + bb.data.setVar("SYSROOT_DESTDIR", "", d) + bb.note("Legacy staging mode for %s" % bb.data.getVar("FILE", d, True)) + if bb.data.getVarFlags('do_stage', d) is None: + bb.fatal("This recipe (%s) has a do_stage_prepend or do_stage_append and do_stage now doesn't exist. Please rename this to do_stage()" % bb.data.getVar("FILE", d, True)) + lock = bb.utils.lockfile(lockfile) + bb.build.exec_func('populate_staging_prehook', d) + bb.build.exec_func('do_stage', d) + for f in (bb.data.getVar('SYSROOT_PREPROCESS_FUNCS', d, True) or '').split(): + bb.build.exec_func(f, d) + bb.build.exec_func('populate_staging_posthook', d) + bb.utils.unlockfile(lock) + else: + dest = bb.data.getVar('D', d, True) + sysrootdest = bb.data.expand('${SYSROOT_DESTDIR}${STAGING_DIR_TARGET}', d) + bb.mkdirhier(sysrootdest) + + bb.build.exec_func("sysroot_stage_all", d) + #os.system('cp -pPR %s/* %s/' % (dest, sysrootdest)) + for f in (bb.data.getVar('SYSROOT_PREPROCESS_FUNCS', d, True) or '').split(): + bb.build.exec_func(f, d) + bb.build.exec_func("packagedstaging_fastpath", d) + + lock = bb.utils.lockfile(lockfile) + os.system(bb.data.expand('cp -pPR ${SYSROOT_DESTDIR}${TMPDIR}/* ${TMPDIR}/', d)) + bb.utils.unlockfile(lock) } addtask install after do_compile do_install[dirs] = "${D} ${S} ${B}" +# Remove and re-create ${D} so that is it guaranteed to be empty +do_install[cleandirs] = "${D}" base_do_install() { : @@ -594,6 +1172,8 @@ addtask build after do_populate_staging do_build = "" do_build[func] = "1" +inherit packagedata + # Functions that update metadata based on files outputted # during the build process. @@ -614,69 +1194,23 @@ def explode_deps(s): r.append(i) return r -def packaged(pkg, d): - import os, bb - return os.access(bb.data.expand('${STAGING_DIR}/pkgdata/runtime/%s.packaged' % pkg, d), os.R_OK) - -def read_pkgdatafile(fn): - pkgdata = {} - - def decode(str): - import codecs - c = codecs.getdecoder("string_escape") - return c(str)[0] - - import os - if os.access(fn, os.R_OK): - import re - f = file(fn, 'r') - lines = f.readlines() - f.close() - r = re.compile("([^:]+):\s*(.*)") - for l in lines: |
