In our environment, we have package that are store inside git in their own 
repo.  Using SRC_URI we fetch the code and build it from the git repo itself 
and all is fine.  When developer wants to change the content of the package, 
they had to clone, change, commit, push and only then they were able to test 
because yocto recipe clone/fetch from the git server only.

We investigated externalsrc to use it so to build from a local folder, but then 
this required that all our packages be located locally on disk.  In turn, that 
cause other kind of headaches.  

I came up with the following solution "alternatesrc.bbclass" which is based on 
"externalsrc.bbclass" and do nothing unless a folder exists at the 
"ALTERNATESRC" location.  If a folder exists there, then the git SRC_URI is 
ignored and the do_fetch, do_unpack & do_patch are disabled.  The code located 
at the folder is used as is (no specific branch are checked out so to allow 
testing local change that have not been committed).

I am hoping to get feedback and comments, and maybe help someone else by 
sharing this.

Since this is my first contribution, I apologize if I didn't do it properly.

---
 meta/classes/alternatesrc.bbclass | 70 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 meta/classes/alternatesrc.bbclass

diff --git a/meta/classes/alternatesrc.bbclass 
b/meta/classes/alternatesrc.bbclass
new file mode 100644
index 0000000000..13f85df851
--- /dev/null
+++ b/meta/classes/alternatesrc.bbclass
@@ -0,0 +1,72 @@
+# Copyright (C) 2017 Hewlett Packard Enterprise
+# Author: Yannick Koehler
+# Released under the MIT license (see COPYING.MIT for the terms)
+# Some code and influence taken from externalsrc.bbclass
+#
+# alternatesrc.bbclass enables use of an optionally existing source tree, 
usually external  
+# to the build system to build a piece of software rather than the usual 
fetch/unpack
+# process.
+#
+# To use, add alternatesrc to the global inherit and set ALTERNATESRC to point 
at the
+# directory you want to use containing the sources e.g. from local.conf for a 
recipe
+# called "myrecipe" you would do:
+#
+# INHERIT += "alternatesrc"
+# ALTERNATESRC_pn-myrecipe = "/path/to/my/source/tree"
+#
+
+ALTERNATESRC_COVEREDTASKS ?= "do_unpack do_fetch"
+
+python () {
+    alternatesrc = d.getVar('ALTERNATESRC', True)
+
+    if alternatesrc and os.path.isdir(alternatesrc):
+        # Make it obvious that this is happening, since forgetting about it 
could lead to much confusion
+        bb.note('NOTE: using alternate source tree %s' % 
(d.getVar('ALTERNATESRC', True)))
+
+        d.setVar('S', alternatesrc)
+
+        local_srcuri = []
+        fetch = bb.fetch2.Fetch((d.getVar('SRC_URI', True) or '').split(), d)
+        for url in fetch.urls:
+            url_data = fetch.ud[url]
+            parm = url_data.parm
+            if (url_data.type == 'file' or
+                    'type' in parm and parm['type'] == 'kmeta'):
+                local_srcuri.append(url)
+
+        d.setVar('SRC_URI', ' '.join(local_srcuri))
+
+        if '{SRCPV}' in d.getVar('PV', False):
+            # Dummy value because the default function can't be called with 
blank SRC_URI
+            d.setVar('SRCPV', '999')
+
+        tasks = filter(lambda k: d.getVarFlag(k, "task", True), d.keys())
+
+        for task in tasks:
+            #if task.endswith("_setscene"):
+            #    # sstate is never going to work for external source trees, 
disable it
+            #    bb.build.deltask(task, d)
+            #else:
+            # Since configure will likely touch ${S}, ensure only we lock so 
one task has access at a time
+            d.appendVarFlag(task, "lockfiles", " ${S}/singletask.lock")
+
+            # We do not want our source to be wiped out, ever (kernel.bbclass 
does this for do_clean)
+            cleandirs = (d.getVarFlag(task, 'cleandirs', False) or '').split()
+            setvalue = False
+            for cleandir in cleandirs[:]:
+                if d.expand(cleandir) == alternatesrc:
+                    cleandirs.remove(cleandir)
+                    setvalue = True
+            if setvalue:
+                d.setVarFlag(task, 'cleandirs', ' '.join(cleandirs))
+
+        fetch_tasks = ['do_fetch', 'do_unpack']
+
+        for task in d.getVar("ALTERNATESRC_COVEREDTASKS", True).split():
+            if local_srcuri and task in fetch_tasks:
+                continue
+            bb.build.deltask(task, d)
+    else:
+            bb.note('NOTE: using git source tree, since local folder %s is 
inexistent' % (d.getVar('ALTERNATESRC', True)))
+}
-- 
2.12.0

-- 
_______________________________________________
yocto mailing list
yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to