Skip to content

Commit

Permalink
Adds manual dependency support
Browse files Browse the repository at this point in the history
  • Loading branch information
kraigher committed Jan 24, 2016
1 parent 5cb57cd commit 2b2893d
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 3 deletions.
10 changes: 10 additions & 0 deletions vunit/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self,
self._verilog_parser = verilog_parser
self._libraries = {}
self._source_files_in_order = []
self._manual_dependencies = []
self._depend_on_components = depend_on_components
self._depend_on_package_body = depend_on_package_body

Expand Down Expand Up @@ -97,6 +98,12 @@ def add_source_file(self, file_name, library_name, file_type='vhdl', include_dir
self._source_files_in_order.append(source_file)
return source_file

def add_manual_dependency(self, source_file, depends_on):
"""
Add manual dependency where 'source_file' depends_on 'depends_on'
"""
self._manual_dependencies.append((source_file, depends_on))

@staticmethod
def _find_primary_secondary_design_unit_dependencies(source_file):
"""
Expand Down Expand Up @@ -257,6 +264,9 @@ def add_dependencies(dependency_function, files):
if self._depend_on_components:
add_dependencies(self._find_component_design_unit_dependencies, vhdl_files)

for source_file, depends_on in self._manual_dependencies:
add_dependency(depends_on, source_file)

return dependency_graph

def get_files_in_compile_order(self, incremental=True):
Expand Down
23 changes: 23 additions & 0 deletions vunit/test/unit/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,29 @@ def create_project():
module = create_project()
self.assert_should_recompile([module])

def test_manual_dependencies(self):
self.project.add_library("lib", "lib_path")
ent1 = self.add_source_file("lib", "ent1.vhd", """\
entity ent1 is
end ent1;
architecture arch of ent1 is
begin
end architecture;
""")

ent2 = self.add_source_file("lib", "ent2.vhd", """\
entity ent2 is
end ent2;
architecture arch of ent2 is
begin
end architecture;
""")

self.project.add_manual_dependency(ent2, depends_on=ent1)
self.assert_compiles(ent1, before=ent2)

def test_file_type_of(self):
self.assertEqual(file_type_of("file.vhd"), "vhdl")
self.assertEqual(file_type_of("file.vhdl"), "vhdl")
Expand Down
57 changes: 57 additions & 0 deletions vunit/test/unit/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,63 @@ def test_get_source_files_errors(self):
self.assertRaisesRegexp(ValueError, ".*Found no file named.*%s.* in library 'lib1'" % non_existant_name,
ui.get_source_file, non_existant_name, "lib1")

@mock.patch("vunit.project.Project.add_manual_dependency", autospec=True)
def test_add_single_file_manual_dependencies(self, add_manual_dependency):
# pylint: disable=protected-access
ui = self._create_ui()
lib = ui.library("lib")
file_name1 = self.create_entity_file(1)
file_name2 = self.create_entity_file(2)
file1 = lib.add_source_file(file_name1)
file2 = lib.add_source_file(file_name2)

add_manual_dependency.assert_has_calls([])
file1.depends_on(file2)
add_manual_dependency.assert_has_calls([
mock.call(ui._project,
file1._source_file,
depends_on=file2._source_file)])

@mock.patch("vunit.project.Project.add_manual_dependency", autospec=True)
def test_add_multiple_file_manual_dependencies(self, add_manual_dependency):
# pylint: disable=protected-access
ui = self._create_ui()
lib = ui.library("lib")
self.create_file("foo1.vhd")
self.create_file("foo2.vhd")
self.create_file("foo3.vhd")
self.create_file("bar.vhd")
foo_files = lib.add_source_files("foo*.vhd")
bar_file = lib.add_source_file("bar.vhd")

add_manual_dependency.assert_has_calls([])
bar_file.depends_on(foo_files)
add_manual_dependency.assert_has_calls([
mock.call(ui._project,
bar_file._source_file,
depends_on=foo_file._source_file)
for foo_file in foo_files])

@mock.patch("vunit.project.Project.add_manual_dependency", autospec=True)
def test_add_fileset_manual_dependencies(self, add_manual_dependency):
# pylint: disable=protected-access
ui = self._create_ui()
lib = ui.library("lib")
self.create_file("foo1.vhd")
self.create_file("foo2.vhd")
self.create_file("foo3.vhd")
self.create_file("bar.vhd")
foo_files = lib.add_source_files("foo*.vhd")
bar_file = lib.add_source_file("bar.vhd")

add_manual_dependency.assert_has_calls([])
foo_files.depends_on(bar_file)
add_manual_dependency.assert_has_calls([
mock.call(ui._project,
foo_file._source_file,
depends_on=bar_file._source_file)
for foo_file in foo_files])

def _test_pre_config_helper(self, retval, test_not_entity=False):
"""
Helper method to test pre_config where the pre config can return different values
Expand Down
29 changes: 26 additions & 3 deletions vunit/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def get_source_files(self, pattern="*", library_name=None, allow_empty=False):
fnmatch(relpath(source_file.name), pattern)):
continue

results.append(FileFacade(source_file))
results.append(FileFacade(source_file, self._project))

if (not allow_empty) and len(results) == 0:
raise ValueError(("Pattern %r did not match any file. "
Expand Down Expand Up @@ -317,7 +317,8 @@ def add_source_file(self, file_name, library_name, preprocessors=None, include_d
return FileFacade(self._project.add_source_file(file_name,
library_name,
file_type=file_type,
include_dirs=include_dirs))
include_dirs=include_dirs),
self._project)

def _preprocess(self, library_name, file_name, preprocessors):
"""
Expand Down Expand Up @@ -816,20 +817,42 @@ def set_compile_option(self, name, value):
for source_file in self:
source_file.set_compile_option(name, value)

def depends_on(self, source_file):
"""
Add manual dependency of these files on another
"""
for my_source_file in self:
my_source_file.depends_on(source_file)


class FileFacade(object):
"""
A single file
"""
def __init__(self, source_file):
def __init__(self, source_file, project):
self._source_file = source_file
self._project = project

def set_compile_option(self, name, value):
"""
Set compile option
"""
self._source_file.set_compile_option(name, value)

def depends_on(self, source_file):
"""
Add manual dependency of this file on another
"""
if isinstance(source_file, FileFacade):
private_source_file = source_file._source_file # pylint: disable=protected-access
self._project.add_manual_dependency(self._source_file,
depends_on=private_source_file)
elif hasattr(source_file, "__iter__"):
for element in source_file:
self.depends_on(element)
else:
raise ValueError(source_file)


def select_vhdl_standard():
"""
Expand Down

0 comments on commit 2b2893d

Please sign in to comment.