diff options
-rw-r--r-- | docs/markdown/Rewriter.md | 13 | ||||
-rw-r--r-- | docs/markdown/snippets/rewriter_extra_files.md | 26 | ||||
-rw-r--r-- | mesonbuild/rewriter.py | 99 | ||||
-rw-r--r-- | test cases/rewrite/6 extra_files/addExtraFiles.json | 111 | ||||
-rw-r--r-- | test cases/rewrite/6 extra_files/info.json | 57 | ||||
-rw-r--r-- | test cases/rewrite/6 extra_files/meson.build | 21 | ||||
-rw-r--r-- | test cases/rewrite/6 extra_files/rmExtraFiles.json | 93 | ||||
-rw-r--r-- | unittests/rewritetests.py | 155 |
8 files changed, 518 insertions, 57 deletions
diff --git a/docs/markdown/Rewriter.md b/docs/markdown/Rewriter.md index 018434f..535093b 100644 --- a/docs/markdown/Rewriter.md +++ b/docs/markdown/Rewriter.md @@ -77,6 +77,17 @@ and print an error message. For more information see the help output of the rewriter target command. +### Adding and removing `extra_files` + +*Since 0.61.0* + +In the same way you can add and remove source files from a target, you can modify a target's +`extra_files` list: + +```bash +meson rewrite target <target name/id> {add_extra_files/rm_extra_files} [list of extra files] +``` + ### Setting the project version It is also possible to set kwargs of specific functions with the @@ -191,7 +202,7 @@ The format for the type `target` is defined as follows: { "type": "target", "target": "target ID/name/assignment variable", - "operation": "one of ['src_add', 'src_rm', 'target_rm', 'target_add', 'info']", + "operation": "one of ['src_add', 'src_rm', 'target_rm', 'target_add', 'extra_files_add', 'extra_files_rm', 'info']", "sources": ["list", "of", "source", "files", "to", "add, remove"], "subdir": "subdir where the new target should be added (only has an effect for operation 'tgt_add')", "target_type": "function name of the new target -- same as in the CLI (only has an effect for operation 'tgt_add')" diff --git a/docs/markdown/snippets/rewriter_extra_files.md b/docs/markdown/snippets/rewriter_extra_files.md new file mode 100644 index 0000000..c46f076 --- /dev/null +++ b/docs/markdown/snippets/rewriter_extra_files.md @@ -0,0 +1,26 @@ +## `meson rewrite` can modify `extra_files` + +The build script rewriter can now modify targets' `extra_files` lists, +or create them if absent. It it used in the same way as with rewriting +source lists: + +```bash +meson rewrite target <target name/id> {add_extra_files/rm_extra_files} [list of extra files] +``` + +The rewriter's script mode also supports these actions: + +```json +{ + "type": "target", + "target": "<target name>", + "operation": "extra_files_add / extra_files_rm", + "sources": ["list", "of", "extra", "files", "to", "add, remove"], +} +``` + +## `meson rewrite target <target> info` outputs *target*'s `extra_files` + +Targets' `extra_files` lists are now included in the rewriter's target info dump +as a list of file paths, in the same way `sources` are. This applies to both +`meson rewrite` CLI and script mode. diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 67cd871..d816cce 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -46,7 +46,7 @@ def add_arguments(parser, formatter=None): tgt_parser.add_argument('--type', dest='tgt_type', choices=rewriter_keys['target']['target_type'][2], default='executable', help='Type of the target to add (only for the "add_target" action)') tgt_parser.add_argument('target', help='Name or ID of the target') - tgt_parser.add_argument('operation', choices=['add', 'rm', 'add_target', 'rm_target', 'info'], + tgt_parser.add_argument('operation', choices=['add', 'rm', 'add_target', 'rm_target', 'add_extra_files', 'rm_extra_files', 'info'], help='Action to execute') tgt_parser.add_argument('sources', nargs='*', help='Sources to add/remove') @@ -308,7 +308,7 @@ rewriter_keys = { }, 'target': { 'target': (str, None, None), - 'operation': (str, None, ['src_add', 'src_rm', 'target_rm', 'target_add', 'info']), + 'operation': (str, None, ['src_add', 'src_rm', 'target_rm', 'target_add', 'extra_files_add', 'extra_files_rm', 'info']), 'sources': (list, [], None), 'subdir': (str, '', None), 'target_type': (str, 'executable', ['both_libraries', 'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library']), @@ -709,6 +709,91 @@ class Rewriter: if root not in self.modified_nodes: self.modified_nodes += [root] + elif cmd['operation'] == 'extra_files_add': + tgt_function: FunctionNode = target['node'] + mark_array = True + try: + node = target['extra_files'][0] + except IndexError: + # Specifying `extra_files` with a list that flattens to empty gives an empty + # target['extra_files'] list, account for that. + try: + extra_files_key = next(k for k in tgt_function.args.kwargs.keys() if isinstance(k, IdNode) and k.value == 'extra_files') + node = tgt_function.args.kwargs[extra_files_key] + except StopIteration: + # Target has no extra_files kwarg, create one + node = ArrayNode(ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno) + tgt_function.args.kwargs[IdNode(Token('string', tgt_function.filename, 0, 0, 0, None, 'extra_files'))] = node + mark_array = False + if tgt_function not in self.modified_nodes: + self.modified_nodes += [tgt_function] + target['extra_files'] = [node] + if isinstance(node, IdNode): + node = self.interpreter.assignments[node.value] + target['extra_files'] = [node] + if not isinstance(node, ArrayNode): + mlog.error('Target', mlog.bold(cmd['target']), 'extra_files argument must be a list', *self.on_error()) + return self.handle_error() + + # Generate the current extra files list + extra_files_list = [] + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + extra_files_list += [j.value] + + # Generate the new String nodes + to_append = [] + for i in sorted(set(cmd['sources'])): + if i in extra_files_list: + mlog.log(' -- Extra file', mlog.green(i), 'is already defined for the target --> skipping') + continue + mlog.log(' -- Adding extra file', mlog.green(i), 'at', + mlog.yellow(f'{node.filename}:{node.lineno}')) + token = Token('string', node.filename, 0, 0, 0, None, i) + to_append += [StringNode(token)] + + # Append to the AST at the right place + arg_node = node.args + arg_node.arguments += to_append + + # Mark the node as modified + if arg_node not in to_sort_nodes: + to_sort_nodes += [arg_node] + # If the extra_files array is newly created, don't mark it as its parent function node already is, + # otherwise this would cause double modification. + if mark_array and node not in self.modified_nodes: + self.modified_nodes += [node] + + elif cmd['operation'] == 'extra_files_rm': + # Helper to find the exact string node and its parent + def find_node(src): + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + if j.value == src: + return i, j + return None, None + + for i in cmd['sources']: + # Try to find the node with the source string + root, string_node = find_node(i) + if root is None: + mlog.warning(' -- Unable to find extra file', mlog.green(i), 'in the target') + continue + + # Remove the found string node from the argument list + arg_node = root.args + mlog.log(' -- Removing extra file', mlog.green(i), 'from', + mlog.yellow(f'{string_node.filename}:{string_node.lineno}')) + arg_node.arguments.remove(string_node) + + # Mark the node as modified + if arg_node not in to_sort_nodes and not isinstance(root, FunctionNode): + to_sort_nodes += [arg_node] + if root not in self.modified_nodes: + self.modified_nodes += [root] + elif cmd['operation'] == 'target_add': if target is not None: mlog.error('Can not add target', mlog.bold(cmd['target']), 'because it already exists', *self.on_error()) @@ -756,9 +841,15 @@ class Rewriter: for j in arg_list_from_node(i): if isinstance(j, StringNode): src_list += [j.value] + extra_files_list = [] + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + extra_files_list += [j.value] test_data = { 'name': target['name'], - 'sources': src_list + 'sources': src_list, + 'extra_files': extra_files_list } self.add_info('target', target['id'], test_data) @@ -879,6 +970,8 @@ target_operation_map = { 'rm': 'src_rm', 'add_target': 'target_add', 'rm_target': 'target_rm', + 'add_extra_files': 'extra_files_add', + 'rm_extra_files': 'extra_files_rm', 'info': 'info', } diff --git a/test cases/rewrite/6 extra_files/addExtraFiles.json b/test cases/rewrite/6 extra_files/addExtraFiles.json new file mode 100644 index 0000000..421ed92 --- /dev/null +++ b/test cases/rewrite/6 extra_files/addExtraFiles.json @@ -0,0 +1,111 @@ +[ + { + "type": "target", + "target": "trivialprog1", + "operation": "extra_files_add", + "sources": ["a2.hpp", "a1.hpp", "a2.hpp"] + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "extra_files_add", + "sources": ["a7.hpp"] + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "extra_files_add", + "sources": ["a5.hpp"] + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "extra_files_add", + "sources": ["a5.hpp"] + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "extra_files_add", + "sources": ["a3.hpp"] + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "extra_files_add", + "sources": ["a6.hpp", "a1.hpp"] + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "extra_files_add", + "sources": ["a2.hpp", "a7.hpp"] + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "extra_files_add", + "sources": ["a9.hpp", "a8.hpp"] + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "extra_files_add", + "sources": ["a4.hpp", "a1.hpp"] + }, + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff --git a/test cases/rewrite/6 extra_files/info.json b/test cases/rewrite/6 extra_files/info.json new file mode 100644 index 0000000..0f1a3bd --- /dev/null +++ b/test cases/rewrite/6 extra_files/info.json @@ -0,0 +1,57 @@ +[ + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "exe2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "exe4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "exe6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "exe8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff --git a/test cases/rewrite/6 extra_files/meson.build b/test cases/rewrite/6 extra_files/meson.build new file mode 100644 index 0000000..f9aab46 --- /dev/null +++ b/test cases/rewrite/6 extra_files/meson.build @@ -0,0 +1,21 @@ +project('rewritetest', 'cpp') + +ef1 = ['main.hpp', 'fileA.hpp'] +ef2 = files(['fileB.hpp', 'fileC.hpp']) +ef3 = ef1 +ef4 = [ef3] +ef5 = [] + +# Magic comment + +exe0 = executable('trivialprog0', 'main.cpp', extra_files : ef1 + ef2) +exe1 = executable('trivialprog1', 'main.cpp', extra_files : ef1) +exe2 = executable('trivialprog2', 'main.cpp', extra_files : [ef2]) +exe3 = executable('trivialprog3', 'main.cpp', extra_files : ['main.hpp', 'fileA.hpp']) +exe4 = executable('trivialprog4', 'main.cpp', extra_files : ['main.hpp', ['fileA.hpp']]) +exe5 = executable('trivialprog5', 'main.cpp', extra_files : [ef2, 'main.hpp']) +exe6 = executable('trivialprog6', 'main.cpp', extra_files : ef3) +executable('trivialprog7', 'main.cpp', extra_files : ef4) +exe8 = executable('trivialprog8', 'main.cpp', extra_files : []) +exe9 = executable('trivialprog9', 'main.cpp') +exe10 = executable('trivialprog10', 'main.cpp', extra_files : ef5) diff --git a/test cases/rewrite/6 extra_files/rmExtraFiles.json b/test cases/rewrite/6 extra_files/rmExtraFiles.json new file mode 100644 index 0000000..bd2855b --- /dev/null +++ b/test cases/rewrite/6 extra_files/rmExtraFiles.json @@ -0,0 +1,93 @@ +[ + { + "type": "target", + "target": "trivialprog1", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "extra_files_rm", + "sources": ["fileB.hpp"] + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff --git a/unittests/rewritetests.py b/unittests/rewritetests.py index f03de0a..1e6a398 100644 --- a/unittests/rewritetests.py +++ b/unittests/rewritetests.py @@ -56,16 +56,16 @@ class RewriterTests(BasePlatformTests): out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) expected = { 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp']}, + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, } } self.assertDictEqual(out, expected) @@ -75,16 +75,16 @@ class RewriterTests(BasePlatformTests): out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) expected = { 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['a5.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['a5.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['a3.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp', 'a4.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['a5.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['a5.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['a3.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp', 'a4.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, } } self.assertDictEqual(out, expected) @@ -100,7 +100,7 @@ class RewriterTests(BasePlatformTests): inf = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "info"}]) self.rewrite(self.builddir, add) out = self.rewrite(self.builddir, inf) - expected = {'target': {'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}}} + expected = {'target': {'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}}} self.assertDictEqual(out, expected) def test_target_remove_sources(self): @@ -108,16 +108,16 @@ class RewriterTests(BasePlatformTests): out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmSrc.json')) expected = { 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileC.cpp', 'main.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp']}, + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileC.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, } } self.assertDictEqual(out, expected) @@ -129,7 +129,7 @@ class RewriterTests(BasePlatformTests): def test_target_subdir(self): self.prime('2 subdirs') out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) - expected = {'name': 'something', 'sources': ['first.c', 'second.c', 'third.c']} + expected = {'name': 'something', 'sources': ['first.c', 'second.c', 'third.c'], 'extra_files': []} self.assertDictEqual(list(out['target'].values())[0], expected) # Check the written file @@ -143,13 +143,13 @@ class RewriterTests(BasePlatformTests): expected = { 'target': { - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, } } self.assertDictEqual(out, expected) @@ -161,17 +161,17 @@ class RewriterTests(BasePlatformTests): expected = { 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog10@sha': {'name': 'trivialprog10', 'sources': ['new1.cpp', 'new2.cpp']}, + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog10@sha': {'name': 'trivialprog10', 'sources': ['new1.cpp', 'new2.cpp'], 'extra_files': []}, } } self.assertDictEqual(out, expected) @@ -186,7 +186,7 @@ class RewriterTests(BasePlatformTests): self.prime('2 subdirs') self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = {'name': 'something', 'sources': ['first.c', 'second.c']} + expected = {'name': 'something', 'sources': ['first.c', 'second.c'], 'extra_files': []} self.assertDictEqual(out['target']['94b671c@@something@exe'], expected) def test_target_source_sorting(self): @@ -228,7 +228,8 @@ class RewriterTests(BasePlatformTests): 'a666.c', 'b1.c', 'c2.c' - ] + ], + 'extra_files': [] } } } @@ -238,7 +239,7 @@ class RewriterTests(BasePlatformTests): self.prime('4 same name targets') out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = {'name': 'myExe', 'sources': ['main.cpp']} + expected = {'name': 'myExe', 'sources': ['main.cpp'], 'extra_files': []} self.assertEqual(len(out['target']), 2) for val in out['target'].values(): self.assertDictEqual(expected, val) @@ -345,3 +346,51 @@ class RewriterTests(BasePlatformTests): } } self.assertDictEqual(out, expected) + + def test_target_add_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'main.hpp', 'fileA.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['a3.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': ['a2.hpp', 'a7.hpp']}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': ['a8.hpp', 'a9.hpp']}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a4.hpp']}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_remove_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) |