33Each comes with a key, used to identify a previously compiled version.
44We can then reuse already compiled versions.
55"""
6- from typing import Any , Awaitable , Callable , Generic , Hashable , List , Set , Tuple , TypeVar
6+ import shutil
7+ from typing import (
8+ Any , Awaitable , Callable , Generic , Hashable , List , Optional , Set , Tuple , TypeVar ,
9+ ContextManager , Union ,
10+ )
711from typing_extensions import Self
812from pathlib import Path
913import os
1014import pickle
1115import random
1216import tempfile
17+ import contextlib
1318
1419from srctools import AtomicWriter , logger
1520from srctools .game import Game
@@ -52,6 +57,7 @@ def __init__(
5257 folder_name : str ,
5358 version : object = 0 ,
5459 pack_models : bool = True ,
60+ compile_dir : Optional [Path ] = None ,
5561 ) -> None :
5662 # The models already constructed.
5763 self ._built_models : ACache [ModelKey , GenModel [OutT ]] = ACache ()
@@ -65,6 +71,7 @@ def __init__(
6571 self .pack : PackList = pack
6672 self .version = version
6773 self .studiomdl_loc = studiomdl_loc
74+ self .compile_dir = (compile_dir / folder_name ) if compile_dir is not None else None
6875 self .limiter = trio .CapacityLimiter (8 )
6976 self .pack_models = pack_models
7077 # For statistics, the number we built this compile
@@ -82,6 +89,7 @@ def from_ctx(cls, ctx: Context, folder_name: str, version: object=0) -> 'ModelCo
8289 ctx .bsp_path .stem ,
8390 folder_name ,
8491 version ,
92+ compile_dir = ctx .modelcompile_dump ,
8593 )
8694
8795 def use_count (self ) -> int :
@@ -225,7 +233,20 @@ async def _compile(
225233 self ._mdl_names .add (mdl_name )
226234 break
227235
228- with tempfile .TemporaryDirectory (prefix = 'mdl_compile' ) as folder :
236+ # If compile dir is specified, create the folder/clear it, but don't delete once done.
237+ ctx_man : ContextManager [Union [str , bytes , Path ]]
238+ if self .compile_dir is not None :
239+ path = Path (self .compile_dir , mdl_name )
240+ ctx_man = contextlib .nullcontext (path )
241+ try :
242+ shutil .rmtree (path )
243+ except FileNotFoundError :
244+ pass
245+ path .mkdir (parents = True , exist_ok = True )
246+ else : # If not specified, use a temporary directory.
247+ ctx_man = tempfile .TemporaryDirectory (prefix = 'mdl_compile' )
248+
249+ with ctx_man as folder :
229250 path = Path (folder )
230251 result = await compile_func (key , path , f'{ self .model_folder } { mdl_name } .mdl' , args )
231252 studio_args = [
@@ -237,6 +258,8 @@ async def _compile(
237258 LOGGER .debug ("Execute {}" , studio_args )
238259 async with self .limiter :
239260 res = await trio .run_process (studio_args , capture_stdout = True , check = False )
261+ if self .compile_dir is not None :
262+ (path / 'compile.log' ).write_bytes (res .stdout )
240263 LOGGER .debug (
241264 'Log for {}:\n {}' ,
242265 str (path / 'model.qc' ),
0 commit comments