@@ -535,6 +535,139 @@ const GLOBALLY_BANNED_EXTENSIONS: &[&str] = &[
535
535
"nis" ,
536
536
] ;
537
537
538
+ const GLOBAL_EXTENSIONS : & [ & str ] = & [
539
+ "_abc" ,
540
+ "_ast" ,
541
+ "_asyncio" ,
542
+ "_bisect" ,
543
+ "_blake2" ,
544
+ "_bz2" ,
545
+ "_codecs" ,
546
+ "_codecs_cn" ,
547
+ "_codecs_hk" ,
548
+ "_codecs_iso2022" ,
549
+ "_codecs_jp" ,
550
+ "_codecs_kr" ,
551
+ "_codecs_tw" ,
552
+ "_collections" ,
553
+ "_contextvars" ,
554
+ "_csv" ,
555
+ "_ctypes" ,
556
+ "_datetime" ,
557
+ "_decimal" ,
558
+ "_elementtree" ,
559
+ "_functools" ,
560
+ "_hashlib" ,
561
+ "_heapq" ,
562
+ "_imp" ,
563
+ "_io" ,
564
+ "_json" ,
565
+ "_locale" ,
566
+ "_lsprof" ,
567
+ "_lzma" ,
568
+ "_md5" ,
569
+ "_multibytecodec" ,
570
+ "_multiprocessing" ,
571
+ "_opcode" ,
572
+ "_operator" ,
573
+ "_pickle" ,
574
+ "_queue" ,
575
+ "_random" ,
576
+ "_sha1" ,
577
+ "_sha256" ,
578
+ "_sha3" ,
579
+ "_sha512" ,
580
+ "_signal" ,
581
+ "_socket" ,
582
+ "_sqlite3" ,
583
+ "_sre" ,
584
+ "_ssl" ,
585
+ "_stat" ,
586
+ "_statistics" ,
587
+ "_string" ,
588
+ "_struct" ,
589
+ "_symtable" ,
590
+ "_thread" ,
591
+ "_tkinter" ,
592
+ "_tracemalloc" ,
593
+ "_warnings" ,
594
+ "_weakref" ,
595
+ "array" ,
596
+ "atexit" ,
597
+ "audioop" ,
598
+ "binascii" ,
599
+ "builtins" ,
600
+ "cmath" ,
601
+ "errno" ,
602
+ "faulthandler" ,
603
+ "gc" ,
604
+ "itertools" ,
605
+ "marshal" ,
606
+ "math" ,
607
+ "mmap" ,
608
+ "pyexpat" ,
609
+ "select" ,
610
+ "sys" ,
611
+ "time" ,
612
+ "unicodedata" ,
613
+ "xxsubtype" ,
614
+ "zlib" ,
615
+ ] ;
616
+
617
+ // _zoneinfo added in 3.9.
618
+ // parser removed in 3.10.
619
+
620
+ // We didn't build ctypes_test until 3.9.
621
+ // We didn't build some test extensions until 3.9.
622
+
623
+ const GLOBAL_EXTENSIONS_PYTHON_3_8 : & [ & str ] = & [ "parser" ] ;
624
+
625
+ const GLOBAL_EXTENSIONS_PYTHON_3_9 : & [ & str ] = & [
626
+ "_peg_parser" ,
627
+ "_uuid" ,
628
+ "_xxsubinterpreters" ,
629
+ "_zoneinfo" ,
630
+ "parser" ,
631
+ ] ;
632
+
633
+ const GLOBAL_EXTENSIONS_PYTHON_3_10 : & [ & str ] = & [ "_uuid" , "_xxsubinterpreters" , "_zoneinfo" ] ;
634
+
635
+ const GLOBAL_EXTENSIONS_MACOS : & [ & str ] = & [ "_scproxy" ] ;
636
+
637
+ const GLOBAL_EXTENSIONS_POSIX : & [ & str ] = & [
638
+ "_crypt" ,
639
+ "_curses" ,
640
+ "_curses_panel" ,
641
+ "_dbm" ,
642
+ "_posixshmem" ,
643
+ "_posixsubprocess" ,
644
+ "_testinternalcapi" ,
645
+ "fcntl" ,
646
+ "grp" ,
647
+ "posix" ,
648
+ "pwd" ,
649
+ "readline" ,
650
+ "resource" ,
651
+ "syslog" ,
652
+ "termios" ,
653
+ ] ;
654
+
655
+ const GLOBAL_EXTENSIONS_LINUX : & [ & str ] = & [ "spwd" ] ;
656
+
657
+ const GLOBAL_EXTENSIONS_WINDOWS : & [ & str ] = & [
658
+ "_msi" ,
659
+ "_overlapped" ,
660
+ "_winapi" ,
661
+ "_xxsubinterpreters" ,
662
+ "msvcrt" ,
663
+ "nt" ,
664
+ "winreg" ,
665
+ "winsound" ,
666
+ ] ;
667
+
668
+ /// Extension modules not present in Windows static builds.
669
+ const GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC : & [ & str ] = & [ "_testinternalcapi" , "_tkinter" ] ;
670
+
538
671
const PYTHON_VERIFICATIONS : & str = include_str ! ( "verify_distribution.py" ) ;
539
672
540
673
fn allowed_dylibs_for_triple ( triple : & str ) -> Vec < MachOAllowedDylib > {
@@ -1109,6 +1242,103 @@ fn validate_possible_object_file(
1109
1242
Ok ( context)
1110
1243
}
1111
1244
1245
+ fn validate_extension_modules (
1246
+ python_major_minor : & str ,
1247
+ target_triple : & str ,
1248
+ static_crt : bool ,
1249
+ have_extensions : & BTreeSet < & str > ,
1250
+ ) -> Result < Vec < String > > {
1251
+ let mut errors = vec ! [ ] ;
1252
+
1253
+ let is_macos = target_triple. contains ( "-apple-darwin" ) ;
1254
+ let is_linux = target_triple. contains ( "-unknown-linux-" ) ;
1255
+ let is_windows = target_triple. contains ( "-pc-windows-" ) ;
1256
+ let is_linux_musl = target_triple. contains ( "-unknown-linux-musl" ) ;
1257
+
1258
+ let mut wanted = BTreeSet :: from_iter ( GLOBAL_EXTENSIONS . iter ( ) . map ( |x| * x) ) ;
1259
+
1260
+ match python_major_minor {
1261
+ "3.8" => {
1262
+ wanted. extend ( GLOBAL_EXTENSIONS_PYTHON_3_8 ) ;
1263
+ }
1264
+ "3.9" => {
1265
+ wanted. extend ( GLOBAL_EXTENSIONS_PYTHON_3_9 ) ;
1266
+ }
1267
+ "3.10" => {
1268
+ wanted. extend ( GLOBAL_EXTENSIONS_PYTHON_3_10 ) ;
1269
+ }
1270
+ _ => {
1271
+ panic ! ( "unhandled Python version: {}" , python_major_minor) ;
1272
+ }
1273
+ }
1274
+
1275
+ if is_macos {
1276
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX ) ;
1277
+ wanted. extend ( GLOBAL_EXTENSIONS_MACOS ) ;
1278
+ }
1279
+
1280
+ if is_windows {
1281
+ wanted. extend ( GLOBAL_EXTENSIONS_WINDOWS ) ;
1282
+
1283
+ if static_crt {
1284
+ for x in GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC {
1285
+ wanted. remove ( * x) ;
1286
+ }
1287
+ }
1288
+ }
1289
+
1290
+ if is_linux {
1291
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX ) ;
1292
+ wanted. extend ( GLOBAL_EXTENSIONS_LINUX ) ;
1293
+
1294
+ if !is_linux_musl {
1295
+ wanted. insert ( "ossaudiodev" ) ;
1296
+ }
1297
+ }
1298
+
1299
+ if ( is_linux || is_macos) && matches ! ( python_major_minor, "3.9" | "3.10" ) {
1300
+ wanted. extend ( [
1301
+ "_ctypes_test" ,
1302
+ "_testbuffer" ,
1303
+ "_testimportmultiple" ,
1304
+ "_testmultiphase" ,
1305
+ "_xxtestfuzz" ,
1306
+ ] ) ;
1307
+ }
1308
+
1309
+ // _gdbm Linux only until 3.10, where it was dropped by us.
1310
+ if is_linux && matches ! ( python_major_minor, "3.8" | "3.9" ) {
1311
+ // But it isn't present on i686 due to build issues.
1312
+ if target_triple != "i686-unknown-linux-gnu" {
1313
+ wanted. insert ( "_gdbm" ) ;
1314
+ }
1315
+ }
1316
+
1317
+ // _uuid is POSIX only on 3.8. On 3.9, it is global.
1318
+ if python_major_minor == "3.8" {
1319
+ if is_linux || is_macos {
1320
+ wanted. insert ( "_uuid" ) ;
1321
+ }
1322
+ } else {
1323
+ wanted. insert ( "_uuid" ) ;
1324
+ }
1325
+
1326
+ // _ctypes_test was only added to some cross builds on 3.8.
1327
+ if python_major_minor == "3.8" && target_triple == "aarch64-unknown-linux-gnu" {
1328
+ wanted. insert ( "_ctypes_test" ) ;
1329
+ }
1330
+
1331
+ for extra in have_extensions. difference ( & wanted) {
1332
+ errors. push ( format ! ( "extra/unknown extension module: {}" , extra) ) ;
1333
+ }
1334
+
1335
+ for missing in wanted. difference ( have_extensions) {
1336
+ errors. push ( format ! ( "missing extension module: {}" , missing) ) ;
1337
+ }
1338
+
1339
+ Ok ( errors)
1340
+ }
1341
+
1112
1342
fn validate_json ( json : & PythonJsonMain , triple : & str , is_debug : bool ) -> Result < Vec < String > > {
1113
1343
let mut errors = vec ! [ ] ;
1114
1344
@@ -1163,6 +1393,23 @@ fn validate_json(json: &PythonJsonMain, triple: &str, is_debug: bool) -> Result<
1163
1393
}
1164
1394
}
1165
1395
1396
+ let have_extensions = json
1397
+ . build_info
1398
+ . extensions
1399
+ . keys ( )
1400
+ . map ( |x| x. as_str ( ) )
1401
+ . collect :: < BTreeSet < _ > > ( ) ;
1402
+
1403
+ errors. extend (
1404
+ validate_extension_modules (
1405
+ & json. python_major_minor_version ,
1406
+ triple,
1407
+ json. crt_features . contains ( & "static" . to_string ( ) ) ,
1408
+ & have_extensions,
1409
+ ) ?
1410
+ . into_iter ( ) ,
1411
+ ) ;
1412
+
1166
1413
Ok ( errors)
1167
1414
}
1168
1415
0 commit comments