@@ -3775,6 +3775,245 @@ final class SwiftDriverTests: XCTestCase {
37753775 try checkSupplementaryOutputFileMap ( format: " bitstream " , . bitstreamOptimizationRecord)
37763776 }
37773777
3778+ func testOptimizationRecordPathUserProvidedPath( ) throws {
3779+
3780+ do {
3781+ var driver = try Driver ( args: [
3782+ " swiftc " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/test.opt.yaml " ,
3783+ " -c " , " test.swift "
3784+ ] )
3785+ let plannedJobs = try driver. planBuild ( )
3786+ let compileJob = try XCTUnwrap ( plannedJobs. first { $0. kind == . compile } )
3787+
3788+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/test.opt.yaml " ) ) ) ) )
3789+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) )
3790+ }
3791+
3792+ // Test primary file mode with multiple files and explicit path
3793+ do {
3794+ var driver = try Driver ( args: [
3795+ " swiftc " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/primary.opt.yaml " ,
3796+ " -c " , " file1.swift " , " file2.swift "
3797+ ] )
3798+ let plannedJobs = try driver. planBuild ( )
3799+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3800+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3801+
3802+ for compileJob in compileJobs {
3803+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3804+ " Each compile job should have -save-optimization-record-path flag " )
3805+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/primary.opt.yaml " ) ) ) ) ,
3806+ " Each compile job should have the user-provided path " )
3807+ }
3808+ }
3809+
3810+ do {
3811+ var driver = try Driver ( args: [
3812+ " swiftc " , " -wmo " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/wmo.opt.yaml " ,
3813+ " -c " , " test.swift "
3814+ ] )
3815+ let plannedJobs = try driver. planBuild ( )
3816+ let compileJob = try XCTUnwrap ( plannedJobs. first { $0. kind == . compile } )
3817+
3818+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/wmo.opt.yaml " ) ) ) ) )
3819+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) )
3820+ }
3821+
3822+ // Test multithreaded WMO with multiple optimization record paths
3823+ do {
3824+ var driver = try Driver ( args: [
3825+ " swiftc " , " -wmo " , " -num-threads " , " 4 " , " -save-optimization-record " ,
3826+ " -save-optimization-record-path " , " /tmp/mt1.opt.yaml " ,
3827+ " -save-optimization-record-path " , " /tmp/mt2.opt.yaml " ,
3828+ " -c " , " test1.swift " , " test2.swift "
3829+ ] )
3830+ let plannedJobs = try driver. planBuild ( )
3831+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3832+
3833+ XCTAssertGreaterThanOrEqual ( compileJobs. count, 1 , " Should have at least one compile job " )
3834+
3835+ var foundPaths : Set < String > = [ ]
3836+ for compileJob in compileJobs {
3837+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3838+ " Each compile job should have -save-optimization-record-path flag " )
3839+
3840+ if compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/mt1.opt.yaml " ) ) ) ) {
3841+ foundPaths. insert ( " /tmp/mt1.opt.yaml " )
3842+ }
3843+ if compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/mt2.opt.yaml " ) ) ) ) {
3844+ foundPaths. insert ( " /tmp/mt2.opt.yaml " )
3845+ }
3846+ }
3847+
3848+ XCTAssertGreaterThanOrEqual ( foundPaths. count, 1 ,
3849+ " At least one of the provided optimization record paths should be used " )
3850+ }
3851+ }
3852+
3853+ func testOptimizationRecordWithOutputFileMap( ) throws {
3854+ try withTemporaryDirectory { path in
3855+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3856+ let file1 = path. appending ( component: " file1.swift " )
3857+ let file2 = path. appending ( component: " file2.swift " )
3858+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3859+ let optRecord2 = path. appending ( component: " file2.opt.yaml " )
3860+
3861+ try localFileSystem. writeFileContents ( outputFileMap) {
3862+ $0. send ( """
3863+ {
3864+ " \( file1. pathString) " : {
3865+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3866+ " yaml-opt-record " : " \( optRecord1. pathString) "
3867+ },
3868+ " \( file2. pathString) " : {
3869+ " object " : " \( path. appending ( component: " file2.o " ) . pathString) " ,
3870+ " yaml-opt-record " : " \( optRecord2. pathString) "
3871+ }
3872+ }
3873+ """ )
3874+ }
3875+
3876+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3877+ try localFileSystem. writeFileContents ( file2) { $0. send ( " func bar() {} " ) }
3878+
3879+ // Test primary file mode with output file map containing optimization record entries
3880+ var driver = try Driver ( args: [
3881+ " swiftc " , " -save-optimization-record " ,
3882+ " -output-file-map " , outputFileMap. pathString,
3883+ " -c " , file1. pathString, file2. pathString
3884+ ] )
3885+ let plannedJobs = try driver. planBuild ( )
3886+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3887+
3888+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3889+
3890+ for (index, compileJob) in compileJobs. enumerated ( ) {
3891+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3892+ " Compile job \( index) should have -save-optimization-record-path flag " )
3893+
3894+ if let primaryFileIndex = compileJob. commandLine. firstIndex ( of: . flag( " -primary-file " ) ) ,
3895+ primaryFileIndex + 1 < compileJob. commandLine. count {
3896+ let primaryFile = compileJob. commandLine [ primaryFileIndex + 1 ]
3897+
3898+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
3899+ optRecordIndex + 1 < compileJob. commandLine. count {
3900+ let optRecordPath = compileJob. commandLine [ optRecordIndex + 1 ]
3901+
3902+ if case . path( let primaryPath) = primaryFile, case . path( let optPath) = optRecordPath {
3903+ if primaryPath == . absolute( file1) {
3904+ XCTAssertEqual ( optPath, . absolute( optRecord1) ,
3905+ " Compile job with file1.swift as primary should use file1.opt.yaml from output file map " )
3906+ } else if primaryPath == . absolute( file2) {
3907+ XCTAssertEqual ( optPath, . absolute( optRecord2) ,
3908+ " Compile job with file2.swift as primary should use file2.opt.yaml from output file map " )
3909+ }
3910+ }
3911+ }
3912+ }
3913+ }
3914+ }
3915+ }
3916+
3917+ func testOptimizationRecordConflictingOptions( ) throws {
3918+ try withTemporaryDirectory { path in
3919+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3920+ let file1 = path. appending ( component: " file1.swift " )
3921+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3922+ let explicitPath = path. appending ( component: " explicit.opt.yaml " )
3923+
3924+ try localFileSystem. writeFileContents ( outputFileMap) {
3925+ $0. send ( """
3926+ {
3927+ " \( file1. pathString) " : {
3928+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3929+ " yaml-opt-record " : " \( optRecord1. pathString) "
3930+ }
3931+ }
3932+ """ )
3933+ }
3934+
3935+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3936+
3937+ // Test that providing both -save-optimization-record-path and file map entry produces a warning
3938+ try assertDriverDiagnostics ( args: [
3939+ " swiftc " , " -save-optimization-record " ,
3940+ " -save-optimization-record-path " , explicitPath. pathString,
3941+ " -output-file-map " , outputFileMap. pathString,
3942+ " -c " , file1. pathString
3943+ ] ) {
3944+ _ = try ? $0. planBuild ( )
3945+ $1. expect ( . warning( " ignoring -save-optimization-record-path because output file map contains optimization record entries " ) )
3946+ }
3947+ }
3948+ }
3949+
3950+ func testOptimizationRecordPartialFileMapCoverage( ) throws {
3951+ try withTemporaryDirectory { path in
3952+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3953+ let file1 = path. appending ( component: " file1.swift " )
3954+ let file2 = path. appending ( component: " file2.swift " )
3955+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3956+
3957+ try localFileSystem. writeFileContents ( outputFileMap) {
3958+ $0. send ( """
3959+ {
3960+ " \( file1. pathString) " : {
3961+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3962+ " yaml-opt-record " : " \( optRecord1. pathString) "
3963+ },
3964+ " \( file2. pathString) " : {
3965+ " object " : " \( path. appending ( component: " file2.o " ) . pathString) "
3966+ }
3967+ }
3968+ """ )
3969+ }
3970+
3971+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3972+ try localFileSystem. writeFileContents ( file2) { $0. send ( " func bar() {} " ) }
3973+
3974+ // Test primary file mode with partial file map coverage
3975+ var driver = try Driver ( args: [
3976+ " swiftc " , " -save-optimization-record " ,
3977+ " -output-file-map " , outputFileMap. pathString,
3978+ " -c " , file1. pathString, file2. pathString
3979+ ] )
3980+ let plannedJobs = try driver. planBuild ( )
3981+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3982+
3983+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3984+
3985+ // file1 should use the path from the file map, file2 should use a derived path
3986+ for compileJob in compileJobs {
3987+ if let primaryFileIndex = compileJob. commandLine. firstIndex ( of: . flag( " -primary-file " ) ) ,
3988+ primaryFileIndex + 1 < compileJob. commandLine. count {
3989+ let primaryFile = compileJob. commandLine [ primaryFileIndex + 1 ]
3990+
3991+ if case . path( let primaryPath) = primaryFile {
3992+ if primaryPath == . absolute( file1) {
3993+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3994+ " file1 compile job should have -save-optimization-record-path flag " )
3995+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
3996+ optRecordIndex + 1 < compileJob. commandLine. count,
3997+ case . path( let optPath) = compileJob. commandLine [ optRecordIndex + 1 ] {
3998+ XCTAssertEqual ( optPath, . absolute( optRecord1) ,
3999+ " file1 should use the optimization record path from the file map " )
4000+ }
4001+ } else if primaryPath == . absolute( file2) {
4002+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
4003+ " file2 compile job should have -save-optimization-record-path flag " )
4004+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
4005+ optRecordIndex + 1 < compileJob. commandLine. count,
4006+ case . path( let optPath) = compileJob. commandLine [ optRecordIndex + 1 ] {
4007+ XCTAssertNotEqual ( optPath, . absolute( optRecord1) ,
4008+ " file2 should not use file1's optimization record path " )
4009+ }
4010+ }
4011+ }
4012+ }
4013+ }
4014+ }
4015+ }
4016+
37784017 func testUpdateCode( ) throws {
37794018 do {
37804019 var driver = try Driver ( args: [
0 commit comments