Skip to content

Commit cef3714

Browse files
author
Martin Krulis
committed
Adding custom compilation box.
1 parent 3b1cb9e commit cef3714

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

app/helpers/ExerciseConfig/Pipeline/Box/BoxService.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function __construct() {
4949
MergeFilesBox::$MERGE_FILES_TYPE => MergeFilesBox::class,
5050
MergeTwoFilesBox::$MERGE_TWO_FILES_TYPE => MergeTwoFilesBox::class,
5151
MergeFileAndFilesBox::$MERGE_FILE_AND_FILES_TYPE => MergeFileAndFilesBox::class,
52+
CustomCompilationBox::$CUSTOM_COMPILATION_TYPE => CustomCompilationBox::class,
5253
];
5354
}
5455

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
namespace App\Helpers\ExerciseConfig\Pipeline\Box;
4+
5+
use App\Helpers\ExerciseConfig\Compilation\CompilationParams;
6+
use App\Helpers\ExerciseConfig\Pipeline\Box\Params\ConfigParams;
7+
use App\Helpers\ExerciseConfig\Pipeline\Box\Params\LinuxSandbox;
8+
use App\Helpers\ExerciseConfig\Pipeline\Box\Params\Priorities;
9+
use App\Helpers\ExerciseConfig\Pipeline\Box\Params\TaskType;
10+
use App\Helpers\ExerciseConfig\Pipeline\Ports\Port;
11+
use App\Helpers\ExerciseConfig\Pipeline\Ports\PortMeta;
12+
use App\Helpers\ExerciseConfig\VariableTypes;
13+
use App\Helpers\JobConfig\SandboxConfig;
14+
use App\Helpers\JobConfig\Tasks\Task;
15+
16+
17+
/**
18+
* Box which represents custom compilation unit.
19+
* It can be used for any compilation preprocessing or postprocessing,
20+
* like custom macro processing, bison&flex compilation, or additional executable bundling.
21+
*/
22+
class CustomCompilationBox extends CompilationBox
23+
{
24+
/** Type key */
25+
public static $CUSTOM_COMPILATION_TYPE = "custom-compilation";
26+
public static $DEFAULT_NAME = "Custom Compilation";
27+
public static $COMPILER_EXEC_PORT_KEY = "compiler-exec";
28+
29+
private static $initialized = false;
30+
private static $defaultInputPorts;
31+
private static $defaultOutputPorts;
32+
33+
/**
34+
* Static initializer.
35+
*/
36+
public static function init() {
37+
if (!self::$initialized) {
38+
self::$initialized = true;
39+
self::$defaultInputPorts = array(
40+
new Port((new PortMeta())->setName(self::$COMPILER_EXEC_PORT_KEY)->setType(VariableTypes::$STRING_TYPE)),
41+
new Port((new PortMeta())->setName(self::$ARGS_PORT_KEY)->setType(VariableTypes::$STRING_ARRAY_TYPE)),
42+
new Port((new PortMeta())->setName(self::$SOURCE_FILES_PORT_KEY)->setType(VariableTypes::$FILE_ARRAY_TYPE)),
43+
new Port((new PortMeta())->setName(self::$EXTRA_FILES_PORT_KEY)->setType(VariableTypes::$FILE_ARRAY_TYPE))
44+
);
45+
self::$defaultOutputPorts = array(
46+
new Port((new PortMeta())->setName(self::$BINARY_FILE_PORT_KEY)->setType(VariableTypes::$FILE_TYPE))
47+
);
48+
}
49+
}
50+
51+
/**
52+
* JudgeNormalBox constructor.
53+
* @param BoxMeta $meta
54+
*/
55+
public function __construct(BoxMeta $meta) {
56+
parent::__construct($meta);
57+
}
58+
59+
60+
/**
61+
* Get type of this box.
62+
* @return string
63+
*/
64+
public function getType(): string {
65+
return self::$CUSTOM_COMPILATION_TYPE;
66+
}
67+
68+
/**
69+
* Get default input ports for this box.
70+
* @return array
71+
*/
72+
public function getDefaultInputPorts(): array {
73+
self::init();
74+
return self::$defaultInputPorts;
75+
}
76+
77+
/**
78+
* Get default output ports for this box.
79+
* @return array
80+
*/
81+
public function getDefaultOutputPorts(): array {
82+
self::init();
83+
return self::$defaultOutputPorts;
84+
}
85+
86+
/**
87+
* Get default name of this box.
88+
* @return string
89+
*/
90+
public function getDefaultName(): string {
91+
return self::$DEFAULT_NAME;
92+
}
93+
94+
95+
/**
96+
* Compile box into set of low-level tasks.
97+
* @param CompilationParams $params
98+
* @return array
99+
*/
100+
public function compile(CompilationParams $params): array {
101+
$task = $this->compileBaseTask($params);
102+
$task->setCommandBinary($this->getInputPortValue(self::$COMPILER_EXEC_PORT_KEY)->getValue());
103+
104+
// Get files that should be injected into args....
105+
$binaryFile = $this->getOutputPortValue(self::$BINARY_FILE_PORT_KEY)->getValue(ConfigParams::$EVAL_DIR);
106+
$injections = [
107+
self::$SOURCE_FILES_PORT_KEY =>
108+
$this->getInputPortValue(self::$SOURCE_FILES_PORT_KEY)->getValue(ConfigParams::$EVAL_DIR),
109+
self::$EXTRA_FILES_PORT_KEY =>
110+
$this->getInputPortValue(self::$EXTRA_FILES_PORT_KEY)->getValue(ConfigParams::$EVAL_DIR),
111+
self::$BINARY_FILE_PORT_KEY => [ $binaryFile ],
112+
];
113+
114+
// Process args
115+
$rawArgs = [];
116+
if ($this->hasInputPortValue(self::$ARGS_PORT_KEY)) {
117+
$rawArgs = $this->getInputPortValue(self::$ARGS_PORT_KEY)->getValue();
118+
}
119+
120+
$args = [];
121+
foreach ($rawArgs as $arg) {
122+
if (substr($arg, 0, 2) === '$@') {
123+
$name = substr($arg, 2);
124+
if ($injections[$name]) {
125+
array_push($args, ...$injections[$name]);
126+
unset($injections[$name]);
127+
}
128+
} else {
129+
$args[] = $arg;
130+
}
131+
}
132+
133+
// If no placeholders were found, append the files in typical manner....
134+
if (!empty($injections[self::$SOURCE_FILES_PORT_KEY])) {
135+
array_push($args, ...$injections[self::$SOURCE_FILES_PORT_KEY]);
136+
}
137+
if (!empty($injections[self::$EXTRA_FILES_PORT_KEY])) {
138+
array_push($args, ...$injections[self::$EXTRA_FILES_PORT_KEY]);
139+
}
140+
if (!empty($injections[self::$BINARY_FILE_PORT_KEY])) {
141+
$args[] = "-o";
142+
$args[] = $binaryFile;
143+
}
144+
145+
$task->setCommandArguments($args);
146+
147+
// check if file produced by compilation was successfully created
148+
$binary = $this->getOutputPortValue(self::$BINARY_FILE_PORT_KEY)->getTestPrefixedValue(ConfigParams::$SOURCE_DIR);
149+
$exists = $this->compileExistsTask([$binary]);
150+
151+
return [$task, $exists];
152+
}
153+
154+
}

0 commit comments

Comments
 (0)