7
7
from testutils import (
8
8
simplecpp ,
9
9
format_include_path_arg ,
10
+ format_isystem_path_arg ,
10
11
format_framework_path_arg ,
11
12
format_iframework_path_arg ,
12
13
format_include ,
@@ -346,15 +347,16 @@ def test_framework_lookup(record_property, tmpdir, is_sys, is_iframework, is_pri
346
347
"order,expected" ,
347
348
[
348
349
# Note:
349
- # - `I1` / `F1` / `IFW1` point to distinct directories and contain `Component_1.h` (a decoy).
350
- # - `I` / `F` / `IFW` point to directories that contain `Component.h`, which the
350
+ # - `I1` / `ISYS1` / ` F1` / `IFW1` point to distinct directories and contain `Component_1.h` (a decoy).
351
+ # - `I` / `ISYS` / ` F` / `IFW` point to directories that contain `Component.h`, which the
351
352
# translation unit (TU) includes via `#include "MyKit/Component.h"`.
352
353
#
353
- # This makes the winning flag (-I, -F, or -iframework) uniquely identifiable
354
+ # This makes the winning flag (-I, -isystem, - F, or -iframework) uniquely identifiable
354
355
# in the preprocessor `#line` output.
355
356
356
357
# Sanity checks
357
358
(("I" ,), "I" ),
359
+ (("ISYS" ,), "ISYS" ),
358
360
(("F" ,), "F" ),
359
361
(("IFW" ,), "IFW" ),
360
362
@@ -365,6 +367,13 @@ def test_framework_lookup(record_property, tmpdir, is_sys, is_iframework, is_pri
365
367
(("I1" , "I" , "I1" ), "I" ),
366
368
(("I" , "I1" , "I" ), "I" ),
367
369
370
+ # System includes (-isystem)
371
+ (("ISYS1" , "ISYS" ), "ISYS" ),
372
+ (("ISYS" , "ISYS1" ), "ISYS" ),
373
+ # System includes (-isystem) duplicates
374
+ (("ISYS1" , "ISYS" , "ISYS1" ), "ISYS" ),
375
+ (("ISYS" , "ISYS1" , "ISYS" ), "ISYS" ),
376
+
368
377
# Framework (-F)
369
378
(("F1" , "F" ), "F" ),
370
379
(("F" , "F1" ), "F" ),
@@ -385,6 +394,16 @@ def test_framework_lookup(record_property, tmpdir, is_sys, is_iframework, is_pri
385
394
(("F" , "I" ), "F" ),
386
395
(("F1" , "F" , "I" ), "F" ),
387
396
397
+ # -I and -F takes precedence over -isystem
398
+ (("I" , "ISYS" ), "I" ),
399
+ (("F" , "ISYS" ), "F" ),
400
+ (("ISYS" , "F" ), "F" ),
401
+ (("ISYS" , "I" , "F" ), "I" ),
402
+ (("ISYS" , "I1" , "F1" , "I" , "F" ), "I" ),
403
+ (("ISYS" , "I" ), "I" ),
404
+ (("ISYS" , "F" , "I" ), "F" ),
405
+ (("ISYS" , "F1" , "I1" , "F" , "I" ), "F" ),
406
+
388
407
# -I and -F beat system framework (-iframework)
389
408
(("I" , "IFW" ), "I" ),
390
409
(("F" , "IFW" ), "F" ),
@@ -394,16 +413,24 @@ def test_framework_lookup(record_property, tmpdir, is_sys, is_iframework, is_pri
394
413
(("IFW" , "I" ), "I" ),
395
414
(("IFW" , "F" , "I" ), "F" ),
396
415
(("IFW" , "F1" , "I1" , "F" , "I" ), "F" ),
416
+
417
+ # system include (-isystem) beats system framework (-iframework)
418
+ (("ISYS" , "IFW" ), "ISYS" ),
419
+ (("IFW" , "ISYS" ), "ISYS" ),
420
+ (("IFW1" , "ISYS1" , "IFW" , "ISYS" ), "ISYS" ),
421
+ (("I1" , "F1" , "IFW1" , "ISYS1" , "IFW" , "ISYS" ), "ISYS" ),
397
422
],
398
423
)
399
424
def test_searchpath_order (record_property , tmpdir , is_sys , order , expected ):
400
425
"""
401
- Validate include resolution order across -I (user include), -F (user framework),
402
- and -iframework (system framework) using a minimal file layout, asserting which
403
- physical header path appears in the preprocessor #line output.
426
+ Validate include resolution order across -I (user include),
427
+ -isystem (system include), -F (user framework), and
428
+ -iframework (system framework) using a minimal file layout,
429
+ asserting which physical header path appears in the preprocessor #line output.
404
430
405
- The test constructs three parallel trees (two entries per kind):
431
+ The test constructs four parallel trees (two entries per kind):
406
432
- inc{,_1}/MyKit/Component{,_1}.h # for -I
433
+ - isys{,_1}/MyKit/Component{,_1}.h # for -isystem
407
434
- Fw{,_1}/MyKit.framework/Headers/Component{,_1}.h # for -F
408
435
- SysFw{,_1}/MyKit.framework/Headers/Component{,_1}.h # for -iframework
409
436
@@ -418,7 +445,7 @@ def test_searchpath_order(record_property, tmpdir, is_sys, order, expected):
418
445
"""
419
446
420
447
# Create two include dirs, two user framework dirs, and two system framework dirs
421
- inc_dirs , fw_dirs , sysfw_dirs = [], [], []
448
+ inc_dirs , isys_dirs , fw_dirs , sysfw_dirs = [], [], [], []
422
449
423
450
def _suffix (idx : int ) -> str :
424
451
return f"_{ idx } " if idx > 0 else ""
@@ -429,6 +456,11 @@ def _suffix(idx: int) -> str:
429
456
__test_create_header (inc_dir , hdr_relpath = f"MyKit/Component{ _suffix (idx )} .h" )
430
457
inc_dirs .append (inc_dir )
431
458
459
+ # -isystem paths (system includes)
460
+ isys_dir = os .path .join (tmpdir , f"isys{ _suffix (idx )} " )
461
+ __test_create_header (isys_dir , hdr_relpath = f"MyKit/Component{ _suffix (idx )} .h" )
462
+ isys_dirs .append (isys_dir )
463
+
432
464
# -F paths (user frameworks)
433
465
fw_dir = os .path .join (tmpdir , f"Fw{ _suffix (idx )} " )
434
466
__test_create_framework (fw_dir , "MyKit" , f"Component{ _suffix (idx )} .h" )
@@ -443,15 +475,17 @@ def _suffix(idx: int) -> str:
443
475
test_file = __test_create_source (tmpdir , "MyKit/Component.h" , is_include_sys = is_sys )
444
476
445
477
def idx_from_flag (prefix : str , flag : str ) -> int :
446
- """Extract numeric suffix from tokens like 'I1', 'F1', 'IFW1'.
447
- Returns 0 when no suffix is present (e.g., 'I', 'F', 'IFW')."""
478
+ """Extract numeric suffix from tokens like 'I1', 'ISYS1', ' F1', 'IFW1'.
479
+ Returns 0 when no suffix is present (e.g., 'I', 'ISYS', ' F', 'IFW')."""
448
480
return int (flag [len (prefix ):]) if len (flag ) > len (prefix ) else 0
449
481
450
482
# Build argv in the exact order requested by `order`
451
483
args = []
452
484
for flag in order :
453
485
if flag in ["I" , "I1" ]:
454
486
args .append (format_include_path_arg (inc_dirs [idx_from_flag ("I" , flag )]))
487
+ elif flag in ["ISYS" , "ISYS1" ]:
488
+ args .append (format_isystem_path_arg (isys_dirs [idx_from_flag ("ISYS" , flag )]))
455
489
elif flag in ["F" , "F1" ]:
456
490
args .append (format_framework_path_arg (fw_dirs [idx_from_flag ("F" , flag )]))
457
491
elif flag in ["IFW" , "IFW1" ]:
@@ -469,14 +503,17 @@ def idx_from_flag(prefix: str, flag: str) -> int:
469
503
root = pathlib .PurePath (tmpdir ).as_posix ()
470
504
471
505
inc_paths = [f"{ root } /inc{ _suffix (idx )} /MyKit/Component{ _suffix (idx )} .h" for idx in range (2 )]
506
+ isys_paths = [f"{ root } /isys{ _suffix (idx )} /MyKit/Component{ _suffix (idx )} .h" for idx in range (2 )]
472
507
fw_paths = [f"{ root } /Fw{ _suffix (idx )} /MyKit.framework/Headers/Component{ _suffix (idx )} .h" for idx in range (2 )]
473
508
ifw_paths = [f"{ root } /SysFw{ _suffix (idx )} /MyKit.framework/Headers/Component{ _suffix (idx )} .h" for idx in range (2 )]
474
- all_candidate_paths = [* inc_paths , * fw_paths , * ifw_paths ]
509
+ all_candidate_paths = [* inc_paths , * isys_paths , * fw_paths , * ifw_paths ]
475
510
476
511
# Compute the single path we expect to appear
477
512
expected_path = None
478
513
if expected in ["I" , "I1" ]:
479
514
expected_path = inc_paths [idx_from_flag ("I" , expected )]
515
+ elif expected in ["ISYS" , "ISYS1" ]:
516
+ expected_path = isys_paths [idx_from_flag ("ISYS" , expected )]
480
517
elif expected in ["F" , "F1" ]:
481
518
expected_path = fw_paths [idx_from_flag ("F" , expected )]
482
519
elif expected in ["IFW" , "IFW1" ]:
0 commit comments