diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2017-07-20 16:48:13 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-21 08:44:25 +0100 |
commit | 0d72748e81186d38511cd691521cbd9fa7336879 (patch) | |
tree | f598056e76017584a69bb0882af47383a75e55b4 | |
parent | b5e42005e96d0c3ed5da72007f6c41722332afe6 (diff) | |
download | poky-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__.py | 31 | ||||
-rw-r--r-- | scripts/lib/devtool/standard.py | 34 | ||||
-rw-r--r-- | scripts/lib/recipetool/create.py | 21 | ||||
-rw-r--r-- | scripts/lib/recipetool/create_npm.py | 27 |
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 | ||
264 | def 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 | |||
30 | import glob | 30 | import glob |
31 | import filecmp | 31 | import filecmp |
32 | from collections import OrderedDict | 32 | from collections import OrderedDict |
33 | from 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 | 33 | from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, use_external_build, setup_git_repo, recipe_to_append, get_bbclassextend_targets, DevtoolError |
34 | from devtool import parse_recipe | 34 | from devtool import parse_recipe |
35 | 35 | ||
36 | logger = logging.getLogger('devtool') | 36 | logger = 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 | ||
1155 | def 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 | |||
1171 | def register_commands(subparsers): | 1155 | def 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 | |||
21 | import tempfile | 21 | import tempfile |
22 | import shutil | 22 | import shutil |
23 | import json | 23 | import json |
24 | from recipetool.create import RecipeHandler, split_pkg_licenses, handle_license_vars, check_npm | 24 | from recipetool.create import RecipeHandler, split_pkg_licenses, handle_license_vars |
25 | 25 | ||
26 | logger = logging.getLogger('recipetool') | 26 | logger = logging.getLogger('recipetool') |
27 | 27 | ||
@@ -36,6 +36,27 @@ def tinfoil_init(instance): | |||
36 | class NpmRecipeHandler(RecipeHandler): | 36 | class 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]) |