|  | #!/usr/bin/env python3 | 
|  | """ | 
|  | This file needs to be kept in sync with ../../make/deps.mk | 
|  | """ | 
|  |  | 
|  | import os | 
|  | import os.path | 
|  |  | 
|  | MY_DIR = os.path.dirname(os.path.abspath(__file__)) | 
|  | TOP_DIR = os.path.abspath(os.path.join(MY_DIR, "..", "..")) | 
|  |  | 
|  | DEPS_DIR = ".deps" | 
|  | DEPS_EXT = ".d" | 
|  | DEPMK_EXT = ".dmk" | 
|  |  | 
|  |  | 
|  | def makefile_dir(filepath): | 
|  | """Get the directory part of a path in the same way make does. | 
|  |  | 
|  | Python version of the makefile `$(dir xxx)` function. | 
|  |  | 
|  | >>> makefile_dir("blah1") | 
|  | '' | 
|  | >>> makefile_dir("a/blah2") | 
|  | 'a/' | 
|  | >>> makefile_dir("../b/blah3") | 
|  | '../b/' | 
|  | >>> makefile_dir("./blah4") | 
|  | '' | 
|  | >>> makefile_dir("/abc/blah6") | 
|  | '/abc/' | 
|  | >>> makefile_dir("/blah5") | 
|  | '/' | 
|  | """ | 
|  | dirname = os.path.dirname(os.path.normpath(filepath)) | 
|  | if not dirname or dirname == '.': | 
|  | return '' | 
|  | if dirname[-1] != '/': | 
|  | dirname += '/' | 
|  | return dirname | 
|  |  | 
|  |  | 
|  | def makefile_notdir(filepath): | 
|  | """Get the non-directory part of a path in the same way make does. | 
|  |  | 
|  | Python version of the makefile `$(nodir xxxx)` function. | 
|  |  | 
|  | >>> makefile_notdir("blah1") | 
|  | 'blah1' | 
|  | >>> makefile_notdir("a/blah2") | 
|  | 'blah2' | 
|  | >>> makefile_notdir("../b/blah3") | 
|  | 'blah3' | 
|  | >>> makefile_notdir("blah4/") | 
|  | '' | 
|  | >>> makefile_notdir("/blah5") | 
|  | 'blah5' | 
|  | >>> makefile_notdir("/abc/blah6") | 
|  | 'blah6' | 
|  | """ | 
|  | return os.path.basename(filepath) | 
|  |  | 
|  |  | 
|  | def deps_dir(filepath, *, top_dir=TOP_DIR): | 
|  | """Get the directory to put dependencies files into. | 
|  |  | 
|  | >>> td = os.path.abspath(os.curdir) | 
|  | >>> deps_dir("./a/blah", top_dir=td) | 
|  | '.deps/a/blah' | 
|  | >>> deps_dir("blah", top_dir=td) | 
|  | '.deps/blah' | 
|  | >>> deps_dir("blah.abc", top_dir=td) | 
|  | '.deps/blah.abc' | 
|  | >>> deps_dir("/abc3/blah", top_dir='/abc3') | 
|  | '.deps/blah' | 
|  | >>> deps_dir("/abc3/blah", top_dir='/abc4') | 
|  | Traceback (most recent call last): | 
|  | ... | 
|  | OSError: /abc3/blah is not inside top /abc4 | 
|  | """ | 
|  | filepath = os.path.normpath(filepath) | 
|  | if filepath[0] != '/': | 
|  | filepath = os.path.abspath(filepath) | 
|  | filepath_notop = filepath.replace(top_dir + '/', '') | 
|  | if filepath_notop == filepath: | 
|  | raise IOError("{} is not inside top {}".format(filepath, top_dir)) | 
|  | return "{deps_dir}/{dir}{notdir}".format( | 
|  | deps_dir=DEPS_DIR, | 
|  | dir=makefile_dir(filepath_notop), | 
|  | notdir=makefile_notdir(filepath_notop), | 
|  | ) | 
|  |  | 
|  |  | 
|  | def deps_makefile(filepath, *, top_dir=TOP_DIR): | 
|  | """Get deps makefile name. | 
|  |  | 
|  | Python version of `$(call deps_makefile,{})` in make/deps.mk | 
|  |  | 
|  | >>> td = os.path.abspath(os.curdir) | 
|  | >>> deps_makefile("./a/blah", top_dir=td) | 
|  | '.deps/a/blah.dmk' | 
|  | >>> deps_makefile("blah", top_dir=td) | 
|  | '.deps/blah.dmk' | 
|  | """ | 
|  | return deps_dir( | 
|  | "{dir}{notdir}{ext}".format( | 
|  | dir=makefile_dir(filepath), | 
|  | notdir=makefile_notdir(filepath), | 
|  | ext=DEPMK_EXT, | 
|  | ), | 
|  | top_dir=top_dir | 
|  | ) | 
|  |  | 
|  |  | 
|  | def add_dependency(f, from_file, on_file, fmt=None): | 
|  | """Record a dependency from file on file.""" | 
|  | if fmt is None: | 
|  | fmt = "$(call add_dependency,{from_file},{on_file})\n" | 
|  | f.write(fmt.format( | 
|  | from_file=from_file, | 
|  | on_file=on_file, | 
|  | )) | 
|  |  | 
|  |  | 
|  | def write_deps(inputfile_name, data): | 
|  | deps_filename = deps_makefile(inputfile_name) | 
|  | with open(deps_filename, "w") as f: | 
|  | f.write(data.getvalue()) | 
|  | print("Generated dependency info", deps_filename) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | import doctest | 
|  | failure_count, test_count = doctest.testmod() | 
|  | assert test_count > 0 | 
|  | assert failure_count == 0, "Doctests failed!" |