Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Unity 2018.3 is now released.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Burst for standalone players

Discussion in 'Entity Component System and C# Job system' started by xoofx, Jul 10, 2018.

  1. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    91
    It's an internal error, something is not handled properly in burst on a particular construct (involving likely calling a generic instance of a struct through an interface call). If you can isolate the issue with a simple project and submit a bug, we will have a look at it. Thanks!
     
  2. eric_funktroniclabs

    eric_funktroniclabs

    Joined:
    Oct 4, 2018
    Posts:
    6
    Bug submitted, and I've also put the min case up on github: https://github.com/efruchter/BrokenJob_Nov26

    Here's the offending code, for your convenience:

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Jobs;
    4. using Unity.Mathematics;
    5.  
    6. [BurstCompile]
    7. public struct BrokenJob : IJob
    8. {
    9.     public NativeArray<float3> GrabConstraints;
    10.  
    11.     [ReadOnly] public float3x3 LeftHandPosition, RightHandPosition;
    12.  
    13.     public void Execute()
    14.     {
    15.         for (int grabIndex = 0; grabIndex < GrabConstraints.Length; grabIndex++)
    16.         {
    17.             bool isLeft = grabIndex == 0 || grabIndex == 2;
    18.             var pos = isLeft ? LeftHandPosition.c0 : RightHandPosition.c0;
    19.             int grabStatKey = isLeft ? 1 : 2;
    20.         }
    21.     }
    22. }
    I've noticed that if I remove the 3rd line "grabStatKey", it compiles. I have a custom blittable Bool1 struct that is a "byte" internally, and swapping "bool" with my "bool1" also fixes the compilation.
     
    Last edited: Nov 29, 2018
  3. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    171
    Hi,

    When I want build on Win x64, I have this error :
    Code (CSharp):
    1. System.Exception: C:\Users\sylme\Desktop\Test iso\test iso\Library\PackageCache\com.unity.burst@0.2.4-preview.37\.Runtime\bcl.exe did not run properly!
    2.   at UnityEditorInternal.Runner.RunProgram (UnityEditor.Utils.Program p, System.String exe, System.String args, System.String workingDirectory, UnityEditor.Scripting.Compilers.CompilerOutputParserBase parser) [0x0011f] in C:\buildslave\unity\build\Editor\Mono\BuildPipeline\BuildUtils.cs:130
    3.   at UnityEditorInternal.Runner.RunManagedProgram (System.String exe, System.String args, System.String workingDirectory, UnityEditor.Scripting.Compilers.CompilerOutputParserBase parser, System.Action`1[T] setupStartInfo) [0x00063] in C:\buildslave\unity\build\Editor\Mono\BuildPipeline\BuildUtils.cs:73
    4.   at Unity.Burst.Editor.BurstAotCompiler.OnPostBuildPlayerScriptDLLs (UnityEditor.Build.Reporting.BuildReport report) [0x0054f] in C:\Users\sylme\Desktop\Test iso\test iso\Library\PackageCache\com.unity.burst@0.2.4-preview.37\Editor\BurstAotCompiler.cs:236
    5. UnityEngine.Debug:LogError(Object)
    6. Unity.Burst.Editor.BurstAotCompiler:OnPostBuildPlayerScriptDLLs(BuildReport) (at Library/PackageCache/com.unity.burst@0.2.4-preview.37/Editor/BurstAotCompiler.cs:240)
    7. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    This job is unit tested so I know it works in editor with burst and of course I have no try/catch in my ECS world
    Can you add line where burst crash in furtur ?

    Job code :

    Code (CSharp):
    1.         [BurstCompile]
    2.         public struct DistributionLinkDemandToOfferJob : IJob
    3.         {
    4.             #region Implementation of IJob
    5.  
    6.             /// <inheritdoc />
    7.  
    8.             // ReSharper disable once FunctionComplexityOverflow
    9.             public void Execute()
    10.             {
    11.                 foreach (var currentDemandIndex in DemandOrder)
    12.                 {
    13.                     var demandChunk      = DemandChunks[currentDemandIndex.x];
    14.                     var demandResumArray = demandChunk.GetNativeArray(DemandResumACC);
    15.  
    16.                     _demandResum = demandResumArray[currentDemandIndex.y];
    17.  
    18.                     if (_demandResum.FillByLinkedDemand)
    19.                         continue;
    20.  
    21.                     int bestScore = -999;
    22.  
    23.                     for (int offerChunkIndex = 0; offerChunkIndex < GoodOfferChunk.Length; offerChunkIndex++)
    24.                     {
    25.                         var offerArray = OfferChunks[GoodOfferChunk[offerChunkIndex]].GetNativeArray(OfferResumACC);
    26.  
    27.                         for (int offerArrayIndex = 0; offerArrayIndex < offerArray.Length; offerArrayIndex++)
    28.                         {
    29.                             if (offerArray[offerArrayIndex].Reserved)
    30.                                 continue;
    31.  
    32.                             var currentScore = GetScoreOffer(offerArray[offerArrayIndex]);
    33.  
    34.                             if (bestScore >= currentScore)
    35.                                 continue;
    36.  
    37.                             bestScore       = currentScore;
    38.                             _betterOffer[0] = GoodOfferChunk[offerChunkIndex];
    39.                             _betterOffer[1] = offerArrayIndex;
    40.                         }
    41.                     }
    42.  
    43.                     //if score inf -2 again, it means that any offer is valid so cute this resource
    44.                     if (bestScore < -1) //-1 is not valid beause an offer can be not valid for this demand but good for next
    45.                         return;
    46.  
    47.                     var offerResumArray = OfferChunks[_betterOffer.x].GetNativeArray(OfferResumACC);
    48.                     var oTraget         = offerResumArray[_betterOffer.y];
    49.                     oTraget.Reserved                = true;
    50.                     offerResumArray[_betterOffer.y] = oTraget;
    51.  
    52.                     PreAgreementList.Add(new PreAgreement { DemandIndex = currentDemandIndex, OfferIndex = _betterOffer });
    53.                 }
    54.             }
    55.  
    56.             #endregion
    57.  
    58.             private int GetScoreOffer(OfferResum offer)
    59.             {
    60.                 if (offer.AmountSum < 1F || _demandResum.CarrierCameFromMe == false && offer.CarrierCount == 0)
    61.                     return -1;
    62.  
    63.                 int score = ((int)offer.Priority + 1) * 2000;
    64.  
    65.                 //distance of vector 100,100,100
    66.                 const float maxDistanceForValue = 1F / 173.20508F;
    67.  
    68.                 score += (int)(1000F * (1F - math.clamp(math.distance(_demandResum.Position, offer.Position) * maxDistanceForValue, 0F, 1F)));
    69.  
    70.                 var tuple = CalcAmountResource(offer.AmountFree);
    71.  
    72.                 int amountResource = tuple.Sum, amountValue = tuple.Value;
    73.  
    74.                 if (_demandResum.InternalStorageAccepted)
    75.                 {
    76.                     tuple = CalcAmountResource(offer.AmountInternal);
    77.  
    78.                     amountResource += tuple.Sum;
    79.                     amountValue    += tuple.Value;
    80.                 }
    81.  
    82.                 if (amountResource < 1F)
    83.                     return -1;
    84.  
    85.                 score += math.min(15 * amountValue, 1000);
    86.                 score += math.min(15 * amountResource, 500);
    87.  
    88.                 return score;
    89.             }
    90.  
    91.             /// <summary>
    92.             /// Calcul amount sum and amount value
    93.             /// </summary>
    94.             /// <param name="offer"></param>
    95.             /// <returns></returns>
    96.             private (int Sum, int Value) CalcAmountResource(OfferAmount offer)
    97.             {
    98.                 int sum = 0, value = 0;
    99.  
    100.                 var qualMin = _demandResum.QualityMinimun;
    101.                 var qualMax = _demandResum.QualityMaximum;
    102.  
    103.                 if (qualMin == QualityResource.Poor)
    104.                 {
    105.                     sum   += offer.AmountPoor;
    106.                     value += offer.AmountPoor;
    107.                 }
    108.  
    109.                 if (qualMin <= QualityResource.Basic && qualMax >= QualityResource.Basic)
    110.                 {
    111.                     sum   += offer.AmountBasic;
    112.                     value += offer.AmountBasic * 2;
    113.                 }
    114.  
    115.                 if (qualMin <= QualityResource.Good && qualMax >= QualityResource.Good)
    116.                 {
    117.                     sum   += offer.AmountGood;
    118.                     value += offer.AmountGood * 3;
    119.                 }
    120.  
    121.                 if (qualMin <= QualityResource.Excellent && qualMax >= QualityResource.Excellent)
    122.                 {
    123.                     sum   += offer.AmountExcellent;
    124.                     value += offer.AmountExcellent * 4;
    125.                 }
    126.  
    127.                 if (qualMin <= QualityResource.Divin && qualMax == QualityResource.Divin)
    128.                 {
    129.                     sum   += offer.AmountDivin;
    130.                     value += offer.AmountDivin * 5;
    131.                 }
    132.  
    133.                 return (sum, value);
    134.             }
    135.  
    136.             #region Variables
    137.  
    138.             [ReadOnly]
    139.             public NativeArray<ArchetypeChunk> DemandChunks;
    140.             [ReadOnly]
    141.             public NativeArray<ArchetypeChunk> OfferChunks;
    142.  
    143.             [ReadOnly]
    144.             public NativeArray<int2> DemandOrder;
    145.             [ReadOnly]
    146.             public NativeList<int> GoodOfferChunk;
    147.  
    148.             [ReadOnly]
    149.             public ArchetypeChunkComponentType<DemandResum> DemandResumACC;
    150.             public ArchetypeChunkComponentType<OfferResum> OfferResumACC;
    151.  
    152.             //output
    153.             [WriteOnly]
    154.             public NativeList<PreAgreement> PreAgreementList;
    155.  
    156.             private int2                    _betterOffer;
    157.             private DemandResum             _demandResum;
    158.  
    159.             #endregion
    160.         }
    161.  
     
  4. capyvara

    capyvara

    Joined:
    Mar 11, 2010
    Posts:
    68
    Just a heads up, updating to the latest Xcode command line tools fixed the problem, maybe the clang version did't accepted symlinks to .tbd's ?

    I see you use /usr/bin/clang directly so this needs a dependency on the command line tools directly, instead may be better to use xcrun clang in order to run the compiler, etc?
     
    Last edited: Dec 17, 2018
  5. capyvara

    capyvara

    Joined:
    Mar 11, 2010
    Posts:
    68
    Ok, now after updating, the linux standalone shows this while trying to compile on OSX:

    Code (csharp):
    1. Failed running /.../Library/PackageCache/com.unity.burst@0.2.4-preview.39/.Runtime/bcl.exe @/var/folders/yf/_fy5r6g51hg14jw41ppwgcr40000gn/T/tmp296d70fd.tmp
    2.  
    3. stdout:
    4. Compiling for the platform `Linux` using the following toolchain : GccLinuxToolChain
    5. System.NotSupportedException: Burst compilation for standalone, is only supported with a suitable compiler tool chain. (C++ code builder is unable to build C++ code. In order to build C++ code for Linux, you must be running on Linux.).
    6.   at Burst.Compiler.IL.Aot.AotLinker.Link (System.Collections.Generic.IEnumerable`1[T] objFiles, System.String outPath) [0x0006d] in <f47ca3c15253443792b4dc3d62cd9b18>:0
    7.   at Burst.Linker.Program.Main (System.String[] args) [0x0017b] in <f47ca3c15253443792b4dc3d62cd9b18>:0
    8. Usage: blink.exe [options] <input .o/.obj/.ll files...>
    9.       --help                 Show Help
    10.       --platform=VALUE       Target Platform <Windows|macOS|Linux|Android|iOS|
    11.                                PS4|XboxOne|Wasm|UWP>
    12.       --target=VALUE         Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
    13.                                SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
    14.                                AARCH64|THUMB2_NEON32>
    15.       --il2cpp-plugin-folder=VALUE
    16.                              Plugin folder
    17.       --output=VALUE         Output shared library file
    18.  
    Unity 2018.3.0f2, Xcode 10.1 (10B61), Burst 0.2.4-preview.39

    The same error happens on the Unity cloud build machine.
     
  6. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    91
    As IL2CPP, burst does not support cross compiling (apart for consoles). So you need to be on the target machine to compile.

    We are trying to find a solution to allow this scenario in a future version.
     
  7. capyvara

    capyvara

    Joined:
    Mar 11, 2010
    Posts:
    68
    As a side question, there are plans for IL2CPP on Linux standalone also? maybe will help for headless servers.
     
    wobes likes this.
  8. jeromeWork

    jeromeWork

    Joined:
    Sep 1, 2015
    Posts:
    239
    Sorry, stupid newbie question... Been told by an asset developer that Unity requires me to install Windows SDK and VC++ toolkit from the VisualStudio Installer in order for burst compiler and standalone builds to work. However I didn't install VisualStudio along with Unity, I'm using VisualStudioCode. Is there any workaround or am I stuck having to install the full fat version? (and if so, will it be ok if I don't set it as my default code editor in Unity?)
     
  9. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,384
    Will Switch support come any time soon?
     
  10. MartijnGG

    MartijnGG

    Joined:
    May 3, 2018
    Posts:
    43
    Currently this prints as an error which is a little confusing as the build itself succeeds. Is it possible to change this to a warning instead?

    Since its a known issue that cross compiling doesn't work, could the burst compiler skip running when compiling for a target different as your host platform? (With a log of course)

    Thanks :D
     
  11. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    1,906
    So a development build using IL2CPP resulted in the client immediately consuming 12GB of ram. Production build uses 950MB in the same state. Is that in the realm of expected?

    Edit: Doesn't appear to be burst related, and I'm also getting the same behavior on production builds now, so will take this over to the platforms forum.
     
    Last edited: Jan 22, 2019
  12. Jay-Pavlina

    Jay-Pavlina

    Joined:
    Feb 19, 2012
    Posts:
    185
    Is burst support planned for WebGL?
     
  13. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,294
    Will there be a SSE4a support for potato driven CPU's from AMD?
    Would be really nice.
     
    davenirline likes this.
  14. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    305
    Asking the same because we can't release our game with Burst turned on. It crashes on old CPU.
     
  15. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    753
    What are you actually asking about? Your issue is related to SSE4 instructions (used by Burst) which are not supported on old Phenoms etc.
     
  16. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    305
    What I meant was existing players with old CPUs (like Phenoms) can't run the game if we enabled Burst compiler. It just crashes. For now, we disabled Burst until Unity fixes it. So our game is actually slower when it should not be.
     
    xVergilx likes this.
  17. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,294
    Yeah, some foolproof protection would be nice. Like automatic disabling burst jobs on devices that do not support it.
    I'm pretty sure it's going to be implemented, it's just not there yet.
     
    MegamaDev likes this.
  18. Gabriel_Alexandre

    Gabriel_Alexandre

    Joined:
    Nov 3, 2016
    Posts:
    1
    Had the error:
    Failed running C:\Users\Eric\Desktop\BurstTest\Library\PackageCache\com.unity.burst@0.2.4-preview.38\.Runtime\bcl.exe
    ...

    Installing Dektop Development with C++ in VS fixed.

     
  19. pcysl5edgo

    pcysl5edgo

    Joined:
    Jun 3, 2018
    Posts:
    41
    I tried dynamic burst-job generation by AssemblyBuilder.
    I successfully dynamically generated IJobParallelFor struct but it throwed Mono.Cecil.AssemblyResolutionException when it was with [BurstCompile].
    I hope Unity Technologies to resolve this problem.

    Unexpected exception Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'F***, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'

    at Mono.Cecil.BaseAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name, Mono.Cecil.ReaderParameters parameters) [0x00105] in <28cdca1704d2491781795499c297b78b>:0

    at Burst.Compiler.IL.AssemblyLoader.Resolve (Mono.Cecil.AssemblyNameReference name) [0x0003d] in <b7b473b74a1a407ea639da1765481143>:0

    at Burst.Compiler.IL.AssemblyLoader.Resolve (Burst.Compiler.IL.Helpers.SimpleTypeReferenceString simpleTypeReferenceString) [0x00015] in <b7b473b74a1a407ea639da1765481143>:0

    at Burst.Compiler.IL.AssemblyLoader.Resolve (Burst.Compiler.IL.Helpers.SimpleTypeReferenceString simpleTypeReferenceString) [0x00120] in <b7b473b74a1a407ea639da1765481143>:0

    at Burst.Compiler.IL.AssemblyLoader.Resolve (Burst.Compiler.IL.Helpers.MethodReferenceString methodReferenceString) [0x0000e] in <b7b473b74a1a407ea639da1765481143>:0

    at Burst.Compiler.IL.Jit.JitCompilerService.Compile (Burst.Compiler.IL.Jit.JitCompilerService+CompileJob job) [0x001d9] in <b7b473b74a1a407ea639da1765481143>:0

    Code (CSharp):
    1. using System;
    2. using System.Diagnostics;
    3. using UnityEngine;
    4. using Unity.Burst;
    5. using Unity.Jobs;
    6. using Unity.Collections;
    7. using Unity.Collections.LowLevel.Unsafe;
    8. using System.Reflection;
    9. using System.Reflection.Emit;
    10.  
    11. using static System.Reflection.Emit.OpCodes;
    12.  
    13. public class TestManager : MonoBehaviour
    14. {
    15.     public unsafe interface IAccessor : IJobParallelFor
    16.     {
    17.         int* GetPtr();
    18.         void SetPtr(int* value);
    19.         JobHandle Schedule();
    20.     }
    21.  
    22.     private const int V = 50000;
    23.     IAccessor accessor;
    24.  
    25.     void Start()
    26.     {
    27.         const string ModuleName = "Hoge";
    28.         const string FileName = ModuleName + ".dll";
    29.         AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(ModuleName), AssemblyBuilderAccess.RunAndSave);
    30.         var moduleBulder = assemblyBuilder.DefineDynamicModule(ModuleName, FileName);
    31.         var typeBuilder = moduleBulder.DefineType("BURSTJOB",
    32.             TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.SequentialLayout,
    33.             typeof(System.ValueType),
    34.             new Type[] { typeof(IAccessor), typeof(IJobParallelFor) });
    35.         typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(BurstCompileAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>()));
    36.         var intPtrType = typeof(int).MakePointerType();
    37.         var field0 = typeBuilder.DefineField("ptr",
    38.             intPtrType,
    39.             FieldAttributes.Public);
    40.         field0.SetCustomAttribute(new CustomAttributeBuilder(typeof(NativeDisableUnsafePtrRestrictionAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>()));
    41.         const MethodAttributes Attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.HideBySig;
    42.         var schedule = typeBuilder.DefineMethod("Schedule", Attributes, typeof(JobHandle), Type.EmptyTypes);
    43.         {
    44.             var il = schedule.GetILGenerator();
    45.             var local = il.DeclareLocal(typeof(JobHandle));
    46.             il.Emit(Ldarg_0);
    47.             il.Emit(Ldobj, typeBuilder);
    48.             il.Emit(Ldc_I4, V);
    49.             il.Emit(Ldc_I4, 1024);
    50.             il.Emit(Ldloca_S, 0);
    51.             il.Emit(Initobj, typeof(JobHandle));
    52.             il.Emit(Ldloc_0);
    53.             il.EmitCall(Call, typeof(IJobParallelForExtensions).GetMethod("Schedule").MakeGenericMethod(typeBuilder), Type.EmptyTypes);
    54.             il.Emit(Ret);
    55.         }
    56.         var execute = typeBuilder.DefineMethod("Execute", Attributes, CallingConventions.Standard, typeof(void), new Type[] { typeof(int) });
    57.         {
    58.             var il = execute.GetILGenerator();
    59.             il.Emit(Ldarg_0);
    60.             il.Emit(Ldfld, field0);
    61.             il.Emit(Ldarg_1);
    62.             il.Emit(Conv_I);
    63.             il.Emit(Ldc_I4_4);
    64.             il.Emit(Mul);
    65.             il.Emit(Add);
    66.             il.Emit(Ldarg_1);
    67.             il.Emit(Stind_I4);
    68.             il.Emit(Ret);
    69.         }
    70.         var setPtr = typeBuilder.DefineMethod("SetPtr", Attributes, CallingConventions.Standard, typeof(void), new[] { intPtrType });
    71.         {
    72.             var il = setPtr.GetILGenerator();
    73.             il.Emit(Ldarg_0);
    74.             il.Emit(Ldarg_1);
    75.             il.Emit(Stfld, field0);
    76.             il.Emit(Ret);
    77.         }
    78.         var getPtr = typeBuilder.DefineMethod("GetPtr", Attributes, CallingConventions.Standard, intPtrType, Type.EmptyTypes);
    79.         {
    80.             var il = getPtr.GetILGenerator();
    81.             il.Emit(Ldarg_0);
    82.             il.Emit(Ldfld, field0);
    83.             il.Emit(Ret);
    84.         }
    85.         accessor = (IAccessor)Activator.CreateInstance(typeBuilder.CreateType());
    86.         assemblyBuilder.Save(FileName);
    87.         Verify(assemblyBuilder);
    88.     }
    89.  
    90.     unsafe void Update()
    91.     {
    92.         using (var array = new NativeArray<int>(V, Allocator.TempJob))
    93.         {
    94.             accessor.SetPtr((int*)array.GetUnsafePtr());
    95.             accessor.Schedule().Complete();
    96.         }
    97.     }
    98.  
    99.     static void Verify(params AssemblyBuilder[] builders)
    100.     {
    101.         var path = @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\x64\PEVerify.exe";
    102.  
    103.         foreach (var targetDll in builders)
    104.         {
    105.             var psi = new ProcessStartInfo(path, targetDll.GetName().Name + ".dll")
    106.             {
    107.                 CreateNoWindow = true,
    108.                 WindowStyle = ProcessWindowStyle.Hidden,
    109.                 RedirectStandardOutput = true,
    110.                 RedirectStandardError = true,
    111.                 UseShellExecute = false
    112.             };
    113.  
    114.             var p = Process.Start(psi);
    115.             var data = p.StandardOutput.ReadToEnd();
    116.             Console.WriteLine(data);
    117.         }
    118.     }
    119. }
     
  20. MegamaDev

    MegamaDev

    Joined:
    Jul 17, 2017
    Posts:
    18
    No worries--the VS Installer is actually just an all-purpose installer/uninstaller for any part of Microsoft's full dev package, which need not include Visual Studio if you don't want it to. You'd never guess it from the name...threw me for a bit of a loop when I was trying to get started with Rust. Yet here I am, happily sporting the VS compiler and VC++ build tools without ever having to dump 8GB worth of IDE onto my hard drive in the process.
     
    jeromeWork likes this.
  21. jeromeWork

    jeromeWork

    Joined:
    Sep 1, 2015
    Posts:
    239
    Thanks @MegamaDev I did install it in the end, but good hear I can get rid of it without causing any damage
     
    MegamaDev likes this.