<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:"Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle18
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Hi all,<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">For about two years now, we have been using Emscripten together with Yocto, via an emscripten.bbclass that I wrote. In a nutshell, it works by conducting the actual build in a Docker container, whose image is where Emscripten is actually
 installed.&nbsp; I mount all the necessary directories (e.g. ${B}, ${S}, etc.) into the container, and I&#8217;ve got some Python scripting that ensures that containers get cleaned up even if the build is aborted with Ctrl&#43;C or otherwise dies. All of our Emscripten-enabled
 recipes happen to be using CMake, so emscripten.bbclass is CMake specific. It&#8217;s basically a reimplementation of cmake.bbclass (from Poky) that happens to run in a container.<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">For the time being the specifics of how the Emscripten part works isn&#8217;t relevant (1). I provide it as background for what I really want to ask about, which is the Yocto-specific plumbing. Here&#8217;s a snippet of it:
<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">-------<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; # Copyright (C) 2020 Agilent Technologies, Inc.<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; # SPDX-License-Identifier: GPL-2.0-only<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp; &nbsp;CLASSOVERRIDE = &quot;class-emscripten&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; SPECIAL_PKGSUFFIX_class-emscripten &#43;= &quot;-emscripten&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; BASEDEPENDS_class-emscripten = &quot;&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; FILES_${PN} =&#43; &quot;${libdir}/*.js&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; export prefix = &quot;/usr/js&quot;<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; python emscripten_virtclass_handler() {<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pn = e.data.getVar(&quot;PN&quot;)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not pn.endswith(&quot;-emscripten&quot;):<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; classextend = e.data.getVar('BBCLASSEXTEND') or &quot;&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if &quot;emscripten&quot; not in classextend:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def map_dependencies(varname, d, suffix = &quot;&quot;):<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if suffix:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varname = varname &#43; &quot;_&quot; &#43; suffix<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deps = d.getVar(varname)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not deps:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deps = bb.utils.explode_deps(deps)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newdeps = []<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for dep in deps:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if dep == pn:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif dep in [&quot;cmake-native&quot;]:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif dep.endswith(&quot;-emscripten&quot;):<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newdeps.append(dep)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif dep.endswith(&quot;-native&quot;):<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bb.warn(&quot;emscripten.bbclass: Native dependency {0} will not be usable from within Emscripten Docker container&quot;.format(dep))<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newdeps.append(dep)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d.setVar(varname, &quot; &quot;.join(newdeps))<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.data.setVar(&quot;OVERRIDES&quot;, e.data.getVar(&quot;OVERRIDES&quot;, False) &#43; &quot;:virtclass-emscripten&quot;)<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;DEPENDS&quot;, e.data)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for pkg in [e.data.getVar(&quot;PN&quot;), &quot;&quot;, &quot;${PN}&quot;]:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;RDEPENDS&quot;, e.data, pkg)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;RRECOMMENDS&quot;, e.data, pkg)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;RSUGGESTS&quot;, e.data, pkg)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;RPROVIDES&quot;, e.data, pkg)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map_dependencies(&quot;RREPLACES&quot;, e.data, pkg)<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provides = e.data.getVar(&quot;PROVIDES&quot;)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nprovides = []<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for prov in provides.split():<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if prov.find(pn) != -1:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nprovides.append(prov)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif not prov.endswith(&quot;-emscripten&quot;):<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nprovides.append(prov.replace(prov, prov &#43; &quot;-emscripten&quot;))<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nprovides.append(prov)<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.data.setVar(&quot;PROVIDES&quot;, ' '.join(nprovides))<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; } <o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; addhandler emscripten_virtclass_handler<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; emscripten_virtclass_handler[eventmask] = &quot;bb.event.RecipePreFinalise&quot;<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; do_populate_sysroot[stamp-extra-info] = &quot;&quot;<o:p></o:p></p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp; do_packagedata[stamp-extra-info] = &quot;&quot;<o:p></o:p></p>
<p class="MsoNormal">-------<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">There are two main goals of this code. First, it sets up dependencies between -emscripten recipes. Second, it sets &#8216;prefix&#8217; to be &#8216;/usr/js/&#8217; so that, for example, a &#8220;foo&#8221; and &#8220;foo-emscripten&#8221; recipe that both install development headers
 won&#8217;t collide. I call this the &#8220;sub-sysroot&#8221;.<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">I have a few concerns/questions:<o:p></o:p></p>
<p class="MsoNormal">[a] Is the basic premise of a custom CLASSOVERRIDE supported by Yocto? Our situation seems a bit weird, because our emscripten recipes are still sort of &#8220;target&#8221; recipes, so I feel a bit funny completely wiping CLASSOVERRIDE.<o:p></o:p></p>
<p class="MsoNormal">[b] At the very least, I know I did something wrong, because sometimes we get weird warnings like:<o:p></o:p></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-family:&quot;Arial&quot;,sans-serif">WARNING: app-emscripten-1.0&#43;gitAUTOINC&#43;1d1073e7c4-r0 do_compile: Manifest /home/user/yocto/build/tmp/sstate-control/manifest-x86_64_x86_64-nativesdk-library-emscripten.populate_sysroot
 not found in my_mach cortexa9t2hf-neon cortexa9t2hf-vfp cortexa9hf-neon cortexa9hf-vfp armv7at2hf-neon armv7ahf-neon armv7at2hf-vfp armv7ahf-vfp armv6thf-vfp armv6hf-vfp armv5tehf-vfp armv5ehf-vfp armv5thf-vfp armv5hf-vfp allarch x86_64_x86_64-nativesdk (variant
 '')?<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal" style="margin-bottom:10.0pt;line-height:115%;text-autospace:none">
<span lang="EN">... usually followed by a build failure in &#8220;app-emscripten&#8221; because &#8220;library-emscripten:do_populate_sysroot&#8221; indeed didn&#8217;t run. Related to [a] or perhaps the stamp-extra-info lines?<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN">[c] Is there a better way to do the &#8220;sub-sysroot&#8221; (/usr/js)? Would multilib cover this whole use case?&nbsp; (2)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN">I appreciate any comments/help.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN">Chris<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<p class="MsoNormal">(1) I&#8217;m happy to cover it in a separate thread if people are interested. I hope to rewrite the class using Clang&#8217;s WebAssembly backend, rather than call out to the Emscripten container which has always seemed like a hack. Regardless, I
 will make what we have public on poky-contrib soon anyway.<o:p></o:p></p>
<p class="MsoNormal">(2) I suppose one option is to have Emscripten flavors of all the MACHINEs we are building for, but I&#8217;d like to avoid that. We only have a handful of Emscripten recipes, so a separate MACHINE at this time would be overkill.
<o:p></o:p></p>
</div>
</body>
</html>