summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2016-10-04 22:31:16 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-10-05 10:10:11 +0100
commit18caacae069a025662fcdd96b846857fc3107e41 (patch)
tree3fbd57297f2548b45ee0a87ff80dfb79941674fe /scripts
parentee697d84ba2a83b196bd3b927a0b6047464f5292 (diff)
downloadpoky-18caacae069a025662fcdd96b846857fc3107e41.tar.gz
devtool: add: build nodejs-native if npm is needed and not available
If the user runs devtool add on an npm:// URL (or source tree that uses node.js), and npm is not available, just build nodejs-native instead of telling the user they need to do it; if that fails because there isn't any such recipe (which would be the default, since it's not in OE-Core) then produce a slightly more readable error message hinting at what the user needs to do. Note that this forces the use of nodejs-native rather than npm on the host - this makes sense for two reasons: (1) we need it to be compatible with nodejs for the target, and (2) we have to have a recipe for that anyway, so allowing you to avoid having a recipe for the native version isn't really beneficial. There's a bit of a hack in here in order to allow this - for node.js sources that aren't fetched via npm we don't know that they are that until we've fetched and unpacked them, by which time we're inside recipetool and have an active tinfoil instance that will prevent bitbake being run. To avoid this being an issue, we allow recipetool to get to the point where we know we need npm and then exit with a specific exit code, at which point devtool can try to build it and then if that succeeds, it will re-execute recipetool. This is definitely not ideal, but it can't really be refactored and done properly until we do the tinfoil2 refactoring; in the mean time though we still want to be helpful to the user. Fixes [YOCTO #10337]. (From OE-Core rev: f40662bde5aab158c4e4c3c3ff5e68665a4194a5) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/lib/devtool/__init__.py29
-rw-r--r--scripts/lib/devtool/standard.py31
-rw-r--r--scripts/lib/recipetool/create.py10
-rw-r--r--scripts/lib/recipetool/create_npm.py4
4 files changed, 60 insertions, 14 deletions
diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py
index b432e3d44e..e675133f63 100644
--- a/scripts/lib/devtool/__init__.py
+++ b/scripts/lib/devtool/__init__.py
@@ -259,3 +259,32 @@ def get_bbclassextend_targets(recipefile, pn):
259 elif variant in ['native', 'cross', 'crosssdk']: 259 elif variant in ['native', 'cross', 'crosssdk']:
260 targets.append('%s-%s' % (pn, variant)) 260 targets.append('%s-%s' % (pn, variant))
261 return targets 261 return targets
262
263def ensure_npm(config, basepath, fixed_setup=False):
264 """
265 Ensure that npm is available and either build it or show a
266 reasonable error message
267 """
268 tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
269 try:
270 nativepath = tinfoil.config_data.getVar('STAGING_BINDIR_NATIVE', True)
271 finally:
272 tinfoil.shutdown()
273
274 npmpath = os.path.join(nativepath, 'npm')
275 if not os.path.exists(npmpath):
276 logger.info('Building nodejs-native')
277 try:
278 exec_build_env_command(config.init_path, basepath,
279 'bitbake -q nodejs-native', watch=True)
280 except bb.process.ExecutionError as e:
281 if "Nothing PROVIDES 'nodejs-native'" in e.stdout:
282 if fixed_setup:
283 msg = 'nodejs-native is required for npm but is not available within this SDK'
284 else:
285 msg = 'nodejs-native is required for npm but is not available - you will likely need to add a layer that provides nodejs'
286 raise DevtoolError(msg)
287 else:
288 raise
289 if not os.path.exists(npmpath):
290 raise DevtoolError('Built nodejs-native but npm binary still could not be found at %s' % npmpath)
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 02ed23574b..4b9b173156 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -30,7 +30,7 @@ import errno
30import glob 30import glob
31import filecmp 31import filecmp
32from collections import OrderedDict 32from collections import OrderedDict
33from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, use_external_build, setup_git_repo, recipe_to_append, get_bbclassextend_targets, DevtoolError 33from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, use_external_build, setup_git_repo, recipe_to_append, get_bbclassextend_targets, ensure_npm, DevtoolError
34from devtool import parse_recipe 34from devtool import parse_recipe
35 35
36logger = logging.getLogger('devtool') 36logger = logging.getLogger('devtool')
@@ -128,6 +128,9 @@ def add(args, config, basepath, workspace):
128 color = args.color 128 color = args.color
129 extracmdopts = '' 129 extracmdopts = ''
130 if args.fetchuri: 130 if args.fetchuri:
131 if args.fetchuri.startswith('npm://'):
132 ensure_npm(config, basepath, args.fixed_setup)
133
131 source = args.fetchuri 134 source = args.fetchuri
132 if srctree: 135 if srctree:
133 extracmdopts += ' -x %s' % srctree 136 extracmdopts += ' -x %s' % srctree
@@ -150,13 +153,23 @@ def add(args, config, basepath, workspace):
150 153
151 tempdir = tempfile.mkdtemp(prefix='devtool') 154 tempdir = tempfile.mkdtemp(prefix='devtool')
152 try: 155 try:
153 try: 156 while True:
154 stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create -o %s "%s" %s' % (color, tempdir, source, extracmdopts)) 157 try:
155 except bb.process.ExecutionError as e: 158 stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create -o %s "%s" %s' % (color, tempdir, source, extracmdopts))
156 if e.exitcode == 15: 159 except bb.process.ExecutionError as e:
157 raise DevtoolError('Could not auto-determine recipe name, please specify it on the command line') 160 if e.exitcode == 14:
158 else: 161 # FIXME this is a horrible hack that is unfortunately
159 raise DevtoolError('Command \'%s\' failed:\n%s' % (e.command, e.stdout)) 162 # necessary due to the fact that we can't run bitbake from
163 # inside recipetool since recipetool keeps tinfoil active
164 # with references to it throughout the code, so we have
165 # to exit out and come back here to do it.
166 ensure_npm(config, basepath, args.fixed_setup)
167 continue
168 elif e.exitcode == 15:
169 raise DevtoolError('Could not auto-determine recipe name, please specify it on the command line')
170 else:
171 raise DevtoolError('Command \'%s\' failed:\n%s' % (e.command, e.stdout))
172 break
160 173
161 recipes = glob.glob(os.path.join(tempdir, '*.bb')) 174 recipes = glob.glob(os.path.join(tempdir, '*.bb'))
162 if recipes: 175 if recipes:
@@ -1567,7 +1580,7 @@ def register_commands(subparsers, context):
1567 parser_add.add_argument('--binary', '-b', help='Treat the source tree as something that should be installed verbatim (no compilation, same directory structure). Useful with binary packages e.g. RPMs.', action='store_true') 1580 parser_add.add_argument('--binary', '-b', help='Treat the source tree as something that should be installed verbatim (no compilation, same directory structure). Useful with binary packages e.g. RPMs.', action='store_true')
1568 parser_add.add_argument('--also-native', help='Also add native variant (i.e. support building recipe for the build host as well as the target machine)', action='store_true') 1581 parser_add.add_argument('--also-native', help='Also add native variant (i.e. support building recipe for the build host as well as the target machine)', action='store_true')
1569 parser_add.add_argument('--src-subdir', help='Specify subdirectory within source tree to use', metavar='SUBDIR') 1582 parser_add.add_argument('--src-subdir', help='Specify subdirectory within source tree to use', metavar='SUBDIR')
1570 parser_add.set_defaults(func=add) 1583 parser_add.set_defaults(func=add, fixed_setup=context.fixed_setup)
1571 1584
1572 parser_modify = subparsers.add_parser('modify', help='Modify the source for an existing recipe', 1585 parser_modify = subparsers.add_parser('modify', help='Modify the source for an existing recipe',
1573 description='Sets up the build environment to modify the source for an existing recipe. The default behaviour is to extract the source being fetched by the recipe into a git tree so you can work on it; alternatively if you already have your own pre-prepared source tree you can specify -n/--no-extract.', 1586 description='Sets up the build environment to modify the source for an existing recipe. The default behaviour is to extract the source being fetched by the recipe into a git tree so you can work on it; alternatively if you already have your own pre-prepared source tree you can specify -n/--no-extract.',
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 9b31fe92d7..d427d32062 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -406,10 +406,7 @@ def create_recipe(args):
406 srctree = tempsrc 406 srctree = tempsrc
407 if fetchuri.startswith('npm://'): 407 if fetchuri.startswith('npm://'):
408 # Check if npm is available 408 # Check if npm is available
409 npm = bb.utils.which(tinfoil.config_data.getVar('PATH', True), 'npm') 409 check_npm(tinfoil.config_data)
410 if not npm:
411 logger.error('npm:// URL requested but npm is not available - you need to either build nodejs-native or install npm using your package manager')
412 sys.exit(1)
413 logger.info('Fetching %s...' % srcuri) 410 logger.info('Fetching %s...' % srcuri)
414 try: 411 try:
415 checksums = scriptutils.fetch_uri(tinfoil.config_data, fetchuri, srctree, srcrev) 412 checksums = scriptutils.fetch_uri(tinfoil.config_data, fetchuri, srctree, srcrev)
@@ -1076,6 +1073,11 @@ def convert_rpm_xml(xmlfile):
1076 return values 1073 return values
1077 1074
1078 1075
1076def check_npm(d):
1077 if not os.path.exists(os.path.join(d.getVar('STAGING_BINDIR_NATIVE', True), 'npm')):
1078 logger.error('npm required to process specified source, but npm is not available - you need to build nodejs-native first')
1079 sys.exit(14)
1080
1079def register_commands(subparsers): 1081def register_commands(subparsers):
1080 parser_create = subparsers.add_parser('create', 1082 parser_create = subparsers.add_parser('create',
1081 help='Create a new recipe', 1083 help='Create a new recipe',
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index e794614978..7bb844cb0c 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -21,7 +21,7 @@ import subprocess
21import tempfile 21import tempfile
22import shutil 22import shutil
23import json 23import json
24from recipetool.create import RecipeHandler, split_pkg_licenses, handle_license_vars 24from recipetool.create import RecipeHandler, split_pkg_licenses, handle_license_vars, check_npm
25 25
26logger = logging.getLogger('recipetool') 26logger = logging.getLogger('recipetool')
27 27
@@ -157,6 +157,8 @@ class NpmRecipeHandler(RecipeHandler):
157 157
158 files = RecipeHandler.checkfiles(srctree, ['package.json']) 158 files = RecipeHandler.checkfiles(srctree, ['package.json'])
159 if files: 159 if files:
160 check_npm(tinfoil.config_data)
161
160 data = read_package_json(files[0]) 162 data = read_package_json(files[0])
161 if 'name' in data and 'version' in data: 163 if 'name' in data and 'version' in data:
162 extravalues['PN'] = data['name'] 164 extravalues['PN'] = data['name']