summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2017-07-20 16:48:13 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-07-21 08:44:25 +0100
commit0d72748e81186d38511cd691521cbd9fa7336879 (patch)
treef598056e76017584a69bb0882af47383a75e55b4
parentb5e42005e96d0c3ed5da72007f6c41722332afe6 (diff)
downloadpoky-0d72748e81186d38511cd691521cbd9fa7336879.tar.gz
recipetool: create: refactor code for ensuring npm is available
Across devtool and recipetool we had an ugly set of code for ensuring that we can call an npm binary, and much of that ugliness was a result of not being able to run build tasks when tinfoil was active - if recipetool found that npm was required and we didn't know beforehand (e.g. we're fetching from a plain git repository as opposed to an npm:// URL where it's obvious) then it had to exit and return a special result code, so that devtool knew it needed to build nodejs-native and then call recipetool again. Now that we are using real build tasks to fetch and unpack, we can drop most of this and move the code to the one place where it's still needed (i.e. create_npm where we potentially have to deal with node.js code in a plain source repository). (From OE-Core rev: 8450de16ddb02d863204b411a94c6d84e0f88817) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--scripts/lib/devtool/__init__.py31
-rw-r--r--scripts/lib/devtool/standard.py34
-rw-r--r--scripts/lib/recipetool/create.py21
-rw-r--r--scripts/lib/recipetool/create_npm.py27
4 files changed, 34 insertions, 79 deletions
diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py
index 29c4c05071..bba0721543 100644
--- a/scripts/lib/devtool/__init__.py
+++ b/scripts/lib/devtool/__init__.py
@@ -261,34 +261,3 @@ def get_bbclassextend_targets(recipefile, pn):
261 targets.append('%s-%s' % (pn, variant)) 261 targets.append('%s-%s' % (pn, variant))
262 return targets 262 return targets
263 263
264def ensure_npm(config, basepath, fixed_setup=False, check_exists=True):
265 """
266 Ensure that npm is available and either build it or show a
267 reasonable error message
268 """
269 if check_exists:
270 tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
271 try:
272 rd = tinfoil.parse_recipe('nodejs-native')
273 nativepath = rd.getVar('STAGING_BINDIR_NATIVE')
274 finally:
275 tinfoil.shutdown()
276 npmpath = os.path.join(nativepath, 'npm')
277 build_npm = not os.path.exists(npmpath)
278 else:
279 build_npm = True
280
281 if build_npm:
282 logger.info('Building nodejs-native')
283 try:
284 exec_build_env_command(config.init_path, basepath,
285 'bitbake -q nodejs-native -c addto_recipe_sysroot', watch=True)
286 except bb.process.ExecutionError as e:
287 if "Nothing PROVIDES 'nodejs-native'" in e.stdout:
288 if fixed_setup:
289 msg = 'nodejs-native is required for npm but is not available within this SDK'
290 else:
291 msg = 'nodejs-native is required for npm but is not available - you will likely need to add a layer that provides nodejs'
292 raise DevtoolError(msg)
293 else:
294 raise
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 0104e675db..54558ce799 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, ensure_npm, 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, DevtoolError
34from devtool import parse_recipe 34from devtool import parse_recipe
35 35
36logger = logging.getLogger('devtool') 36logger = logging.getLogger('devtool')
@@ -128,9 +128,6 @@ 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
134 source = args.fetchuri 131 source = args.fetchuri
135 if srctree: 132 if srctree:
136 extracmdopts += ' -x %s' % srctree 133 extracmdopts += ' -x %s' % srctree
@@ -155,28 +152,13 @@ def add(args, config, basepath, workspace):
155 152
156 tempdir = tempfile.mkdtemp(prefix='devtool') 153 tempdir = tempfile.mkdtemp(prefix='devtool')
157 try: 154 try:
158 builtnpm = False 155 try:
159 while True: 156 stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create --devtool -o %s \'%s\' %s' % (color, tempdir, source, extracmdopts), watch=True)
160 try: 157 except bb.process.ExecutionError as e:
161 stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create --devtool -o %s \'%s\' %s' % (color, tempdir, source, extracmdopts), watch=True) 158 if e.exitcode == 15:
162 except bb.process.ExecutionError as e: 159 raise DevtoolError('Could not auto-determine recipe name, please specify it on the command line')
163 if e.exitcode == 14: 160 else:
164 if builtnpm: 161 raise DevtoolError('Command \'%s\' failed' % e.command)
165 raise DevtoolError('Re-running recipetool still failed to find npm')
166 # FIXME this is a horrible hack that is unfortunately
167 # necessary due to the fact that we can't run bitbake from
168 # inside recipetool since recipetool keeps tinfoil active
169 # with references to it throughout the code, so we have
170 # to exit out and come back here to do it.
171 ensure_npm(config, basepath, args.fixed_setup, check_exists=False)
172 logger.info('Re-running recipe creation process after building nodejs')
173 builtnpm = True
174 continue
175 elif e.exitcode == 15:
176 raise DevtoolError('Could not auto-determine recipe name, please specify it on the command line')
177 else:
178 raise DevtoolError('Command \'%s\' failed' % e.command)
179 break
180 162
181 recipes = glob.glob(os.path.join(tempdir, '*.bb')) 163 recipes = glob.glob(os.path.join(tempdir, '*.bb'))
182 if recipes: 164 if recipes:
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 2a6a28ba91..359eb9adfc 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -1152,22 +1152,6 @@ def convert_rpm_xml(xmlfile):
1152 return values 1152 return values
1153 1153
1154 1154
1155def check_npm(tinfoil, debugonly=False):
1156 try:
1157 rd = tinfoil.parse_recipe('nodejs-native')
1158 except bb.providers.NoProvider:
1159 # We still conditionally show the message and exit with the special
1160 # return code, otherwise we can't show the proper message for eSDK
1161 # users
1162 log_error_cond('nodejs-native is required for npm but is not available - you will likely need to add a layer that provides nodejs', debugonly)
1163 sys.exit(14)
1164 bindir = rd.getVar('STAGING_BINDIR_NATIVE')
1165 npmpath = os.path.join(bindir, 'npm')
1166 if not os.path.exists(npmpath):
1167 log_error_cond('npm required to process specified source, but npm is not available - you need to run bitbake -c addto_recipe_sysroot nodejs-native first', debugonly)
1168 sys.exit(14)
1169 return bindir
1170
1171def register_commands(subparsers): 1155def register_commands(subparsers):
1172 parser_create = subparsers.add_parser('create', 1156 parser_create = subparsers.add_parser('create',
1173 help='Create a new recipe', 1157 help='Create a new recipe',
@@ -1185,8 +1169,5 @@ def register_commands(subparsers):
1185 parser_create.add_argument('--keep-temp', action="store_true", help='Keep temporary directory (for debugging)') 1169 parser_create.add_argument('--keep-temp', action="store_true", help='Keep temporary directory (for debugging)')
1186 parser_create.add_argument('--fetch-dev', action="store_true", help='For npm, also fetch devDependencies') 1170 parser_create.add_argument('--fetch-dev', action="store_true", help='For npm, also fetch devDependencies')
1187 parser_create.add_argument('--devtool', action="store_true", help=argparse.SUPPRESS) 1171 parser_create.add_argument('--devtool', action="store_true", help=argparse.SUPPRESS)
1188 # FIXME I really hate having to set parserecipes for this, but given we may need 1172 parser_create.set_defaults(func=create_recipe)
1189 # to call into npm (and we don't know in advance if we will or not) and in order
1190 # to do so we need to know npm's recipe sysroot path, there's not much alternative
1191 parser_create.set_defaults(func=create_recipe, parserecipes=True)
1192 1173
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index ba7e39a406..885d5438e3 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, check_npm 24from recipetool.create import RecipeHandler, split_pkg_licenses, handle_license_vars
25 25
26logger = logging.getLogger('recipetool') 26logger = logging.getLogger('recipetool')
27 27
@@ -36,6 +36,27 @@ def tinfoil_init(instance):
36class NpmRecipeHandler(RecipeHandler): 36class NpmRecipeHandler(RecipeHandler):
37 lockdownpath = None 37 lockdownpath = None
38 38
39 def _ensure_npm(self, fixed_setup=False):
40 if not tinfoil.recipes_parsed:
41 tinfoil.parse_recipes()
42 try:
43 rd = tinfoil.parse_recipe('nodejs-native')
44 except bb.providers.NoProvider:
45 if fixed_setup:
46 msg = 'nodejs-native is required for npm but is not available within this SDK'
47 else:
48 msg = 'nodejs-native is required for npm but is not available - you will likely need to add a layer that provides nodejs'
49 logger.error(msg)
50 return None
51 bindir = rd.getVar('STAGING_BINDIR_NATIVE')
52 npmpath = os.path.join(bindir, 'npm')
53 if not os.path.exists(npmpath):
54 tinfoil.build_targets('nodejs-native', 'addto_recipe_sysroot')
55 if not os.path.exists(npmpath):
56 logger.error('npm required to process specified source, but nodejs-native did not seem to populate it')
57 return None
58 return bindir
59
39 def _handle_license(self, data): 60 def _handle_license(self, data):
40 ''' 61 '''
41 Handle the license value from an npm package.json file 62 Handle the license value from an npm package.json file
@@ -189,7 +210,9 @@ class NpmRecipeHandler(RecipeHandler):
189 files = RecipeHandler.checkfiles(srctree, ['package.json']) 210 files = RecipeHandler.checkfiles(srctree, ['package.json'])
190 if files: 211 if files:
191 d = bb.data.createCopy(tinfoil.config_data) 212 d = bb.data.createCopy(tinfoil.config_data)
192 npm_bindir = check_npm(tinfoil, self._devtool) 213 npm_bindir = self._ensure_npm()
214 if not npm_bindir:
215 sys.exit(14)
193 d.prependVar('PATH', '%s:' % npm_bindir) 216 d.prependVar('PATH', '%s:' % npm_bindir)
194 217
195 data = read_package_json(files[0]) 218 data = read_package_json(files[0])