112 lines
2.9 KiB
Python
112 lines
2.9 KiB
Python
import os
|
|
import shutil
|
|
import subprocess as sp
|
|
from sane import _Help as Sane
|
|
from glob import glob
|
|
from sane import *
|
|
|
|
COMPILER = "gcc"
|
|
COMPILE_FLAGS = [
|
|
"-std=c11",
|
|
"-g3",
|
|
"-O0",
|
|
"-Wall",
|
|
"-Wextra",
|
|
"-Werror",
|
|
"-Wpedantic",
|
|
"-pedantic-errors",
|
|
"-fopenmp",
|
|
]
|
|
LINK_FLAGS = ["-fopenmp"]
|
|
LIBRARIES = ["-lm"]
|
|
OBJ_DIR = os.path.join("obj", "release" if ("RELEASE" in os.environ) else "debug")
|
|
SRC_DIR = "src"
|
|
EXE_NAME = "main." + ("release" if ("RELEASE" in os.environ) else "debug") + ".exe"
|
|
|
|
ROOT = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
if "RELEASE" in os.environ:
|
|
COMPILE_FLAGS[COMPILE_FLAGS.index("-O0")] = "-O2"
|
|
COMPILE_FLAGS[COMPILE_FLAGS.index("-g3")] = "-g"
|
|
COMPILE_FLAGS.append("-DRELEASE")
|
|
LINK_FLAGS.append("-DRELEASE")
|
|
|
|
if "COMPILE_FLAGS" in os.environ:
|
|
COMPILE_FLAGS.extend(os.environ["COMPILE_FLAGS"].split(";"))
|
|
if "LINK_FLAGS" in os.environ:
|
|
LINK_FLAGS.extend(os.environ["LINK_FLAGS"].split(";"))
|
|
|
|
|
|
def as_object(source_path):
|
|
"""Takes a source path and returns the path to the corresponding compiled object."""
|
|
source_path = os.path.relpath(source_path, ROOT)
|
|
object_name = source_path + ".obj"
|
|
object_path = os.path.join(OBJ_DIR, object_name)
|
|
return object_path
|
|
|
|
|
|
def make_object_recipe(source_path):
|
|
object_path = os.path.realpath(as_object(source_path))
|
|
object_dir = os.path.dirname(object_path)
|
|
|
|
if not os.path.exists(object_dir):
|
|
os.makedirs(object_dir)
|
|
|
|
condition = Sane.file_condition(sources=[source_path], targets=[object_path])
|
|
|
|
@recipe(
|
|
name=f"compile_{source_path}", conditions=[condition], hooks=["obj_compile"]
|
|
)
|
|
def compile_obj():
|
|
sp.run([COMPILER, "-c", *COMPILE_FLAGS, "-o", object_path, source_path])
|
|
|
|
|
|
source_files = [os.path.realpath(path) for path in glob("**/*.c", recursive=True)]
|
|
|
|
for source_file in source_files:
|
|
make_object_recipe(source_file)
|
|
|
|
|
|
def exe_not_exists():
|
|
return not os.path.exists(EXE_NAME)
|
|
|
|
|
|
def old_exe():
|
|
object_files = [os.path.realpath(path) for path in glob("**/*.obj", recursive=True)]
|
|
return Sane.file_condition(object_files, [EXE_NAME])()
|
|
|
|
|
|
@recipe(hook_deps=["obj_compile"], info="Compile the source files.")
|
|
def compile():
|
|
pass
|
|
|
|
|
|
@recipe(
|
|
recipe_deps=[compile],
|
|
conditions=[exe_not_exists, old_exe],
|
|
info="Links the main executable.",
|
|
)
|
|
def link():
|
|
obj_files = glob(
|
|
os.path.join(OBJ_DIR, "**", "*.obj").replace("\\", "/"), recursive=True
|
|
)
|
|
sp.run([COMPILER, *LINK_FLAGS, "-o", EXE_NAME, *obj_files, *LIBRARIES])
|
|
|
|
|
|
@recipe(info="Removes all compiled objects.")
|
|
def clean():
|
|
shutil.rmtree(OBJ_DIR)
|
|
|
|
|
|
@recipe(recipe_deps=[link], conditions=[lambda: True])
|
|
def run():
|
|
with open(os.path.join(ROOT, "data/2222_inq.txt"), "r") as input:
|
|
exe = os.path.join(ROOT, EXE_NAME)
|
|
sp.run(
|
|
[exe, "2", "2", "2", "2"],
|
|
stdin=input,
|
|
)
|
|
|
|
|
|
sane_run(link)
|