Last active
March 16, 2018 02:12
-
-
Save obskyr/e4124d29444dbbf70337fe6e5a30e893 to your computer and use it in GitHub Desktop.
Near-instant RGBDS assembly dependency generation / include scanning, for use with makefiles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Get all the dependencies of RGBDS assembly files recursively, | |
# and output them using Make dependency syntax. | |
def dependencies_in(asm_file_paths) | |
asm_file_paths = asm_file_paths.clone | |
dependencies = {} of String => Set(String) | |
asm_file_paths.each do |asm_file_path| | |
if !dependencies.has_key? asm_file_path | |
asm_dependencies, bin_dependencies = shallow_dependencies_of asm_file_path | |
dependencies[asm_file_path] = asm_dependencies | bin_dependencies | |
asm_file_paths.concat asm_dependencies.to_a | |
end | |
end | |
return dependencies | |
end | |
def shallow_dependencies_of(asm_file_path) | |
asm_dependencies = Set(String).new | |
bin_dependencies = Set(String).new | |
File.each_line asm_file_path do |line| | |
keyword_match = line.match /^\s*(INC(?:LUDE|BIN))/i | |
next if !keyword_match | |
keyword = keyword_match[1].upcase | |
line = line.split(';', 1)[0] | |
path = line[line.index('"').not_nil! + 1...line.rindex('"').not_nil!] | |
if keyword == "INCLUDE" | |
asm_dependencies << path | |
else | |
bin_dependencies << path | |
end | |
end | |
return asm_dependencies, bin_dependencies | |
end | |
if ARGV.size == 0 | |
puts "Usage: #{PROGRAM_NAME.split('/')[-1]} <paths to assembly files...>" | |
exit 1 | |
end | |
dependencies_in(ARGV).each do |file, dependencies| | |
# It seems that if A depends on B which depends on C, and | |
# C is modified, Make needs you to change the modification | |
# time of B too. That's the reason for the "@touch $@". | |
puts "#{file}: #{dependencies.join(' ')}\n\t@touch $@" if !dependencies.empty? | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
"""Get all the dependencies of RGBDS assembly files recursively, | |
and output them using Make dependency syntax. | |
""" | |
from __future__ import print_function | |
from __future__ import unicode_literals | |
import os | |
import re | |
import sys | |
if sys.version_info[0] < 3: | |
from codecs import open | |
INCLUDE_RE = re.compile(r"^\s*(INC(?:LUDE|BIN))", re.IGNORECASE) | |
def dependencies_in(asm_file_paths): | |
asm_file_paths = list(asm_file_paths) | |
dependencies = {} | |
for path in asm_file_paths: | |
if path not in dependencies: | |
asm_dependencies, bin_dependencies = shallow_dependencies_of(path) | |
dependencies[path] = asm_dependencies | bin_dependencies | |
asm_file_paths += asm_dependencies | |
return dependencies | |
def shallow_dependencies_of(asm_file_path): | |
asm_dependencies = set() | |
bin_dependencies = set() | |
with open(asm_file_path, 'r', encoding='utf-8') as f: | |
for line in f: | |
m = INCLUDE_RE.match(line) | |
if m is None: | |
continue | |
keyword = m.group(1).upper() | |
line = line.split(';', 1)[0] | |
path = line[line.index('"') + 1:line.rindex('"')] | |
if keyword == 'INCLUDE': | |
asm_dependencies.add(path) | |
else: | |
bin_dependencies.add(path) | |
return asm_dependencies, bin_dependencies | |
def main(): | |
if not len(sys.argv) > 1: | |
print("Usage: {} <paths to assembly files...>".format(os.path.basename(__file__))) | |
sys.exit(1) | |
for path, dependencies in dependencies_in(sys.argv[1:]).items(): | |
# It seems that if A depends on B which depends on C, and | |
# C is modified, Make needs you to change the modification | |
# time of B too. That's the reason for the "@touch $@". | |
if dependencies: | |
print("{}: {}\n\t@touch $@".format(path, ' '.join(dependencies))) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.PHONY: all | |
OBJECTS = src/one_file_with_recursive_includes.o src/another_such_file.o | |
# [Your actual rules here] | |
# For example: | |
$(OBJECTS): %.o: %.asm | |
rgbasm -o $@ $< | |
# If you're using pattern rules, it actually matters that all | |
# the dependencies lie after those in the makefile. | |
# If you have Make version 4.2 or newer, you can skip the echo | |
# and variable and just use .SHELLSTATUS in the ifneq. | |
# If you want the Python version, switch this shell command out. | |
DEPENDENCY_SCAN_EXIT_STATUS := $(shell asmdependencies $(OBJECTS:.o=.asm) > dependencies.d; echo $$?) | |
ifneq ($(DEPENDENCY_SCAN_EXIT_STATUS), 0) | |
$(error Dependency scan failed) | |
endif | |
include dependencies.d |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment