diff options
Diffstat (limited to 'meta-openembedded/meta-oe/classes')
-rw-r--r-- | meta-openembedded/meta-oe/classes/breakpad.bbclass | 33 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/dos2unix.bbclass | 14 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/gitpkgv.bbclass | 122 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/gitver.bbclass | 84 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/gpe.bbclass | 17 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/machine_kernel_pr.bbclass | 8 | ||||
-rw-r--r-- | meta-openembedded/meta-oe/classes/socorro-syms.bbclass | 231 |
7 files changed, 509 insertions, 0 deletions
diff --git a/meta-openembedded/meta-oe/classes/breakpad.bbclass b/meta-openembedded/meta-oe/classes/breakpad.bbclass new file mode 100644 index 000000000..36f11ff48 --- /dev/null +++ b/meta-openembedded/meta-oe/classes/breakpad.bbclass @@ -0,0 +1,33 @@ +# Class to inherit when you want to build against Breakpad. +# Apart from inheriting this class, you need to set BREAKPAD_BIN in +# your recipe, and make sure that you link against libbreakpad_client.a. + +DEPENDS += "breakpad breakpad-native" + +CFLAGS += "-I${STAGING_DIR_TARGET}${includedir}/breakpad " +CXXFLAGS += "-I${STAGING_DIR_TARGET}${includedir}/breakpad " + +BREAKPAD_BIN ?= "" + +python () { + breakpad_bin = d.getVar("BREAKPAD_BIN") + + if not breakpad_bin: + PN = d.getVar("PN") + FILE = os.path.basename(d.getVar("FILE")) + bb.error("To build %s, see breakpad.bbclass for instructions on \ + setting up your Breakpad configuration" % PN) + raise ValueError('BREAKPAD_BIN not defined in %s' % PN) +} + +# Add creation of symbols here +PACKAGE_PREPROCESS_FUNCS += "breakpad_package_preprocess" +breakpad_package_preprocess () { + mkdir -p ${PKGD}/usr/share/breakpad-syms + find ${D} -name ${BREAKPAD_BIN} -exec sh -c "dump_syms {} > ${PKGD}/usr/share/breakpad-syms/${BREAKPAD_BIN}.sym" \; +} + +PACKAGES =+ "${PN}-breakpad" + +FILES_${PN}-breakpad = "/usr/share/breakpad-syms" + diff --git a/meta-openembedded/meta-oe/classes/dos2unix.bbclass b/meta-openembedded/meta-oe/classes/dos2unix.bbclass new file mode 100644 index 000000000..1bad998dd --- /dev/null +++ b/meta-openembedded/meta-oe/classes/dos2unix.bbclass @@ -0,0 +1,14 @@ +# Class for use to convert all CRLF line terminators to LF +# provided that some projects are being developed/maintained +# on Windows so they have different line terminators(CRLF) vs +# on Linux(LF), which can cause annoying patching errors during +# git push/checkout processes. + +do_convert_crlf_to_lf[depends] += "dos2unix-native:do_populate_sysroot" + +# Convert CRLF line terminators to LF +do_convert_crlf_to_lf () { + find ${S} -type f -exec dos2unix {} \; +} + +addtask convert_crlf_to_lf after do_unpack before do_patch diff --git a/meta-openembedded/meta-oe/classes/gitpkgv.bbclass b/meta-openembedded/meta-oe/classes/gitpkgv.bbclass new file mode 100644 index 000000000..2d9680a35 --- /dev/null +++ b/meta-openembedded/meta-oe/classes/gitpkgv.bbclass @@ -0,0 +1,122 @@ +# gitpkgv.bbclass provides a GITPKGV and GITPKGVTAG variables to be +# used in PKGV, as described bellow: +# +# - GITPKGV which is a sortable version with the format NN+GITHASH, to +# be used in PKGV, where +# +# NN equals the total number of revs up to SRCREV +# GITHASH is SRCREV's (full) hash +# +# - GITPKGVTAG which is the output of 'git describe' allowing for +# automatic versioning +# +# gitpkgv.bbclass assumes the git repository has been cloned, and +# contains SRCREV. So ${GITPKGV} and ${GITPKGVTAG} should never be +# used in PV, only in PKGV. It can handle SRCREV = ${AUTOREV}, as +# well as SRCREV = "<some fixed git hash>". +# +# WARNING: if upstream repository is always using consistent and +# sortable tag name scheme you can get sortable version including tag +# name with ${GITPKGVTAG}, but be aware that ie tag sequence "v1.0, +# v1.2, xtest, v2.0" will force you to increment PE to get upgradeable +# path to v2.0 revisions +# +# use example: +# +# inherit gitpkgv +# +# PV = "1.0+gitr${SRCPV}" # expands to something like 1.0+gitr3+4c1c21d7dbbf93b0df336994524313dfe0d4963b +# PKGV = "1.0+gitr${GITPKGV}" # expands also to something like 1.0+gitr31337+4c1c21d7d +# +# or +# +# inherit gitpkgv +# +# PV = "1.0+gitr${SRCPV}" # expands to something like 1.0+gitr3+4c1c21d7dbbf93b0df336994524313dfe0d4963b +# PKGV = "${GITPKGVTAG}" # expands to something like 1.0-31337+g4c1c21d +# if there is tag v1.0 before this revision or +# ver1.0-31337+g4c1c21d if there is tag ver1.0 + +GITPKGV = "${@get_git_pkgv(d, False)}" +GITPKGVTAG = "${@get_git_pkgv(d, True)}" + +def gitpkgv_drop_tag_prefix(version): + import re + if re.match("v\d", version): + return version[1:] + else: + return version + +def get_git_pkgv(d, use_tags): + import os + import bb + from pipes import quote + + src_uri = d.getVar('SRC_URI').split() + fetcher = bb.fetch2.Fetch(src_uri, d) + ud = fetcher.ud + + # + # If SRCREV_FORMAT is set respect it for tags + # + format = d.getVar('SRCREV_FORMAT') + if not format: + names = [] + for url in ud.values(): + if url.type == 'git' or url.type == 'gitsm': + names.extend(url.revisions.keys()) + if len(names) > 0: + format = '_'.join(names) + else: + format = 'default' + + found = False + for url in ud.values(): + if url.type == 'git' or url.type == 'gitsm': + for name, rev in url.revisions.items(): + if not os.path.exists(url.localpath): + return None + + found = True + + vars = { 'repodir' : quote(url.localpath), + 'rev' : quote(rev) } + + rev = bb.fetch2.get_srcrev(d).split('+')[1] + rev_file = os.path.join(url.localpath, "oe-gitpkgv_" + rev) + + if not os.path.exists(rev_file) or os.path.getsize(rev_file)==0: + commits = bb.fetch2.runfetchcmd( + "cd %(repodir)s && " + "git rev-list %(rev)s -- 2> /dev/null " + "| wc -l" % vars, + d, quiet=True).strip().lstrip('0') + + if commits != "": + oe.path.remove(rev_file, recurse=False) + with open(rev_file, "w") as f: + f.write("%d\n" % int(commits)) + else: + commits = "0" + else: + with open(rev_file, "r") as f: + commits = f.readline(128).strip() + + if use_tags: + try: + output = bb.fetch2.runfetchcmd( + "cd %(repodir)s && " + "git describe %(rev)s 2>/dev/null" % vars, + d, quiet=True).strip() + ver = gitpkgv_drop_tag_prefix(output) + except Exception: + ver = "0.0-%s-g%s" % (commits, vars['rev'][:7]) + else: + ver = "%s+%s" % (commits, vars['rev'][:7]) + + format = format.replace(name, ver) + + if found: + return format + + return '0+0' diff --git a/meta-openembedded/meta-oe/classes/gitver.bbclass b/meta-openembedded/meta-oe/classes/gitver.bbclass new file mode 100644 index 000000000..07f44c34b --- /dev/null +++ b/meta-openembedded/meta-oe/classes/gitver.bbclass @@ -0,0 +1,84 @@ +# Copyright (C) 2009 Chris Larson <clarson@kergoth.com> +# Released under the MIT license (see COPYING.MIT for the terms) +# +# gitver.bbclass provides a GITVER variable which is a (fairly) sane version, +# for use in ${PV}, extracted from the ${S} git checkout, assuming it is one. +# This is most useful in concert with srctree.bbclass. + +def git_drop_tag_prefix(version): + import re + if re.match("v\d", version): + return version[1:] + else: + return version + +GIT_TAGADJUST = "git_drop_tag_prefix(version)" +GITVER = "${@get_git_pv(d, tagadjust=lambda version:${GIT_TAGADJUST})}" +GITSHA = "${@get_git_hash(d)}" + +def gitrev_run(cmd, path): + (output, error) = bb.process.run(cmd, cwd=path) + return output.rstrip() + +def get_git_pv(d, tagadjust=None): + import os + + srcdir = d.getVar("EXTERNALSRC") or d.getVar("S") + gitdir = os.path.abspath(os.path.join(srcdir, ".git")) + try: + ver = gitrev_run("git describe --tags", gitdir) + except: + try: + ver = gitrev_run("git rev-parse --short HEAD", gitdir) + if ver: + return "0.0+%s" % ver + else: + return "0.0" + + except Exception as exc: + raise bb.parse.SkipRecipe(str(exc)) + + if ver and tagadjust: + ver = tagadjust(ver) + return ver + +def get_git_hash(d): + import os + + srcdir = d.getVar("EXTERNALSRC") or d.getVar("S") + gitdir = os.path.abspath(os.path.join(srcdir, ".git")) + try: + rev = gitrev_run("git rev-list HEAD -1") + return rev[:7] + except Exception as exc: + bb.fatal(str(exc)) + +def mark_recipe_dependencies(path, d): + from bb.parse import mark_dependency + + gitdir = os.path.join(path, ".git") + + # Force the recipe to be reparsed so the version gets bumped + # if the active branch is switched, or if the branch changes. + mark_dependency(d, os.path.join(gitdir, "HEAD")) + + # Force a reparse if anything in the index changes. + mark_dependency(d, os.path.join(gitdir, "index")) + + try: + ref = gitrev_run("git symbolic-ref -q HEAD", gitdir) + except bb.process.CmdError: + pass + else: + if ref: + mark_dependency(d, os.path.join(gitdir, ref)) + + # Catch new tags. + tagdir = os.path.join(gitdir, "refs", "tags") + if os.path.exists(tagdir): + mark_dependency(d, tagdir) + +python () { + srcdir = d.getVar("EXTERNALSRC") or d.getVar("S") + mark_recipe_dependencies(srcdir, d) +} diff --git a/meta-openembedded/meta-oe/classes/gpe.bbclass b/meta-openembedded/meta-oe/classes/gpe.bbclass new file mode 100644 index 000000000..9fc136590 --- /dev/null +++ b/meta-openembedded/meta-oe/classes/gpe.bbclass @@ -0,0 +1,17 @@ +DEPENDS_prepend = "virtual/libintl intltool-native " +GPE_TARBALL_SUFFIX ?= "gz" +SRC_URI = "${GPE_MIRROR}/${BP}.tar.${GPE_TARBALL_SUFFIX}" +FILES_${PN} += "${datadir}/gpe ${datadir}/application-registry" +SECTION ?= "gpe" + +inherit gettext + +gpe_do_compile() { + oe_runmake PREFIX=${prefix} +} + +gpe_do_install() { + oe_runmake PREFIX=${prefix} DESTDIR=${D} install +} + +EXPORT_FUNCTIONS do_compile do_install diff --git a/meta-openembedded/meta-oe/classes/machine_kernel_pr.bbclass b/meta-openembedded/meta-oe/classes/machine_kernel_pr.bbclass new file mode 100644 index 000000000..e48bd017f --- /dev/null +++ b/meta-openembedded/meta-oe/classes/machine_kernel_pr.bbclass @@ -0,0 +1,8 @@ +python __anonymous () { + + machine_kernel_pr = d.getVar('MACHINE_KERNEL_PR') + + if machine_kernel_pr: + d.setVar('PR', machine_kernel_pr) +} + diff --git a/meta-openembedded/meta-oe/classes/socorro-syms.bbclass b/meta-openembedded/meta-oe/classes/socorro-syms.bbclass new file mode 100644 index 000000000..cc435aba1 --- /dev/null +++ b/meta-openembedded/meta-oe/classes/socorro-syms.bbclass @@ -0,0 +1,231 @@ +# Inherit this class when you want to allow Mozilla Socorro to link Breakpad's +# stack trace information to the correct source code revision. +# This class creates a new version of the symbol file (.sym) created by +# Breakpad. The absolute file paths in the symbol file will be replaced by VCS, +# branch, file and revision of the source file. That information facilitates the +# lookup of a particular source code line in the stack trace. +# +# Use example: +# +# BREAKPAD_BIN = "YourBinary" +# inherit socorro-syms +# + +# We depend on Breakpad creating the original symbol file. +inherit breakpad + +PACKAGE_PREPROCESS_FUNCS += "symbol_file_preprocess" +PACKAGES =+ "${PN}-socorro-syms" +FILES_${PN}-socorro-syms = "/usr/share/socorro-syms" + + +python symbol_file_preprocess() { + + package_dir = d.getVar("PKGD") + breakpad_bin = d.getVar("BREAKPAD_BIN") + if not breakpad_bin: + package_name = d.getVar("PN") + bb.error("Package %s depends on Breakpad via socorro-syms. See " + "breakpad.bbclass for instructions on setting up the Breakpad " + "configuration." % package_name) + raise ValueError("BREAKPAD_BIN not defined in %s." % package_name) + + sym_file_name = breakpad_bin + ".sym" + + breakpad_syms_dir = os.path.join( + package_dir, "usr", "share", "breakpad-syms") + socorro_syms_dir = os.path.join( + package_dir, "usr", "share", "socorro-syms") + if not os.path.exists(socorro_syms_dir): + os.makedirs(socorro_syms_dir) + + breakpad_sym_file_path = os.path.join(breakpad_syms_dir, sym_file_name) + socorro_sym_file_path = os.path.join(socorro_syms_dir, sym_file_name) + + create_socorro_sym_file(d, breakpad_sym_file_path, socorro_sym_file_path) + + arrange_socorro_sym_file(socorro_sym_file_path, socorro_syms_dir) + + return +} + + +def run_command(command, directory): + + (output, error) = bb.process.run(command, cwd=directory) + if error: + raise bb.process.ExecutionError(command, error) + + return output.rstrip() + + +def create_socorro_sym_file(d, breakpad_sym_file_path, socorro_sym_file_path): + + # In the symbol file, all source files are referenced like the following. + # FILE 123 /path/to/some/File.cpp + # Go through all references and replace the file paths with repository + # paths. + with open(breakpad_sym_file_path, 'r') as breakpad_sym_file, \ + open(socorro_sym_file_path, 'w') as socorro_sym_file: + + for line in breakpad_sym_file: + if line.startswith("FILE "): + socorro_sym_file.write(socorro_file_reference(d, line)) + else: + socorro_sym_file.write(line) + + return + + +def socorro_file_reference(d, line): + + # The 3rd position is the file path. See example above. + source_file_path = line.split()[2] + source_file_repo_path = repository_path( + d, os.path.normpath(source_file_path)) + + # If the file could be found in any repository then replace it with the + # repository's path. + if source_file_repo_path: + return line.replace(source_file_path, source_file_repo_path) + + return line + + +def repository_path(d, source_file_path): + + if not os.path.isfile(source_file_path): + return None + + # Check which VCS is used and use that to extract repository information. + (output, error) = bb.process.run("git status", + cwd=os.path.dirname(source_file_path)) + if not error: + # Make sure the git repository we just found wasn't the yocto repository + # itself, i.e. the root of the repository we're looking for must be a + # child of the build directory TOPDIR. + git_root_dir = run_command( + "git rev-parse --show-toplevel", os.path.dirname(source_file_path)) + if not git_root_dir.startswith(d.getVar("TOPDIR")): + return None + + return git_repository_path(source_file_path) + + # Here we can add support for other VCSs like hg, svn, cvs, etc. + + # The source file isn't under any VCS so we leave it be. + return None + + +def is_local_url(url): + + return \ + url.startswith("file:") or url.startswith("/") or url.startswith("./") + + +def git_repository_path(source_file_path): + + import re + + # We need to extract the following. + # (1): VCS URL, (2): branch, (3): repo root directory name, (4): repo file, + # (5): revision. + + source_file_dir = os.path.dirname(source_file_path) + + # (1) Get the VCS URL and extract the server part, i.e. change the URL from + # gitolite@git.someserver.com:SomeRepo.git to just git.someserver.com. + source_long_url = run_command( + "git config --get remote.origin.url", source_file_dir) + + # The URL could be a local download directory. If so, get the URL again + # using the local directory's config file. + if is_local_url(source_long_url): + git_config_file = os.path.join(source_long_url, "config") + source_long_url = run_command( + "git config --file %s --get remote.origin.url" % git_config_file, + source_file_dir) + + # If also the download directory redirects to a local git directory, + # then we're probably using source code from a local debug branch which + # won't be accessible by Socorro. + if is_local_url(source_long_url): + return None + + # The URL can have several formats. A full list can be found using + # git help clone. Extract the server part with a regex. + url_match = re.search(".*(://|@)([^:/]*).*", source_long_url) + source_server = url_match.group(2) + + # (2) Get the branch for this file. + source_branch_list = run_command("git show-branch --list", source_file_dir) + source_branch_match = re.search(".*?\[(.*?)\].*", source_branch_list) + source_branch = source_branch_match.group(1) + + # (3) Since the repo root directory name can be changed without affecting + # git, we need to extract the name from something more reliable. + # The git URL has a repo name that we could use. We just need to strip off + # everything around it - from gitolite@git.someserver.com:SomeRepo.git/ to + # SomeRepo. + source_repo_dir = re.sub("/$", "", source_long_url) + source_repo_dir = re.sub("\.git$", "", source_repo_dir) + source_repo_dir = re.sub(".*[:/]", "", source_repo_dir) + + # (4) We know the file but want to remove all of the build system dependent + # path up to and including the repository's root directory, e.g. remove + # /home/someuser/dev/repo/projectx/ + source_toplevel = run_command( + "git rev-parse --show-toplevel", source_file_dir) + source_toplevel = source_toplevel + os.path.sep + source_file = source_file_path.replace(source_toplevel, "") + + # (5) Get the source revision this file is part of. + source_revision = run_command("git rev-parse HEAD", source_file_dir) + + # Assemble the repository path according to the Socorro format. + socorro_reference = "git:%s/%s:%s/%s:%s" % \ + (source_server, source_branch, + source_repo_dir, source_file, + source_revision) + + return socorro_reference + + +def arrange_socorro_sym_file(socorro_sym_file_path, socorro_syms_dir): + + import re + + # Breakpad's minidump_stackwalk needs a certain directory structure in order + # to find correct symbols when extracting a stack trace out of a minidump. + # The directory structure must look like the following. + # YourBinary/<hash>/YourBinary.sym + # YourLibrary.so/<hash>/YourLibrary.so.sym + # To be able to create such structure we need to extract the hash value that + # is found in each symbol file. The header of the symbol file looks + # something like this: + # MODULE Linux x86 A079E473106CE51C74C1C25AF536CCD30 YourBinary + # See + # http://code.google.com/p/google-breakpad/wiki/LinuxStarterGuide + + # Create the directory with the same name as the binary. + binary_dir = re.sub("\.sym$", "", socorro_sym_file_path) + if not os.path.exists(binary_dir): + os.makedirs(binary_dir) + + # Get the hash from the header of the symbol file. + with open(socorro_sym_file_path, 'r') as socorro_sym_file: + + # The hash is the 4th argument of the first line. + sym_file_hash = socorro_sym_file.readline().split()[3] + + # Create the hash directory. + hash_dir = os.path.join(binary_dir, sym_file_hash) + if not os.path.exists(hash_dir): + os.makedirs(hash_dir) + + # Move the symbol file to the hash directory. + sym_file_name = os.path.basename(socorro_sym_file_path) + os.rename(socorro_sym_file_path, os.path.join(hash_dir, sym_file_name)) + + return + |