Add support for symbol stripping (#70233)
authorAdeel Mujahid <3840695+am11@users.noreply.github.com>
Mon, 6 Jun 2022 07:21:39 +0000 (10:21 +0300)
committerGitHub <noreply@github.com>
Mon, 6 Jun 2022 07:21:39 +0000 (16:21 +0900)
eng/native/functions.cmake
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
src/coreclr/nativeaot/docs/optimizing.md

index d5a28fe..eaef0d6 100644 (file)
@@ -390,11 +390,12 @@ function(strip_symbols targetName outputFilename)
         message(FATAL_ERROR "strip not found")
       endif()
 
+      set(strip_command ${STRIP} -no_code_signature_warning -S ${strip_source_file})
+
+      # codesign release build
       string(TOLOWER "${CMAKE_BUILD_TYPE}" LOWERCASE_CMAKE_BUILD_TYPE)
       if (LOWERCASE_CMAKE_BUILD_TYPE STREQUAL release)
-        set(strip_command ${STRIP} -no_code_signature_warning -S ${strip_source_file} && codesign -f -s - ${strip_source_file})
-      else ()
-        set(strip_command)
+        set(strip_command ${strip_command} && codesign -f -s - ${strip_source_file})
       endif ()
 
       execute_process(
index 5ad1cf0..a597070 100644 (file)
   </Target>
 
   <Target Name="CopyNativeBinary" AfterTargets="Publish">
-    <!-- override apphost with binary we generated during native compilation -->
+    <!-- replace apphost with binary we generated during native compilation -->
     <Delete Files="$(PublishDir)\$(TargetName)$(NativeBinaryExt)" />
     <Copy SourceFiles="$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)" DestinationFolder="$(PublishDir)" />
-  </Target>
 
-  <Target Name="CopyNativePdb" Condition="'$(DebugType)' != 'None' and '$(TargetOS)' == 'windows' and '$(NativeLib)' != 'Static'" AfterTargets="Publish">
-    <!-- dotnet CLI produces managed debug symbols - substitute with those we generated during native compilation -->
+    <!-- dotnet CLI produces managed debug symbols, which we will delete and copy native symbols instead -->
     <Delete Files="$(PublishDir)\$(TargetName).pdb" />
-    <Copy SourceFiles="$(NativeOutputPath)$(TargetName).pdb" DestinationFolder="$(PublishDir)" />
+
+    <!-- replace native symbol file if it exists -->
+    <Delete Files="$(PublishDir)\$(TargetName)$(NativeBinaryExt)$(NativeSymbolExt)" />
+    <Copy SourceFiles="$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)$(NativeSymbolExt)" DestinationFolder="$(PublishDir)"
+      Condition="Exists('$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)$(NativeSymbolExt)')" />
   </Target>
 
 </Project>
index 19f4d86..b150bf6 100644 (file)
@@ -14,10 +14,13 @@ The .NET Foundation licenses this file to you under the MIT license.
 -->
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
-    <CppCompilerAndLinker Condition="'$(CppCompilerAndLinker)' == ''">clang</CppCompilerAndLinker>
+    <CustomToolchainSpecified Condition="'$(CppCompilerAndLinker)' != ''">true</CustomToolchainSpecified>
+    <CppCompilerAndLinker Condition="'$(CustomToolchainSpecified)' != 'true'">clang</CppCompilerAndLinker>
+    <CppCompilerAndLinkerAlternative Condition="'$(CustomToolchainSpecified)' != 'true' and '$(TargetOS)' != 'OSX'">gcc</CppCompilerAndLinkerAlternative>
     <CppCompiler>$(CppCompilerAndLinker)</CppCompiler>
     <CppLinker>$(CppCompilerAndLinker)</CppLinker>
     <CppLibCreator>ar</CppLibCreator>
+    <DsymUtilOptions Condition="'$(TargetOS)' == 'OSX'">--flat</DsymUtilOptions>
   </PropertyGroup>
 
   <Target Name="SetupOSSpecificProps" DependsOnTargets="$(IlcDynamicBuildPropertyDependencies)">
@@ -106,7 +109,42 @@ The .NET Foundation licenses this file to you under the MIT license.
     <Exec Command="command -v $(CppLinker)" IgnoreExitCode="true" StandardOutputImportance="Low">
       <Output TaskParameter="ExitCode" PropertyName="_WhereLinker" />
     </Exec>
-    <Error Condition="'$(_WhereLinker)' != '0' and '$(TargetOS)' == 'OSX'" Text="Platform linker ('$(CppLinker)') not found. Try installing Xcode to resolve the problem." />
-    <Error Condition="'$(_WhereLinker)' != '0' and '$(TargetOS)' != 'OSX'" Text="Platform linker ('$(CppLinker)') not found. Try installing $(CppLinker) or the appropriate package for your platform to resolve the problem." />
+
+    <Exec Command="command -v $(CppCompilerAndLinkerAlternative)" Condition="'$(CppCompilerAndLinkerAlternative)' != '' and '$(_WhereLinker)' != '0'" IgnoreExitCode="true" StandardOutputImportance="Low">
+      <Output TaskParameter="ExitCode" PropertyName="_WhereLinkerAlt" />
+    </Exec>
+
+    <PropertyGroup Condition="'$(CppCompilerAndLinkerAlternative)' != '' and '$(_WhereLinker)' != '0' and '$(_WhereLinkerAlt)' == '0'">
+      <CppCompilerAndLinker>$(CppCompilerAndLinkerAlternative)</CppCompilerAndLinker>
+      <CppCompiler>$(CppCompilerAndLinker)</CppCompiler>
+      <CppLinker>$(CppCompilerAndLinker)</CppLinker>
+      <_WhereLinker>0</_WhereLinker>
+    </PropertyGroup>
+
+    <Error Condition="'$(_WhereLinker)' != '0' and '$(TargetOS)' == 'OSX'" Text="Platform linker ('$(CppLinker)') not found in PATH. Try installing Xcode to resolve the problem." />
+    <Error Condition="'$(_WhereLinker)' != '0' and '$(CppCompilerAndLinkerAlternative)' != ''"
+      Text="Platform linker ('$(CppLinker)' or '$(CppCompilerAndLinkerAlternative)') not found in PATH. Try installing appropriate package for $(CppLinker) or $(CppCompilerAndLinkerAlternative) to resolve the problem." />
+    <Error Condition="'$(_WhereLinker)' != '0' and '$(CppCompilerAndLinkerAlternative)' == '' and '$(TargetOS)' != 'OSX'"
+      Text="Requested linker ('$(CppLinker)') not found in PATH." />
+
+    <Exec Command="command -v objcopy" IgnoreExitCode="true" StandardOutputImportance="Low" Condition="'$(TargetOS)' != 'OSX' and '$(StripSymbols)' == 'true'">
+      <Output TaskParameter="ExitCode" PropertyName="_WhereSymbolStripper" />
+    </Exec>
+    <Error Condition="'$(_WhereSymbolStripper)' != '0' and '$(StripSymbols)' == 'true' and '$(TargetOS)' != 'OSX'"
+      Text="Symbol stripping tool ('objcopy') not found in PATH. Make sure 'objcopy' is available in PATH" />
+
+    <Exec Command="command -v dsymutil &amp;&amp; command -v strip" IgnoreExitCode="true" StandardOutputImportance="Low" Condition="'$(TargetOS)' == 'OSX' and '$(StripSymbols)' == 'true'">
+      <Output TaskParameter="ExitCode" PropertyName="_WhereSymbolStripper" />
+    </Exec>
+    <Error Condition="'$(_WhereSymbolStripper)' != '0' and '$(StripSymbols)' == 'true' and '$(TargetOS)' != 'OSX'"
+      Text="Symbol stripping tools ('dsymutil' and 'strip') not found in PATH. Make sure 'dsymutil' and 'strip' are available in PATH" />
+
+    <Exec Command="dsymutil --help" IgnoreExitCode="true" StandardOutputImportance="Low" Condition="'$(TargetOS)' == 'OSX' and '$(StripSymbols)' == 'true'">
+      <Output TaskParameter="ExitCode" PropertyName="_DsymUtilOutput" />
+    </Exec>
+
+    <PropertyGroup Condition="'$(TargetOS)' == 'OSX' and '$(StripSymbols)' == 'true' and $(_DsymUtilOutput.Contains('--minimize'))">
+      <DsymUtilOptions>$(DsymUtilOptions) --minimize</DsymUtilOptions>
+    </PropertyGroup>
   </Target>
 </Project>
index ef10a3e..d5c08a7 100644 (file)
@@ -70,6 +70,10 @@ The .NET Foundation licenses this file to you under the MIT license.
     <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' == 'windows' and $(NativeLib) == 'Static'">.lib</NativeBinaryExt>
     <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' != 'windows' and $(NativeLib) == 'Static'">.a</NativeBinaryExt>
 
+    <NativeSymbolExt Condition="'$(TargetOS)' == 'OSX'">.dwarf</NativeSymbolExt>
+    <NativeSymbolExt Condition="'$(TargetOS)' == 'windows'">.pdb</NativeSymbolExt>
+    <NativeSymbolExt Condition="'$(TargetOS)' != 'OSX' and '$(TargetOS)' != 'windows'">.dbg</NativeSymbolExt>
+
     <ExportsFileExt Condition="'$(TargetOS)' == 'windows'">.def</ExportsFileExt>
     <ExportsFileExt Condition="'$(TargetOS)' != 'windows'">.exports</ExportsFileExt>
 
@@ -341,6 +345,16 @@ The .NET Foundation licenses this file to you under the MIT license.
     <Exec Command="$(CppLinker)  @&quot;$(NativeIntermediateOutputPath)link.rsp&quot;" Condition="'$(TargetOS)' == 'windows' and '$(NativeLib)' != 'Static'" />
     <WriteLinesToFile File="$(NativeIntermediateOutputPath)lib.rsp" Lines="@(CustomLibArg)" Overwrite="true" Encoding="utf-8" Condition="'$(TargetOS)' == 'windows' and '$(NativeLib)' == 'Static'" />
     <Exec Command="$(CppLibCreator)  @&quot;$(NativeIntermediateOutputPath)lib.rsp&quot;" Condition="'$(TargetOS)' == 'windows' and '$(NativeLib)' == 'Static'" />
+
+    <!-- strip symbols, see https://github.com/dotnet/runtime/blob/5d3288d/eng/native/functions.cmake#L374 -->
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(TargetOS)' != 'windows' and '$(TargetOS)' != 'OSX'"
+      Command="
+        objcopy --only-keep-debug &quot;$(NativeBinary)&quot; &quot;$(NativeBinary)$(NativeSymbolExt)&quot; &amp;&amp;
+        objcopy --strip-unneeded &quot;$(NativeBinary)&quot; &amp;&amp;
+        objcopy --add-gnu-debuglink=&quot;$(NativeBinary)$(NativeSymbolExt)&quot; &quot;$(NativeBinary)&quot;" />
+
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(TargetOS)' == 'OSX'" Command="dsymutil $(DsymUtilOptions) &quot;$(NativeBinary)&quot;" />
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(TargetOS)' == 'OSX'" Command="strip -no_code_signature_warning -S &quot;$(NativeBinary)&quot;" />
   </Target>
 
   <Target Name="CreateLib"
index aca22fd..aeee66f 100644 (file)
@@ -44,6 +44,6 @@ To aid in troubleshooting some of the most common problems related to trimming a
 
 ## Special considerations for Linux/macOS
 
-Debugging symbols (data about your program required for debugging) is by default part of native executable files on Unix-like operating systems. To minimize the size of your native executable, you can run the `strip` tool to remove the debugging symbols.
+Debugging symbols (data about your program required for debugging) is by default part of native executable files on Unix-like operating systems. To strip symbols into a separate file (`*.dbg` on Linux and `*.dwarf` on macOS), set `<StripSymbols>true</StripSymbols>`.
 
 No action is needed on Windows since the platform convention is to generate debug information into a separate file (`*.pdb`).