@@ -23,10 +23,7 @@ const MASTERCHAIN_VARIANTS = [false, true];
2323type PythonCmd = { exe : string ; args : string [ ] } ;
2424
2525const resolvePython = ( ) : PythonCmd => {
26- const candidates =
27- process . platform === 'win32'
28- ? [ 'py' , 'py -3' , 'python3' , 'python' ]
29- : [ 'python3' , 'python' ] ;
26+ const candidates = process . platform === 'win32' ? [ 'py' , 'py -3' , 'python3' , 'python' ] : [ 'python3' , 'python' ] ;
3027 for ( const cmd of candidates ) {
3128 const [ exe , ...args ] = cmd . split ( ' ' ) ;
3229 try {
@@ -43,7 +40,9 @@ const resolvePython = (): PythonCmd => {
4340
4441const PYTHON = resolvePython ( ) ;
4542
46- function gpuAvailable ( ) : boolean {
43+ type GpuProbe = { ok : boolean ; reason ?: string } ;
44+
45+ function gpuAvailable ( ) : GpuProbe {
4746 const probe = `
4847try:
4948 import pyopencl as cl
5453 except Exception:
5554 pass
5655 print("1" if devs else "0")
57- except Exception:
58- print("0" )
56+ except Exception as e :
57+ print("err:" + repr(e) )
5958` ;
60- const res = spawnSync ( PYTHON . exe , [ ...PYTHON . args , '-c' , probe ] , { cwd : 'src' , encoding : 'utf8' } ) ;
61- return res . status === 0 && res . stdout . trim ( ) === '1' ;
59+ const res = spawnSync ( PYTHON . exe , [ ...PYTHON . args , '-c' , probe ] , {
60+ cwd : 'src' ,
61+ encoding : 'utf8' ,
62+ } ) ;
63+
64+ if ( res . error ) {
65+ return { ok : false , reason : `spawn failed: ${ res . error . message } ` } ;
66+ }
67+ const out = ( res . stdout || '' ) . trim ( ) ;
68+ if ( res . status !== 0 ) {
69+ const err = ( res . stderr || out || `exit ${ res . status } ` ) . trim ( ) ;
70+ return { ok : false , reason : `python exited ${ res . status } : ${ err } ` } ;
71+ }
72+ if ( out === '1' ) {
73+ return { ok : true } ;
74+ }
75+ return { ok : false , reason : `pyopencl unavailable or no OpenCL devices (stdout="${ out } ")` } ;
6276}
6377
6478type PyInfo = { start_digit_base : number } ;
@@ -218,9 +232,13 @@ for (let len = 1; len <= 4; len++) {
218232
219233const scenarios : Scenario [ ] = [ ...startScenarios , ...endScenarios , ...comboScenarios ] ;
220234
221- const gpuOk = gpuAvailable ( ) ;
235+ const gpu = gpuAvailable ( ) ;
236+ if ( ! gpu . ok ) {
237+ // Log once so it shows up even when the suite is skipped.
238+ console . warn ( `[generator.py GPU matrix] skipping: ${ gpu . reason } ` ) ;
239+ }
222240
223- ( gpuOk ? describe : describe . skip ) ( 'generator.py GPU matrix' , ( ) => {
241+ ( gpu . ok ? describe : describe . skip ) ( 'generator.py GPU matrix' , ( ) => {
224242 const owner = Address . parseFriendly ( OWNER ) . address ;
225243
226244 it . each ( scenarios ) ( '$name' , ( scenario ) => {
@@ -260,7 +278,7 @@ const gpuOk = gpuAvailable();
260278 // Rebuild StateInit and recompute contract address, compare to reported.
261279 type HitInit = {
262280 code : string ;
263- fixedPrefixLength ?: number ;
281+ fixedPrefixLength ?: number | null ;
264282 special ?: { tick : boolean ; tock : boolean } | null ;
265283 } ;
266284 type HitConfig = {
@@ -276,7 +294,7 @@ const gpuOk = gpuAvailable();
276294 const stateInit : StateInit & { special ?: { tick : boolean ; tock : boolean } } = {
277295 code : codeCell ,
278296 } ;
279- if ( init . fixedPrefixLength && init . fixedPrefixLength > 0 ) {
297+ if ( init . fixedPrefixLength !== undefined && init . fixedPrefixLength !== null ) {
280298 stateInit . splitDepth = init . fixedPrefixLength ;
281299 }
282300 if ( init . special ) {
0 commit comments