https://github.com/python/cpython/commit/d8a1cf469e40b538a84e583ac1d5d34418ed9a6a
commit: d8a1cf469e40b538a84e583ac1d5d34418ed9a6a
branch: main
author: Chris Eibl <138194463+chris-e...@users.noreply.github.com>
committer: zooba <steve.do...@microsoft.com>
date: 2025-03-04T19:29:03Z
summary:

gh-130090: Support PGO for clang-cl on Windows (GH-129907)

files:
A Misc/NEWS.d/next/Build/2025-02-13-19-21-41.gh-issue-130090.3ngJaV.rst
A PCbuild/pyproject-clangcl.props
M Misc/ACKS
M PCbuild/_freeze_module.vcxproj
M PCbuild/pyproject.props
M PCbuild/pythoncore.vcxproj
M PCbuild/readme.txt

diff --git a/Misc/ACKS b/Misc/ACKS
index 2a68b69f161041..7bf1d9c99ea24c 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -504,6 +504,7 @@ Grant Edwards
 Vlad Efanov
 Zvi Effron
 John Ehresman
+Chris Eibl
 Tal Einat
 Eric Eisner
 Andrew Eland
diff --git 
a/Misc/NEWS.d/next/Build/2025-02-13-19-21-41.gh-issue-130090.3ngJaV.rst 
b/Misc/NEWS.d/next/Build/2025-02-13-19-21-41.gh-issue-130090.3ngJaV.rst
new file mode 100644
index 00000000000000..9ee7d5cdd8ae8a
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2025-02-13-19-21-41.gh-issue-130090.3ngJaV.rst
@@ -0,0 +1,2 @@
+Building with ``PlatformToolset=ClangCL`` on Windows now supports PGO
+(profile guided optimization). Patch by Chris Eibl with invaluable support 
from Steve Dover.
diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj
index e12876114459bc..44292ee32b19fa 100644
--- a/PCbuild/_freeze_module.vcxproj
+++ b/PCbuild/_freeze_module.vcxproj
@@ -92,6 +92,7 @@
       
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <Optimization>Disabled</Optimization>
       <WholeProgramOptimization>false</WholeProgramOptimization>
+      <AdditionalOptions Condition="$(PlatformToolset) == 
'ClangCL'">%(AdditionalOptions) -fno-lto</AdditionalOptions>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
diff --git a/PCbuild/pyproject-clangcl.props b/PCbuild/pyproject-clangcl.props
new file mode 100644
index 00000000000000..30db6824f3caf5
--- /dev/null
+++ b/PCbuild/pyproject-clangcl.props
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
+  <PropertyGroup Label="Globals">
+    <__PyprojectClangCl_Props_Imported>true</__PyprojectClangCl_Props_Imported>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <!-- CLANG_PROFILE_PATH is configurable for "remote PGO builds"
+         For convenience, we also accept paths without trailing slashes.
+    -->
+    <CLANG_PROFILE_PATH Condition="'$(CLANG_PROFILE_PATH)' == 
''">$(OutDir)</CLANG_PROFILE_PATH>
+    <_CLANG_PROFILE_PATH>$(CLANG_PROFILE_PATH)</_CLANG_PROFILE_PATH>
+    <_CLANG_PROFILE_PATH 
Condition="!HasTrailingSlash($(_CLANG_PROFILE_PATH))">$(_CLANG_PROFILE_PATH)\</_CLANG_PROFILE_PATH>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <_profrawFiles Include="$(OutDir)instrumented\$(TargetName)_*.profraw" />
+  </ItemGroup>
+
+  <Target Name="EnsureClangProfileData" BeforeTargets="PrepareForBuild"
+          Condition="'$(SupportPGO)' and $(Configuration) == 'PGUpdate'">
+    <Error Text="PGO run did not succeed (no $(TargetName)_*.profraw files) 
and there is no data to merge"
+           Condition="$(RequireProfileData) == 'true' and @(_profrawFiles) == 
''" />
+  </Target>
+
+  <Target Name="MergeClangProfileData" BeforeTargets="PrepareForBuild"
+          Condition="'$(SupportPGO)' and $(Configuration) == 'PGUpdate'"
+          Inputs="@(_profrawFiles)"
+          Outputs="$(OutDir)instrumented\profdata.profdata">
+    <Exec
+      Command='"$(LLVMInstallDir)\bin\llvm-profdata.exe" merge 
-output="$(OutDir)instrumented\profdata.profdata" 
"$(OutDir)instrumented\*_*.profraw"' />
+  </Target>
+
+  <Target Name="CleanClangProfileData" BeforeTargets="Clean">
+    <Delete Files="@(_profrawFiles)" TreatErrorsAsWarnings="true" />
+    <Delete Files="$(OutDir)instrumented\profdata.profdata" 
TreatErrorsAsWarnings="true" />
+  </Target>
+
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalOptions>-Wno-deprecated-non-prototype -Wno-unused-label 
-Wno-pointer-sign -Wno-incompatible-pointer-types-discards-qualifiers 
-Wno-unused-function %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalOptions Condition="'$(Platform)' == 'Win32'">-m32 
%(AdditionalOptions)</AdditionalOptions>
+      <AdditionalOptions Condition="'$(Platform)' == 'x64'">-m64 
%(AdditionalOptions)</AdditionalOptions>
+      <AdditionalOptions Condition="$(Configuration) != 'Debug'">-flto 
%(AdditionalOptions)</AdditionalOptions>
+      <AdditionalOptions Condition="$(SupportPGO) and $(Configuration) == 
'PGInstrument'">-fprofile-instr-generate=$(_CLANG_PROFILE_PATH)$(TargetName)_%m.profraw
 %(AdditionalOptions)</AdditionalOptions>
