PGI: Load pgort<ver>.dll from the VS native tools env; do not `install` it (#12581)
authorDaniel Podder <dpodder@gmail.com>
Thu, 14 Sep 2017 17:35:42 +0000 (10:35 -0700)
committerGitHub <noreply@github.com>
Thu, 14 Sep 2017 17:35:42 +0000 (10:35 -0700)
On Windows, PGO instrumented builds (build.cmd release <arch>
pgoinstrument) introduce a runtime dependency on pgort<ver>.dll for
instrumented binaries. This DLL is distributed alongside the C++
compiler, and is made available via the native tools environment that
ships with Visual Studio.

Previously, we were using cmake to find and "install" this binary
alongside the product when doing an instrumented build, so that the
resulting bin\Product drop is free of any added external dependencies.
However, this approach is fragile, and despite a best effort to make the
implementation work across multiple VS releases, it already broke with
VS 2017.

To fix support for pgoinstrument on VS 2017, and to harden the
implementation for future releases of VS, I'm removing the custom cmake
install logic for the pgort DLL. Instead, we fall back to the officially
supported method: load the correct (native tools) environment before
invoking any command that uses an instrumented binary. This happens in
one place in the build today--loading the JIT to crossgen
System.Private.CoreLib.dll.

Note that there's still an existing CLI/Setup bug that requires copying
the pgort DLL. We're now doing it from within build.cmd, which is not
nearly as fragile for this as cmake is. The workaround is also isolated,
so when the referenced issue is fixed, the workaround (as documented)
can simply be removed.

Fixes #12347.

build.cmd
pgosupport.cmake

index 70f62bc..c0c5cb7 100644 (file)
--- a/build.cmd
+++ b/build.cmd
@@ -540,6 +540,31 @@ set PATH=%PATH%;%WinDir%\Microsoft.Net\Framework64\V4.0.30319;%WinDir%\Microsoft
 if %__BuildNativeCoreLib% EQU 1 (
     echo %__MsgPrefix%Generating native image of System.Private.CoreLib for %__BuildOS%.%__BuildArch%.%__BuildType%
 
+    REM Need VS native tools environment for the **target** arch when running instrumented binaries
+    if %__PgoInstrument% EQU 1 (
+        set __VCExecArch=%__BuildArch%
+        if /i [%__BuildArch%] == [x64] set __VCExecArch=amd64
+        echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCExecArch!
+        call                                 "%__VCToolsRoot%\vcvarsall.bat" !__VCExecArch!
+        @if defined _echo @echo on
+        if NOT !errorlevel! == 0 (
+            echo %__MsgPrefix%Error: Failed to load native tools environment for !__VCExecArch!
+            goto CrossgenFailure
+        )
+
+        REM HACK: Workaround for [dotnet/coreclr#13970](https://github.com/dotnet/coreclr/issues/13970)
+        set __PgoRtPath=
+        for /f "tokens=*" %%f in ('where pgort*.dll') do (
+          if not defined __PgoRtPath set "__PgoRtPath=%%~f"
+        )
+        echo %__MsgPrefix%Copying "!__PgoRtPath!" into "%__BinDir%"
+        copy /y "!__PgoRtPath!" "%__BinDir%" || (
+          echo %__MsgPrefix%Error: copy failed
+          goto CrossgenFailure
+        )
+        REM End HACK
+    )
+
     set NEXTCMD="%__CrossgenExe%" %__IbcTuning% /Platform_Assemblies_Paths "%__BinDir%"\IL /out "%__BinDir%\System.Private.CoreLib.dll" "%__BinDir%\IL\System.Private.CoreLib.dll"
     echo %__MsgPrefix%!NEXTCMD!
     !NEXTCMD! > "%__CrossGenCoreLibLog%" 2>&1
index 9472866..96ff80a 100644 (file)
@@ -1,11 +1,3 @@
-function(clr_pgo_unknown_arch)
-    if (WIN32)
-        message(FATAL_ERROR "Only AMD64, ARM and I386 are supported for PGO")
-    else()
-        message(FATAL_ERROR "PGO not currently supported on the current platform")
-    endif()
-endfunction(clr_pgo_unknown_arch)
-
 # Adds Profile Guided Optimization (PGO) flags to the current target
 function(add_pgo TargetName)
     if(WIN32)
@@ -57,33 +49,3 @@ function(add_pgo TargetName)
         endif(EXISTS ${ProfilePath})
     endif(CLR_CMAKE_PGO_INSTRUMENT)
 endfunction(add_pgo)
-
-if(WIN32)
-  if(CLR_CMAKE_PGO_INSTRUMENT)
-    # Instrumented PGO binaries on Windows introduce an additional runtime dependency, pgort<ver>.dll.
-    # Make sure we copy it next to the installed product to make it easier to redistribute the package.
-
-    string(SUBSTRING ${CMAKE_VS_PLATFORM_TOOLSET} 1 -1 VS_PLATFORM_VERSION_NUMBER)
-    set(PGORT_FILENAME "pgort${VS_PLATFORM_VERSION_NUMBER}.dll")
-
-    get_filename_component(PATH_CXX_ROOTDIR ${CMAKE_CXX_COMPILER} DIRECTORY)
-
-    if(CLR_CMAKE_PLATFORM_ARCH_I386)
-      set(PATH_VS_PGORT_DLL "${PATH_CXX_ROOTDIR}/${PGORT_FILENAME}")
-    elseif(CLR_CMAKE_PLATFORM_ARCH_AMD64)
-      set(PATH_VS_PGORT_DLL "${PATH_CXX_ROOTDIR}/../amd64/${PGORT_FILENAME}")
-    elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
-      set(PATH_VS_PGORT_DLL "${PATH_CXX_ROOTDIR}/../arm/${PGORT_FILENAME}")
-    else()
-      clr_pgo_unknown_arch()
-    endif()
-
-    if (EXISTS ${PATH_VS_PGORT_DLL})
-      message(STATUS "Found PGO runtime: ${PATH_VS_PGORT_DLL}")
-      install(PROGRAMS ${PATH_VS_PGORT_DLL} DESTINATION .)
-    else()
-      message(FATAL_ERROR "file not found: ${PATH_VS_PGORT_DLL}")
-    endif()
-
-  endif(CLR_CMAKE_PGO_INSTRUMENT)
-endif(WIN32)