[WS] Use tup to build projects
git-svn-id: svn://kolibrios.org@9377 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
84837f41d5
commit
4bf8ca235a
@ -10,6 +10,9 @@ if len(sys.argv) < 2 or sys.argv[1] != "--remove-everything":
|
|||||||
# Remove workspace folder
|
# Remove workspace folder
|
||||||
shutil.rmtree("workspace", ignore_errors = True)
|
shutil.rmtree("workspace", ignore_errors = True)
|
||||||
|
|
||||||
|
# Remove tup database
|
||||||
|
shutil.rmtree(".tup", ignore_errors = True)
|
||||||
|
|
||||||
# TODO: Make build.py remove the stuff it built
|
# TODO: Make build.py remove the stuff it built
|
||||||
|
|
||||||
# Remove files copied from _tools/workspace
|
# Remove files copied from _tools/workspace
|
||||||
|
@ -32,3 +32,6 @@ if __name__ == "__main__":
|
|||||||
tools_workspace_build_py = os.path.join(tools_workspace, "build.py")
|
tools_workspace_build_py = os.path.join(tools_workspace, "build.py")
|
||||||
create_workspace_script("run.py", tools_workspace_run_py)
|
create_workspace_script("run.py", tools_workspace_run_py)
|
||||||
create_workspace_script("build.py", tools_workspace_build_py)
|
create_workspace_script("build.py", tools_workspace_build_py)
|
||||||
|
# Initalize tup here
|
||||||
|
# TODO: Do anything if tup doesn't exist
|
||||||
|
os.system("tup init")
|
||||||
|
@ -1,153 +1,74 @@
|
|||||||
# Copyright Magomed Kostoev
|
# Copyright Magomed Kostoev
|
||||||
# Published under MIT license
|
# Published under MIT license
|
||||||
|
|
||||||
class Rule:
|
block_beginner2finisher = {
|
||||||
pass
|
"(": ")",
|
||||||
|
"{": "}",
|
||||||
|
"\"": "\"",
|
||||||
|
}
|
||||||
|
|
||||||
def get_config(config_name):
|
def get_to(src, ptr, c, backwards = False):
|
||||||
if config_name == "KPACK_CMD":
|
while src[ptr] != c:
|
||||||
# Just never pack the file for now
|
if not backwards:
|
||||||
return ""
|
ptr += 1
|
||||||
else:
|
else:
|
||||||
print(f"Unknown config name: {config_name}")
|
ptr -= 1
|
||||||
exit(-1)
|
return ptr
|
||||||
|
|
||||||
def skip_whitespaces(src, ptr):
|
# Assuming we are at beginning of some block (string,
|
||||||
while len(src) > ptr and src[ptr] == " ":
|
# parenthesed expression, {}-like thing), get to end
|
||||||
|
# of the block (also handles the blocks openned in the
|
||||||
|
# way to the block ending character. So it's not just
|
||||||
|
# stupid searching for block closing character.
|
||||||
|
def get_to_block_finisher(src, ptr):
|
||||||
|
assert(src[ptr] in block_beginner2finisher)
|
||||||
|
|
||||||
|
block_beginner = src[ptr]
|
||||||
|
ptr += 1
|
||||||
|
while src[ptr] != block_beginner2finisher[block_beginner]:
|
||||||
|
# If any block starts here - get to its end and then continue
|
||||||
|
if src[ptr] in block_beginner2finisher:
|
||||||
|
ptr = get_to_block_finisher(src, ptr)
|
||||||
ptr += 1
|
ptr += 1
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
# Returns True if @src has @string starting from @ptr index
|
def get_strnig(src, ptr):
|
||||||
def match_string(src, ptr, string):
|
# Strings starts with "\""
|
||||||
if len(src) <= ptr + len(string):
|
assert(src[ptr] == "\"")
|
||||||
return False
|
|
||||||
for i in range(len(string)):
|
|
||||||
if src[ptr + i] != string[i]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def parse_tup_getconfig(src, ptr):
|
result = ""
|
||||||
# Skip get straight to the argument
|
# Skip first "\"" of the string
|
||||||
ptr += len("tup.getconfig(")
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
if src[ptr] != "\"":
|
|
||||||
print("Expected \"config name\" as tup.getconfig parameter")
|
|
||||||
exit()
|
|
||||||
(config_name, ptr) = parse_string(src, ptr)
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
# Skip closing parenthese of the tup.getconfig call
|
|
||||||
assert(src[ptr] == ")")
|
|
||||||
ptr += 1
|
ptr += 1
|
||||||
return (get_config(config_name), ptr)
|
|
||||||
|
|
||||||
def parse_string(src, ptr):
|
|
||||||
ptr += 1
|
|
||||||
string = ""
|
|
||||||
while src[ptr] != "\"":
|
while src[ptr] != "\"":
|
||||||
string += src[ptr]
|
result += src[ptr]
|
||||||
ptr += 1
|
ptr += 1
|
||||||
# Skip the closing "\""
|
|
||||||
ptr += 1
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
# Check if we have concatination here
|
|
||||||
if match_string(src, ptr, ".."):
|
|
||||||
# Skip the ".."
|
|
||||||
ptr += 2
|
|
||||||
# The expression parsing should result in a string
|
|
||||||
(string_to_add, ptr) = parse_expression(src, ptr)
|
|
||||||
# Concat our string to the resulting string
|
|
||||||
string += string_to_add
|
|
||||||
return (string, ptr)
|
|
||||||
|
|
||||||
def parse_expression(src, ptr):
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
result = "WAT?!"
|
|
||||||
if src[ptr] == "\"":
|
|
||||||
(result, ptr) = parse_string(src, ptr)
|
|
||||||
elif match_string(src, ptr, "tup.getconfig("):
|
|
||||||
(result, ptr) = parse_tup_getconfig(src, ptr)
|
|
||||||
else:
|
|
||||||
print(f"Can't handle anything starting with '{src[ptr]}'")
|
|
||||||
exit(-1)
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
return (result, ptr)
|
|
||||||
|
|
||||||
def expect_comma(src, ptr):
|
|
||||||
comma_skept = False
|
|
||||||
ptr = skip_whitespaces(src, ptr)
|
|
||||||
if src[ptr] == ",":
|
|
||||||
ptr += 1
|
|
||||||
return (True, ptr)
|
|
||||||
else:
|
|
||||||
return (False, ptr)
|
|
||||||
|
|
||||||
def parse_arguments(src, ptr):
|
|
||||||
result = []
|
|
||||||
# Parse first argument
|
|
||||||
(argument, ptr) = parse_expression(src, ptr)
|
|
||||||
result.append(argument)
|
|
||||||
(comma_encoutered, ptr) = expect_comma(src, ptr)
|
|
||||||
# Parse the second argument if it's there
|
|
||||||
if comma_encoutered:
|
|
||||||
(argument, ptr) = parse_expression(src, ptr)
|
|
||||||
result.append(argument)
|
|
||||||
(comma_encoutered, ptr) = expect_comma(src, ptr)
|
|
||||||
# Parse third argument if it's there
|
|
||||||
if comma_encoutered:
|
|
||||||
(argument, ptr) = parse_expression(src, ptr)
|
|
||||||
result.append(argument)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def parse_rule(src, ptr):
|
def parse_rule_output(src, ptr):
|
||||||
# Get straight to the first argument
|
# Get straight to the first argument
|
||||||
ptr += len("tup.rule(")
|
ptr += len("tup.rule")
|
||||||
# Parse the arguments
|
# Get to parenthese
|
||||||
args = parse_arguments(src, ptr)
|
ptr = get_to(src, ptr, "(")
|
||||||
# Build the rule object
|
# Get to the closing parenthese
|
||||||
result = Rule()
|
ptr = get_to_block_finisher(src, ptr)
|
||||||
if len(args) == 3:
|
# We are at closing parenthese of argument list
|
||||||
result.input = args[0]
|
# And the last argument is always output file
|
||||||
result.command = args[1]
|
# Let's get to closing "\"" of the output file name
|
||||||
result.output = args[2]
|
ptr = get_to(src, ptr, "\"", backwards = True)
|
||||||
# Replace %f with input file in rule's command
|
# Get into the string
|
||||||
if type(result.input == str):
|
ptr -= 1
|
||||||
result.command = result.command.replace("%f", result.input)
|
# Then get to the beginning of the string
|
||||||
else:
|
ptr = get_to(src, ptr, "\"", backwards = True)
|
||||||
print("Command building with non-string tup.rule's first argument"
|
# Now we can read the string
|
||||||
+ " isn't implemented")
|
return get_strnig(src, ptr)
|
||||||
exit()
|
|
||||||
# Replace %o with output file in rule's command
|
|
||||||
if type(result.output == str):
|
|
||||||
result.command = result.command.replace("%o", result.output)
|
|
||||||
else:
|
|
||||||
print("Command building with non-string tup.rule's first argument"
|
|
||||||
+ " isn't implemented")
|
|
||||||
exit()
|
|
||||||
elif len(args) == 2:
|
|
||||||
result.input = []
|
|
||||||
result.command = args[0]
|
|
||||||
result.output = args[1]
|
|
||||||
else:
|
|
||||||
print(f"tup.rule can only take 2 or 3 arguments, not {len(args)}")
|
|
||||||
exit(-1)
|
|
||||||
# Unify the API - return arrays as input and output
|
|
||||||
if type(result.input) == str:
|
|
||||||
result.input = [ result.input ]
|
|
||||||
else:
|
|
||||||
assert(type(result.input) == list)
|
|
||||||
if type(result.output) == str:
|
|
||||||
result.output = [ result.output ]
|
|
||||||
else:
|
|
||||||
assert(type(result.output) == list)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def parse(file_name):
|
def parse_tupfile_outputs(file_name):
|
||||||
rules = []
|
outputs = []
|
||||||
with open(file_name) as f:
|
with open(file_name) as f:
|
||||||
tupfile = f.read()
|
tupfile = f.read()
|
||||||
rule_begin_index = tupfile.find("tup.rule(")
|
rule_begin_index = tupfile.find("tup.rule(")
|
||||||
while (rule_begin_index != -1):
|
while (rule_begin_index != -1):
|
||||||
rules.append(parse_rule(tupfile, rule_begin_index))
|
outputs.append(parse_rule_output(tupfile, rule_begin_index))
|
||||||
# Find the next tup.rule call
|
# Find the next tup.rule call
|
||||||
rule_begin_index = tupfile.find("tup.rule(", rule_begin_index + len("tup.rule("))
|
rule_begin_index = tupfile.find("tup.rule(", rule_begin_index + len("tup.rule("))
|
||||||
return rules
|
return outputs
|
||||||
|
@ -5,21 +5,15 @@ path_to_tools_workspace = os.path.dirname(os.path.abspath(__file__))
|
|||||||
path_to_tools = os.path.dirname(path_to_tools_workspace)
|
path_to_tools = os.path.dirname(path_to_tools_workspace)
|
||||||
sys.path.append(path_to_tools)
|
sys.path.append(path_to_tools)
|
||||||
|
|
||||||
from lib.tupfile_parser import parse as parse_tupfile
|
from lib.tupfile_parser import parse_tupfile_outputs
|
||||||
|
|
||||||
def build():
|
def build():
|
||||||
if not os.path.exists("Tupfile.lua"):
|
os.system("tup")
|
||||||
print("No Tupfile.lua, can't build anything")
|
outputs = parse_tupfile_outputs("Tupfile.lua")
|
||||||
exit()
|
for name in outputs:
|
||||||
|
if name.endswith(".inc"):
|
||||||
tup_rules = parse_tupfile("Tupfile.lua")
|
continue
|
||||||
program_files = []
|
return name
|
||||||
for rule in tup_rules:
|
|
||||||
# TODO: Manage source dependencies
|
|
||||||
# TODO: Inform about tools required for the build
|
|
||||||
os.system(rule.command)
|
|
||||||
program_files += rule.output
|
|
||||||
return program_files
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
build()
|
build()
|
||||||
|
@ -51,7 +51,7 @@ def run_qemu(start_dir = "workspace"):
|
|||||||
return subprocess.Popen(a, bufsize = 0, stdout = qemu_stdout, stderr = qemu_stderr, stdin = subprocess.DEVNULL, start_new_session = True)
|
return subprocess.Popen(a, bufsize = 0, stdout = qemu_stdout, stderr = qemu_stderr, stdin = subprocess.DEVNULL, start_new_session = True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
program_files = build()
|
program_name = build()
|
||||||
|
|
||||||
os.makedirs("workspace", exist_ok = True)
|
os.makedirs("workspace", exist_ok = True)
|
||||||
|
|
||||||
@ -72,19 +72,16 @@ if __name__ == "__main__":
|
|||||||
img.delete_path("DEMOS")
|
img.delete_path("DEMOS")
|
||||||
img.delete_path("3D")
|
img.delete_path("3D")
|
||||||
|
|
||||||
log("Moving program files into kolibri image... ", end = "")
|
log("Moving program into kolibri image... ", end = "")
|
||||||
for file_name in program_files:
|
with open(program_name, "rb") as file:
|
||||||
with open(file_name, "rb") as file:
|
file_data = file.read()
|
||||||
file_data = file.read()
|
if not img.add_file_path(program_name.upper(), file_data):
|
||||||
if not img.add_file_path(file_name.upper(), file_data):
|
print(f"Coudn't move {program_name} into IMG")
|
||||||
print(f"Coudn't move {file_name} into IMG")
|
|
||||||
log("Done")
|
log("Done")
|
||||||
|
|
||||||
# TODO: Figure out which of compiled files is a program executable and only run it
|
# TODO: Figure out which of compiled files is a program executable and only run it
|
||||||
log("Adding program to autorun.dat", end = "")
|
log("Adding program to autorun.dat... ", end = "")
|
||||||
lines_to_add = b""
|
lines_to_add = bytes(f"\r\n/SYS/{program_name.upper()}\t\t""\t0\t# Your program", "ascii")
|
||||||
for file_name in program_files:
|
|
||||||
lines_to_add += bytes(f"\r\n/SYS/{file_name.upper()}\t\t""\t0\t# Your program", "ascii")
|
|
||||||
autorun_dat = img.extract_file_path("SETTINGS\AUTORUN.DAT")
|
autorun_dat = img.extract_file_path("SETTINGS\AUTORUN.DAT")
|
||||||
place_for_new_lines = autorun_dat.index(b"\r\n/SYS/@TASKBAR")# b"\r\n### Hello, ASM World! ###")
|
place_for_new_lines = autorun_dat.index(b"\r\n/SYS/@TASKBAR")# b"\r\n### Hello, ASM World! ###")
|
||||||
autorun_dat = autorun_dat[:place_for_new_lines] + lines_to_add + autorun_dat[place_for_new_lines:]
|
autorun_dat = autorun_dat[:place_for_new_lines] + lines_to_add + autorun_dat[place_for_new_lines:]
|
||||||
|
Loading…
Reference in New Issue
Block a user