Initial rework
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user