From 404f6bac3c261d2970cac361a13eb9089f332145 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 14 May 2026 18:53:37 -0700 Subject: [PATCH] Swift: support PDB emission with Swift Swift supports CodeView/PDB for Windows (with active development ongoing to make it the default). It is currently usable but does not have the same fidelity as DWARF, but can be sufficient for many use cases. The user is able to control this via flags. Wire up the necessary support to allow `TARGET_PDB_FILE` to be used with Swift/Swift-only targets. --- Help/release/dev/swift-target-pdb-file.rst | 5 +++++ Modules/CMakeSwiftInformation.cmake | 8 ++++---- Modules/Platform/Windows-Apple-Swift.cmake | 2 ++ Source/cmNinjaTargetGenerator.cxx | 13 +++++++++--- Tests/RunCMake/Swift/RunCMakeTest.cmake | 20 +++++++++++++++++++ .../Swift/TargetPDBFile-build-stdout.txt | 4 ++++ .../RunCMake/Swift/TargetPDBFile-check.cmake | 9 +++++++++ Tests/RunCMake/Swift/TargetPDBFile.cmake | 12 +++++++++++ .../TargetPDBFileDwarf-build-check.cmake | 9 +++++++++ .../Swift/TargetPDBFileDwarf-build-stdout.txt | 10 ++++++++++ .../TargetPDBFileDwarf-install-check.cmake | 4 ++++ Tests/RunCMake/Swift/TargetPDBFileDwarf.cmake | 12 +++++++++++ 12 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/swift-target-pdb-file.rst create mode 100644 Tests/RunCMake/Swift/TargetPDBFile-build-stdout.txt create mode 100644 Tests/RunCMake/Swift/TargetPDBFile-check.cmake create mode 100644 Tests/RunCMake/Swift/TargetPDBFile.cmake create mode 100644 Tests/RunCMake/Swift/TargetPDBFileDwarf-build-check.cmake create mode 100644 Tests/RunCMake/Swift/TargetPDBFileDwarf-build-stdout.txt create mode 100644 Tests/RunCMake/Swift/TargetPDBFileDwarf-install-check.cmake create mode 100644 Tests/RunCMake/Swift/TargetPDBFileDwarf.cmake diff --git a/Help/release/dev/swift-target-pdb-file.rst b/Help/release/dev/swift-target-pdb-file.rst new file mode 100644 index 0000000000..823e76d26d --- /dev/null +++ b/Help/release/dev/swift-target-pdb-file.rst @@ -0,0 +1,5 @@ +swift-target-pdb-file +--------------------- + +* Swift targets on Windows now support the ``$`` + family of generator expressions. diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index 5743fa1fea..0cd8b77041 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -130,7 +130,7 @@ if(CMAKE_Swift_COMPILATION_MODE_DEFAULT) endif() if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY) - set(CMAKE_Swift_CREATE_SHARED_LIBRARY " ${CMAKE_Swift_PARALLEL_FLAGS} -emit-library ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} -o ") + set(CMAKE_Swift_CREATE_SHARED_LIBRARY " ${CMAKE_Swift_PARALLEL_FLAGS} -emit-library ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} -o ${CMAKE_Swift_PDB_LINKER_FLAGS} ") endif() if(NOT CMAKE_Swift_CREATE_SHARED_MODULE) @@ -138,7 +138,7 @@ if(CMAKE_Swift_COMPILATION_MODE_DEFAULT) endif() if(NOT CMAKE_Swift_LINK_EXECUTABLE) - set(CMAKE_Swift_LINK_EXECUTABLE " ${CMAKE_Swift_PARALLEL_FLAGS} -emit-executable -o ") + set(CMAKE_Swift_LINK_EXECUTABLE " ${CMAKE_Swift_PARALLEL_FLAGS} -emit-executable -o ${CMAKE_Swift_PDB_LINKER_FLAGS} ") endif() if(NOT CMAKE_Swift_CREATE_STATIC_LIBRARY) @@ -154,7 +154,7 @@ else() endif() if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY) - set(CMAKE_Swift_CREATE_SHARED_LIBRARY " -j ${CMAKE_Swift_NUM_THREADS} -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o -module-name -module-link-name -emit-module -emit-module-path -emit-dependencies ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} ") + set(CMAKE_Swift_CREATE_SHARED_LIBRARY " -j ${CMAKE_Swift_NUM_THREADS} -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o -module-name -module-link-name -emit-module -emit-module-path -emit-dependencies ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} ${CMAKE_Swift_PDB_LINKER_FLAGS} ") endif() if(NOT CMAKE_Swift_CREATE_SHARED_MODULE) @@ -162,7 +162,7 @@ else() endif() if(NOT CMAKE_Swift_LINK_EXECUTABLE) - set(CMAKE_Swift_LINK_EXECUTABLE " -j ${CMAKE_Swift_NUM_THREADS} -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o -emit-dependencies ") + set(CMAKE_Swift_LINK_EXECUTABLE " -j ${CMAKE_Swift_NUM_THREADS} -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o -emit-dependencies ${CMAKE_Swift_PDB_LINKER_FLAGS} ") endif() if(NOT CMAKE_Swift_LINK_EXECUTABLE_WITH_EXPORTS) diff --git a/Modules/Platform/Windows-Apple-Swift.cmake b/Modules/Platform/Windows-Apple-Swift.cmake index 3e34985f5f..56082b5def 100644 --- a/Modules/Platform/Windows-Apple-Swift.cmake +++ b/Modules/Platform/Windows-Apple-Swift.cmake @@ -1,4 +1,6 @@ set(CMAKE_Swift_IMPLIB_LINKER_FLAGS "-Xlinker -implib:") +set(CMAKE_Swift_PDB_LINKER_FLAGS "-Xlinker -pdb:") +set(CMAKE_Swift_LINKER_SUPPORTS_PDB ON) set(CMAKE_Swift_FLAGS_DEBUG_LINKER_FLAGS "-Xlinker -debug") set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_LINKER_FLAGS "-Xlinker -debug") diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index a07fe1cc5c..a8a7713888 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -580,9 +580,16 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable( cmNinjaVars& vars, std::string const& config) const { cmMakefile* mf = this->GetMakefile(); - if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || - mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || - mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) { + bool supportsPDB = mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || + mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || + mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID"); + if (!supportsPDB) { + std::string const linkLanguage = + this->GeneratorTarget->GetLinkerLanguage(config); + supportsPDB = + mf->IsOn(cmStrCat("CMAKE_", linkLanguage, "_LINKER_SUPPORTS_PDB")); + } + if (supportsPDB) { std::string pdbPath; std::string compilePdbPath = this->ComputeTargetCompilePDB(config); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || diff --git a/Tests/RunCMake/Swift/RunCMakeTest.cmake b/Tests/RunCMake/Swift/RunCMakeTest.cmake index a56d6bf2ea..d066a7a73f 100644 --- a/Tests/RunCMake/Swift/RunCMakeTest.cmake +++ b/Tests/RunCMake/Swift/RunCMakeTest.cmake @@ -199,6 +199,26 @@ if(RunCMake_GENERATOR MATCHES "Ninja") endif() endblock() + block() + if(CMAKE_SYSTEM_NAME MATCHES Windows) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TargetPDBFile-build) + run_cmake(TargetPDBFile) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(TargetPDBFile-build ${CMAKE_COMMAND} --build . -- -n -v) + endif() + endblock() + + block() + if(CMAKE_SYSTEM_NAME MATCHES Windows) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TargetPDBFileDwarf-build) + run_cmake(TargetPDBFileDwarf) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(TargetPDBFileDwarf-build ${CMAKE_COMMAND} --build . -- -v) + run_cmake_command(TargetPDBFileDwarf-install ${CMAKE_COMMAND} --install . + --prefix "${RunCMake_TEST_BINARY_DIR}/install") + endif() + endblock() + block() set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SwiftModuleNameHyphen-build) run_cmake(SwiftModuleNameHyphen) diff --git a/Tests/RunCMake/Swift/TargetPDBFile-build-stdout.txt b/Tests/RunCMake/Swift/TargetPDBFile-build-stdout.txt new file mode 100644 index 0000000000..6eef06fe13 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFile-build-stdout.txt @@ -0,0 +1,4 @@ +.*swiftc(\.exe)?"?[^ +]* -Xlinker -pdb:[^ +]*SwiftPDBCustom\.pdb[^ +]* diff --git a/Tests/RunCMake/Swift/TargetPDBFile-check.cmake b/Tests/RunCMake/Swift/TargetPDBFile-check.cmake new file mode 100644 index 0000000000..007c805500 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFile-check.cmake @@ -0,0 +1,9 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script) +if(NOT install_script MATCHES "SwiftPDBCustom\\.pdb") + string(APPEND RunCMake_TEST_FAILED + "Generated install script does not reference SwiftPDBCustom.pdb\n") +endif() +if(NOT install_script MATCHES "OPTIONAL") + string(APPEND RunCMake_TEST_FAILED + "Generated install script does not preserve OPTIONAL install\n") +endif() diff --git a/Tests/RunCMake/Swift/TargetPDBFile.cmake b/Tests/RunCMake/Swift/TargetPDBFile.cmake new file mode 100644 index 0000000000..b5b78227d8 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFile.cmake @@ -0,0 +1,12 @@ +cmake_policy(SET CMP0157 NEW) + +enable_language(Swift) + +add_executable(SwiftPDB E.swift) +set_property(TARGET SwiftPDB PROPERTY PDB_NAME SwiftPDBCustom) +set_property(TARGET SwiftPDB PROPERTY PDB_OUTPUT_DIRECTORY + "$<1:${CMAKE_CURRENT_BINARY_DIR}/pdb>") + +install(FILES "$" + DESTINATION bin + OPTIONAL) diff --git a/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-check.cmake b/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-check.cmake new file mode 100644 index 0000000000..88ef741a25 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-check.cmake @@ -0,0 +1,9 @@ +file(GLOB_RECURSE pdb_files LIST_DIRECTORIES false + "${RunCMake_TEST_BINARY_DIR}/*.pdb") +foreach(pdb_file IN LISTS pdb_files) + get_filename_component(pdb_name "${pdb_file}" NAME) + if(pdb_name STREQUAL "SwiftPDBDwarf.pdb") + string(APPEND RunCMake_TEST_FAILED + "DWARF link unexpectedly produced ${pdb_file}\n") + endif() +endforeach() diff --git a/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-stdout.txt b/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-stdout.txt new file mode 100644 index 0000000000..e86126f9f8 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFileDwarf-build-stdout.txt @@ -0,0 +1,10 @@ +.*swiftc(\.exe)?"?[^ +]* -g[^ +]* -debug-info-format=dwarf[^ +]* +.*swiftc(\.exe)?"?[^ +]* -Xlinker -debug:dwarf[^ +]* -use-ld=lld[^ +]* -Xlinker -pdb:[^ +]*SwiftPDBDwarf\.pdb[^ +]* diff --git a/Tests/RunCMake/Swift/TargetPDBFileDwarf-install-check.cmake b/Tests/RunCMake/Swift/TargetPDBFileDwarf-install-check.cmake new file mode 100644 index 0000000000..eef58f8c63 --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFileDwarf-install-check.cmake @@ -0,0 +1,4 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/install/bin/SwiftPDBDwarf.pdb") + string(APPEND RunCMake_TEST_FAILED + "OPTIONAL install unexpectedly copied SwiftPDBDwarf.pdb\n") +endif() diff --git a/Tests/RunCMake/Swift/TargetPDBFileDwarf.cmake b/Tests/RunCMake/Swift/TargetPDBFileDwarf.cmake new file mode 100644 index 0000000000..64d301e28e --- /dev/null +++ b/Tests/RunCMake/Swift/TargetPDBFileDwarf.cmake @@ -0,0 +1,12 @@ +cmake_policy(SET CMP0157 NEW) + +enable_language(Swift) + +add_executable(SwiftPDBDwarf E.swift) +set_property(TARGET SwiftPDBDwarf PROPERTY LINKER_TYPE LLD) +target_compile_options(SwiftPDBDwarf PRIVATE -g -debug-info-format=dwarf) +target_link_options(SwiftPDBDwarf PRIVATE LINKER:-debug:dwarf) + +install(FILES "$" + DESTINATION bin + OPTIONAL)