@@ -15,9 +15,10 @@ import {
1515 readdirSync ,
1616 rmSync ,
1717 statSync ,
18+ unlinkSync ,
1819 writeFileSync ,
1920} from 'fs' ;
20- import { mkdir , readFile , readdir , rm , stat , writeFile } from 'fs/promises' ;
21+ import { mkdir , readFile , readdir , rm , stat , unlink , writeFile } from 'fs/promises' ;
2122import { dirname , isAbsolute , join , parse , resolve } from 'path' ;
2223import { pipeline } from 'stream/promises' ;
2324
@@ -349,3 +350,110 @@ export function enforceZipSizeLimitSync(zipPath: string): number {
349350 }
350351 return size ;
351352}
353+
354+ /**
355+ * Generates a Linux-compatible shell script for a Python console entry point.
356+ * This is needed when packaging on Windows for Linux targets, as uv generates
357+ * .exe files based on the host OS rather than the target platform.
358+ */
359+ function generateLinuxConsoleScript ( modulePath : string , funcName : string ) : string {
360+ return `#!/usr/bin/env python3
361+ # -*- coding: utf-8 -*-
362+ import re
363+ import sys
364+ from ${ modulePath } import ${ funcName }
365+ if __name__ == '__main__':
366+ sys.argv[0] = re.sub(r'(-script\\.pyw|\\.exe)?$', '', sys.argv[0])
367+ sys.exit(${ funcName } ())
368+ ` ;
369+ }
370+
371+ /**
372+ * Known console script entry points that need to be converted from Windows .exe
373+ * to Linux shell scripts when cross-compiling.
374+ * Format: { 'script-name': ['module.path', 'function_name'] }
375+ */
376+ const KNOWN_CONSOLE_SCRIPTS : Record < string , [ string , string ] > = {
377+ 'opentelemetry-instrument' : [ 'opentelemetry.instrumentation.auto_instrumentation' , 'run' ] ,
378+ 'opentelemetry-bootstrap' : [ 'opentelemetry.instrumentation.bootstrap' , 'run' ] ,
379+ } ;
380+
381+ /**
382+ * Converts Windows .exe console scripts to Linux-compatible shell scripts.
383+ * This is necessary when packaging Python dependencies on Windows for deployment
384+ * to Linux-based AWS runtimes.
385+ *
386+ * @param stagingDir The directory containing installed Python packages
387+ */
388+ export async function convertWindowsScriptsToLinux ( stagingDir : string ) : Promise < void > {
389+ if ( ! isWindows ) {
390+ return ; // Only needed when building on Windows
391+ }
392+
393+ const binDir = join ( stagingDir , 'bin' ) ;
394+ if ( ! ( await pathExists ( binDir ) ) ) {
395+ return ;
396+ }
397+
398+ const entries = await readdir ( binDir ) ;
399+
400+ for ( const entry of entries ) {
401+ if ( ! entry . endsWith ( '.exe' ) ) {
402+ continue ;
403+ }
404+
405+ const scriptName = entry . slice ( 0 , - 4 ) ; // Remove .exe extension
406+ const entryPoint = KNOWN_CONSOLE_SCRIPTS [ scriptName ] ;
407+
408+ if ( entryPoint ) {
409+ const [ modulePath , funcName ] = entryPoint ;
410+ const exePath = join ( binDir , entry ) ;
411+ const scriptPath = join ( binDir , scriptName ) ;
412+
413+ // Remove the Windows .exe file
414+ await unlink ( exePath ) ;
415+
416+ // Create Linux-compatible shell script
417+ const scriptContent = generateLinuxConsoleScript ( modulePath , funcName ) ;
418+ await writeFile ( scriptPath , scriptContent , { mode : 0o755 } ) ;
419+ }
420+ }
421+ }
422+
423+ /**
424+ * Synchronous version of convertWindowsScriptsToLinux.
425+ */
426+ export function convertWindowsScriptsToLinuxSync ( stagingDir : string ) : void {
427+ if ( ! isWindows ) {
428+ return ; // Only needed when building on Windows
429+ }
430+
431+ const binDir = join ( stagingDir , 'bin' ) ;
432+ if ( ! pathExistsSync ( binDir ) ) {
433+ return ;
434+ }
435+
436+ const entries = readdirSync ( binDir ) ;
437+
438+ for ( const entry of entries ) {
439+ if ( ! entry . endsWith ( '.exe' ) ) {
440+ continue ;
441+ }
442+
443+ const scriptName = entry . slice ( 0 , - 4 ) ; // Remove .exe extension
444+ const entryPoint = KNOWN_CONSOLE_SCRIPTS [ scriptName ] ;
445+
446+ if ( entryPoint ) {
447+ const [ modulePath , funcName ] = entryPoint ;
448+ const exePath = join ( binDir , entry ) ;
449+ const scriptPath = join ( binDir , scriptName ) ;
450+
451+ // Remove the Windows .exe file
452+ unlinkSync ( exePath ) ;
453+
454+ // Create Linux-compatible shell script
455+ const scriptContent = generateLinuxConsoleScript ( modulePath , funcName ) ;
456+ writeFileSync ( scriptPath , scriptContent , { mode : 0o755 } ) ;
457+ }
458+ }
459+ }
0 commit comments