Initial rework

This commit is contained in:
2026-06-25 02:45:43 +00:00
commit 24b46f7fc2
56 changed files with 2166 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
from pathlib import Path
from ..models import Optimization
from ..models import Result
from ..models import StdC
from ..models import StdCpp
from ..shell import execute
from .._logger import logger
from ._driver import CompilerDriver
from ._options import CompilerOptions
class GnucDriver(CompilerDriver):
__OPTLEVEL_MAPPING = {
Optimization.NONE: "-O0",
Optimization.LOW: "-O1",
Optimization.HIGH: "-O2",
Optimization.DEBUG: "-Og",
Optimization.SMALL: "-Os",
Optimization.SPEED: "-O3",
Optimization.TINY: "-Oz",
Optimization.FAST: "-OFast"
}
def compile_program(
self,
options: CompilerOptions,
dstpath: Path
) -> Result:
assert options is not None, "Compiler options are required"
assert len(options.objfiles) != 0, "Object files are required"
compiler = self.tooling.cc
cppext = [".cpp", ".cxx", ".cc"]
for obj in options.objfiles:
if obj.suffixes[0] in cppext:
compiler = self.tooling.cxx
break
args = [f"{compiler} -o {str(dstpath)}"]
args.extend(sorted(
[str(v) for v in options.objfiles],
key=lambda f: f.endswith(".so")
))
args.extend(options.flags)
if len(options.archives) > 0:
for directory in options.libdirs: args.append(f"-L{str(directory)}")
for archive in options.archives: args.append(f"-l{archive}")
cmdstr = ' '.join(args)
# logger.info(cmdstr)
result: list[Result] = [None]
execute(
cmdstr,
lambda cmdstr, stdout, stderr:
self.handle_on_data(result, str(dstpath), cmdstr, stdout, stderr),
lambda cmdstr, stdout, stderr:
self.handle_on_error(result, str(dstpath), cmdstr, stdout, stderr)
)
return result[0]
def compile_archive(
self,
options: CompilerOptions,
dstpath: Path
) -> Result:
args = [self.tooling.ar, f"rcs {str(dstpath)}"]
for obj in options.objfiles:
args.append(str(obj))
cmdstr = ' '.join(args)
result: list[Result] = [None]
execute(
cmdstr,
lambda cmdstr, stdout, stderr:
self.handle_on_data(result, str(dstpath), cmdstr, stdout, stderr),
lambda cmdstr, stdout, stderr:
self.handle_on_error(result, str(dstpath), cmdstr, stdout, stderr)
)
return result[0]
def compile_library(
self,
options: CompilerOptions,
dstpath: Path
) -> Result:
assert options is not None, "Compiler options are required"
assert len(options.objfiles) != 0, "Object files are required"
compiler = self.tooling.cc
cppext = [".cpp", ".cxx", ".cc"]
for obj in options.objfiles:
if obj.suffixes[0] in cppext:
compiler = self.tooling.cxx
break
args = [f"{compiler} -shared -o {str(dstpath)}"]
args.extend(sorted(
[str(v) for v in options.objfiles],
key=lambda f: f.endswith(".so")
))
args.extend(options.flags)
if len(options.archives) > 0:
for directory in options.libdirs: args.append(f"-L{str(directory)}")
for archive in options.archives: args.append(f"-l{archive}")
cmdstr = ' '.join(args)
# logger.info(cmdstr)
result: list[Result] = [None]
execute(
cmdstr,
lambda cmdstr, stdout, stderr:
self.handle_on_data(result, str(dstpath), cmdstr, stdout, stderr),
lambda cmdstr, stdout, stderr:
self.handle_on_error(result, str(dstpath), cmdstr, stdout, stderr)
)
return result[0]
def compile_object(
self,
options: CompilerOptions,
srcpath: Path,
dstpath: Path
) -> Result:
assert options is not None, "Compiler options are required"
compiler = self.tooling.cc
standard = options.stdc
optlevel = self.__OPTLEVEL_MAPPING.get(options.optlevel)
cppext = [".cpp", ".cxx", ".cc"]
if srcpath.suffix in cppext:
compiler = self.tooling.cxx
standard = options.stdcpp
args = [
f"{compiler}",
f"-c {str(srcpath)}",
f"-o {str(dstpath)}"
]
if options.pic:
args.append("-fPIC")
args.append(f"-std={standard}")
args.append(optlevel)
args.extend(options.flags)
for directory in options.incdirs: args.append(f"-I{str(directory)}")
for directory in options.libdirs: args.append(f"-L{str(directory)}")
for archive in options.archives: args.append(f"-l{archive}")
for define in options.defines: args.append(f"-D{define}")
cmdstr = ' '.join(args)
# logger.info(cmdstr)
result: list[Result] = [None]
execute(
cmdstr,
lambda cmdstr, stdout, stderr:
self.handle_on_data(result, str(dstpath), cmdstr, stdout, stderr),
lambda cmdstr, stdout, stderr:
self.handle_on_error(result, str(dstpath), cmdstr, stdout, stderr)
)
return result[0]
def handle_on_data(
self,
result: list[Result],
target: str,
cmdstr: str,
stdout: str,
stderr: str
) -> None:
result[0] = Result(
success = True,
target = target,
command = cmdstr
)
result[0].diagnostics.append(stdout)
def handle_on_error(
self,
result: list[Result],
target: str,
cmdstr: str,
stdout: str,
stderr: str
) -> None:
result[0] = Result(
success = False,
target = target,
command = cmdstr
)
result[0].diagnostics.append(stderr)