| #!/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!" |