+      <AdditionalOptions Condition="$(SupportPGO) and $(Configuration) == 
'PGUpdate'">-fprofile-instr-use=$(OutDir)instrumented\profdata.profdata 
-Wno-profile-instr-unprofiled %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+
+</Project>
diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props
index 17abfa85201a90..2681e2d42e8996 100644
--- a/PCbuild/pyproject.props
+++ b/PCbuild/pyproject.props
@@ -24,6 +24,9 @@
     <LinkIncremental Condition="$(Configuration) != 
'Debug'">false</LinkIncremental>
   </PropertyGroup>
 
+  <!-- We need the above overridden OutDir, so this must be imported after 
PropertyGroup -->
+  <Import Project="pyproject-clangcl.props" Condition="$(PlatformToolset) == 
'ClangCL' and $(__PyprojectClangCl_Props_Imported) != 'true'" />
+
   <PropertyGroup Condition="$(TargetExt) != ''">
     <TargetNameExt>$(TargetName)$(TargetExt)</TargetNameExt>
     <_TargetNameSep>$(TargetNameExt.LastIndexOf(`.`))</_TargetNameSep>
@@ -69,8 +72,6 @@
       <ControlFlowGuard Condition="$(EnableControlFlowGuard) != 
''">$(EnableControlFlowGuard)</ControlFlowGuard>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalOptions Condition="$(PlatformToolset) == 
'ClangCL'">-Wno-deprecated-non-prototype -Wno-unused-label -Wno-pointer-sign 
-Wno-incompatible-pointer-types-discards-qualifiers -Wno-unused-function 
%(AdditionalOptions)</AdditionalOptions>
-      <AdditionalOptions Condition="$(Configuration) != 'Debug' and 
$(PlatformToolset) == 'ClangCL'">-flto %(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions Condition="$(MSVCHasBrokenARM64Clamping) == 'true' 
and $(Platform) == 'ARM64'">-d2pattern-opt-disable:-932189325 
%(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions Condition="$(MSVCHasBrokenARM64SignExtension) == 
'true' and $(Platform) == 'ARM64'">-d2ssa-patterns-all- 
%(AdditionalOptions)</AdditionalOptions>
       <AdditionalOptions Condition="$(GenerateSourceDependencies) == 
'true'">/sourceDependencies "$(IntDir.Trim(`\`))" 
%(AdditionalOptions)</AdditionalOptions>
@@ -186,7 +187,7 @@ public override bool Execute() {
              Targets="CleanAll" />
   </Target>
 
-  <Target Name="CopyPGCFiles" BeforeTargets="PrepareForBuild" 
Condition="$(Configuration) == 'PGUpdate'">
+  <Target Name="CopyPGCFiles" BeforeTargets="PrepareForBuild" 
Condition="$(Configuration) == 'PGUpdate' and $(PlatformToolset) != 'ClangCL'">
     <ItemGroup>
       <_PGCFiles Include="$(OutDir)instrumented\$(TargetName)!*.pgc" />
       <_PGDFile Include="$(OutDir)instrumented\$(TargetName).pgd" />
@@ -194,7 +195,7 @@ public override bool Execute() {
     </ItemGroup>
     <Delete Files="@(_CopyFiles->'$(OutDir)%(Filename)%(Extension)')" />
     <Error Text="PGO run did not succeed (no $(TargetName)!*.pgc files) and 
there is no data to merge"
-           Condition="$(RequirePGCFiles) == 'true' and @(_PGCFiles) == ''" />
+           Condition="$(RequireProfileData) == 'true' and @(_PGCFiles) == ''" 
/>
     <Copy SourceFiles="@(_CopyFiles)"
           DestinationFolder="$(OutDir)"
           UseHardLinksIfPossible="true"
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 9ebf58ae8a9bc4..3b3c3972987db8 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -81,7 +81,7 @@
   </ImportGroup>
   <PropertyGroup>
     <KillPython>true</KillPython>
-    <RequirePGCFiles>true</RequirePGCFiles>
+    <RequireProfileData>true</RequireProfileData>
     <IncludeExternals Condition="$(IncludeExternals) == '' and 
Exists('$(zlibDir)\zlib.h')">true</IncludeExternals>
     <IncludeExternals Condition="$(IncludeExternals) == 
''">false</IncludeExternals>
   </PropertyGroup>
diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt
index 693fcee5f90ce2..33952d31681cbc 100644
--- a/PCbuild/readme.txt
+++ b/PCbuild/readme.txt
@@ -52,6 +52,45 @@ Release
     settings, though without PGO.
 
 
+Building Python using Clang/LLVM
+--------------------------------
+
+See https://learn.microsoft.com/cpp/build/clang-support-msbuild
+for how to install and use clang-cl bundled with Microsoft Visual Studio.
+You can use the IDE to switch to clang-cl for local development,
+but because this alters the *.vcxproj files, the recommended way is
+to use build.bat:
+
+build.bat "/p:PlatformToolset=ClangCL"
+
+All other build.bat options continue to work as with MSVC, so this
+will create a 64bit release binary.
+
+You can also use a specific version of clang-cl downloaded from
+https://github.com/llvm/llvm-project/releases, e.g.
+clang+llvm-18.1.8-x86_64-pc-windows-msvc.tar.xz.
+Given you have extracted that to <my-clang-dir>, you can use it like so
+build.bat --pgo "/p:PlatformToolset=ClangCL" "/p:LLVMInstallDir=<my-clang-dir> 
"/p:LLVMToolsVersion=18"
+
+Setting LLVMToolsVersion to the major version is enough, although you
+can be specific and use 18.1.8 in the above example, too.
+
+Use the --pgo option to build with PGO (Profile Guided Optimization).
+
+However, if you want to run the PGO task
+on a different host than the build host, you must pass
+"/p:CLANG_PROFILE_PATH=<relative-path-to-instrumented-dir-on-remote-host>"
+in the PGInstrument step to make sure the profile data is generated
+into the instrumented directory when running the PGO task.
+E.g., if you place the instrumented binaries into the folder
+"workdir/instrumented" and then run the PGO task using "workdir"
+as the current working directory, the usage is
+"/p:CLANG_PROFILE_PATH=instrumented"
+
+Like in the MSVC case, after fetching (or manually copying) the instrumented
+folder back into your build tree, you can continue with the PGUpdate
+step with no further parameters.
+
 Building Python using the build.bat script
 ----------------------------------------------
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to