Skip to content

Commit d57f765

Browse files
committed
Add config
1 parent 12ff5f4 commit d57f765

File tree

3 files changed

+90
-31
lines changed

3 files changed

+90
-31
lines changed

.verify-helper/docs/static/document.ja.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ CXXFLAGS = ["-std=c++17", "-Wall", "-g", "-fsanitize=undefined", "-D_GLIBCXX_DEB
4343

4444
### C# の設定
4545

46-
設定項目はありません。
47-
4846
[SourceExpander](https://github.com/kzrnm/SourceExpander) を使用して各種機能を実現します。
4947

5048
必須設定
@@ -54,6 +52,17 @@ CXXFLAGS = ["-std=c++17", "-Wall", "-g", "-fsanitize=undefined", "-D_GLIBCXX_DEB
5452

5553
具体的な設定は [examples/csharpsx](https://github.com/online-judge-tools/verification-helper/tree/master/examples/csharpsx) を参照。
5654

55+
56+
`.verify-helper/config.toml` というファイルを作って以下のように設定を書くと各種設定ができます。
57+
58+
- static_embedding: `dotnet-source-expand``--static-embedding` オプション
59+
- enable_bundle_projects: `bundle` が正常に動作する `csproj`
60+
61+
``` toml
62+
[[languages.csharp]]
63+
static_embedding = "// embed"
64+
enable_bundle_projects = ["examples/csharpsx/Tests/Tests.csproj"]
65+
```
5766
### Nim の設定
5867

5968
`.verify-helper/config.toml` というファイルを作って以下のように設定を書くと、コンパイルの際に変換する言語 (例: `c`, `cpp`) やそのオプションを指定できます。

.verify-helper/docs/static/document.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ There is no config now.
4343

4444
### Settings for C#
4545

46-
There is no config now.
47-
4846
`oj-verify` and `oj-bundle` work with [SourceExpander](https://github.com/kzrnm/SourceExpander).
4947

5048
Requied settings
@@ -54,6 +52,17 @@ Requied settings
5452

5553
For the details refer to [examples/csharpsx](https://github.com/online-judge-tools/verification-helper/tree/master/examples/csharpsx).
5654

55+
You can specify compilers and options with writing `.verify-helper/config.toml` as below.
56+
57+
- static_embedding: `dotnet-source-expand` with `--static-embedding` option
58+
- enable_bundle_projects: List of `csproj` file that `bundle` work correctly.
59+
60+
``` toml
61+
[[languages.csharp]]
62+
static_embedding = "// embed"
63+
enable_bundle_projects = ["examples/csharpsx/Tests/Tests.csproj"]
64+
```
65+
5766
### Settings for Nim
5867

5968
You can specify options and targets (e.g. `c` `cpp`) with writing `.verify-helper/config.toml` as below.

onlinejudge_verify/languages/csharp.py

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,44 @@
1111
from typing import *
1212

1313
import onlinejudge_verify.languages.special_comments as special_comments
14+
from onlinejudge_verify.config import get_config
1415
from onlinejudge_verify.languages.models import Language, LanguageEnvironment
1516

1617
logger = getLogger(__name__)
1718

1819

20+
@overload
21+
def check_output(command: List[str], *, text: Literal[True]) -> str:
22+
...
23+
24+
25+
@overload
26+
def check_output(command: List[str], *, text: Literal[False]) -> bytes:
27+
...
28+
29+
30+
@overload
31+
def check_output(command: List[str]) -> bytes:
32+
...
33+
34+
35+
def check_output(command: List[str], *, text: bool = False) -> Union[bytes, str]:
36+
try:
37+
return subprocess.check_output(command, text=text)
38+
except (subprocess.CalledProcessError) as e:
39+
logger.error('raise subprocess.CalledProcessError')
40+
logger.info(' stdout: %s', e.stdout)
41+
logger.info(' stderr: %s', e.stderr)
42+
raise
43+
44+
1945
@functools.lru_cache(maxsize=1)
2046
def _check_dotnet_version() -> None:
2147
if not shutil.which('dotnet'):
2248
raise RuntimeError('`dotnet` not in $PATH')
2349
command = ['dotnet', '--version']
2450
logger.info('$ %s', ' '.join(command))
25-
res = subprocess.check_output(command, text=True).strip()
51+
res = check_output(command, text=True).strip()
2652
logger.info('dotnet version: %s', res)
2753
if distutils.version.LooseVersion(res) <= distutils.version.LooseVersion("6"):
2854
raise RuntimeError("oj-verify needs .NET 6 SDK or newer")
@@ -34,7 +60,7 @@ def _check_expander_console() -> None:
3460
raise RuntimeError('`dotnet-source-expand` not in $PATH. Run `dotnet tool install -g SourceExpander.Console`')
3561
command = ['dotnet-source-expand', 'version']
3662
logger.info('$ %s', ' '.join(command))
37-
res = subprocess.check_output(command, text=True).strip()
63+
res = check_output(command, text=True).strip()
3864
logger.info('dotnet-source-expand version: %s', res)
3965
if distutils.version.LooseVersion(res) < distutils.version.LooseVersion("5"):
4066
raise RuntimeError('`dotnet-source-expand` version must be 5.0.0 or newer. Update SourceExpander.Console. `dotnet tool update -g SourceExpander.Console`')
@@ -63,7 +89,7 @@ def enumerate_library(lines: List[str]):
6389
if len(sp) >= 2:
6490
yield EmbeddedLibrary(sp[0], sp[1])
6591

66-
res = list(enumerate_library(subprocess.check_output(command, encoding='utf-8').strip().splitlines()))
92+
res = list(enumerate_library(check_output(command, text=True).strip().splitlines()))
6793
logger.debug('libraries: %s', res)
6894
return res
6995

@@ -72,7 +98,7 @@ def enumerate_library(lines: List[str]):
7298
def _check_embedded_existing(csproj_path: pathlib.Path) -> None:
7399
command = ['dotnet', 'build', str(csproj_path)]
74100
logger.info('$ %s', ' '.join(command))
75-
subprocess.check_output(command)
101+
check_output(command)
76102
l = _list_embedded(csproj_path)
77103
if len(l) == 0:
78104
raise RuntimeError('Library needs SourceExpander.Embedder')
@@ -106,24 +132,6 @@ def _resolve_csproj(path: pathlib.Path) -> Optional[pathlib.Path]:
106132
return _resolve_csproj(path.parent)
107133

108134

109-
@functools.lru_cache(maxsize=None)
110-
def _expand_code_dict(csproj_path: pathlib.Path) -> Dict[pathlib.Path, str]:
111-
_check_expander_console()
112-
command = ['dotnet-source-expand', 'expand-all', str(csproj_path)]
113-
logger.info('$ %s', ' '.join(command))
114-
json_res = subprocess.check_output(command)
115-
return {pathlib.Path(t['FilePath']): t['ExpandedCode'] for t in json.loads(json_res)}
116-
117-
118-
@functools.lru_cache(maxsize=None)
119-
def _expand_code(path: pathlib.Path) -> bytes:
120-
_check_expander_console()
121-
csproj_path = _resolve_csproj(path)
122-
_check_no_embedder(csproj_path)
123-
d = _expand_code_dict(csproj_path)
124-
return d[path].encode('utf-8')
125-
126-
127135
class DependencyInfo:
128136
def __init__(self, filename: str, dependencies: List[str], typenames: Set[str]) -> None:
129137
self.filename = filename
@@ -143,7 +151,7 @@ def _dependency_info_list(csproj_path: pathlib.Path) -> List[DependencyInfo]:
143151

144152
command = ['dotnet-source-expand', 'dependency', '-p', str(csproj_path)]
145153
logger.info('$ %s', ' '.join(command))
146-
res = subprocess.check_output(command)
154+
res = check_output(command)
147155
return json.loads(res, object_hook=lambda d: DependencyInfo(d['FileName'], d['Dependencies'], set(d['TypeNames'])))
148156

149157

@@ -173,7 +181,17 @@ def _get_target_framework(csproj_path: pathlib.Path) -> str:
173181
return target
174182

175183

184+
class CSharpConfig:
185+
def __init__(self, config: Dict[str, Any]) -> None:
186+
root = config.get('languages', {}).get('csharp', {})
187+
self.static_embedding: Optional[str] = root.get('static_embedding', None)
188+
189+
176190
class CSharpLanguageEnvironment(LanguageEnvironment):
191+
def __init__(self, config: CSharpConfig) -> None:
192+
super().__init__()
193+
self.config = config
194+
177195
@staticmethod
178196
def _create_runner_project(code: bytes, target_framework: str, output_dir):
179197
os.makedirs(str(output_dir), exist_ok=True)
@@ -194,11 +212,11 @@ def compile(self, path: pathlib.Path, *, basedir: pathlib.Path, tempdir: pathlib
194212
_check_env(path)
195213
target_framework = _get_target_framework(_resolve_csproj(path))
196214
logger.info('build: TargetFramework = %s', target_framework)
197-
self._create_runner_project(_expand_code(path), target_framework, output_dir)
215+
self._create_runner_project(self._expand_code(path, self.config.static_embedding), target_framework, output_dir)
198216

199217
command = ['dotnet', 'build', str(output_dir / 'runner.csproj'), '-c', 'Release', '-o', str(output_dir / 'bin')]
200218
logger.info('$ %s', ' '.join(command))
201-
subprocess.check_output(command)
219+
check_output(command)
202220

203221
def get_execute_command(self, path: pathlib.Path, *, basedir: pathlib.Path, tempdir: pathlib.Path) -> List[str]:
204222
path = path.resolve()
@@ -207,8 +225,31 @@ def get_execute_command(self, path: pathlib.Path, *, basedir: pathlib.Path, temp
207225
_check_env(path)
208226
return [str(output_dir / 'bin' / 'runner')]
209227

228+
@functools.lru_cache(maxsize=None)
229+
def _expand_code_dict(self, csproj_path: pathlib.Path) -> Dict[pathlib.Path, str]:
230+
_check_expander_console()
231+
command = ['dotnet-source-expand', 'expand-all', str(csproj_path)]
232+
if self.static_embedding:
233+
command.extend(['--static-embedding', self.static_embedding])
234+
logger.info('$ %s', ' '.join(command))
235+
json_res = check_output(command)
236+
return {pathlib.Path(t['FilePath']): t['ExpandedCode'] for t in json.loads(json_res)}
237+
238+
@functools.lru_cache(maxsize=None)
239+
def _expand_code(self, path: pathlib.Path) -> bytes:
240+
_check_expander_console()
241+
csproj_path = _resolve_csproj(path)
242+
_check_no_embedder(csproj_path)
243+
d = self._expand_code_dict(csproj_path)
244+
return d[path].encode('utf-8')
245+
210246

211247
class CSharpLanguage(Language):
248+
def __init__(self) -> None:
249+
super().__init__()
250+
self.config = CSharpConfig(get_config())
251+
self.environment = CSharpLanguageEnvironment(self.config)
252+
212253
def list_attributes(self, path: pathlib.Path, *, basedir: pathlib.Path) -> Dict[str, Any]:
213254
path = path.resolve()
214255
attributes: Dict[str, Any] = special_comments.list_special_comments(path)
@@ -224,7 +265,7 @@ def list_dependencies(self, path: pathlib.Path, *, basedir: pathlib.Path) -> Lis
224265
def bundle(self, path: pathlib.Path, *, basedir: pathlib.Path, options: Dict[str, Any]) -> bytes:
225266
path = path.resolve()
226267
_check_env(path)
227-
return _expand_code(path)
268+
return self.environment._expands_code(path, self.config.static_embedding)
228269

229270
def list_environments(self, path: pathlib.Path, *, basedir: pathlib.Path) -> Sequence[CSharpLanguageEnvironment]:
230-
return [CSharpLanguageEnvironment()]
271+
return [self.environment]

0 commit comments

Comments
 (0)