diff --git a/src/VirtualClient/VirtualClient.Dependencies.UnitTests/CompilerInstallationTests.cs b/src/VirtualClient/VirtualClient.Dependencies.UnitTests/CompilerInstallationTests.cs index 9cb5a2c46..838d854e3 100644 --- a/src/VirtualClient/VirtualClient.Dependencies.UnitTests/CompilerInstallationTests.cs +++ b/src/VirtualClient/VirtualClient.Dependencies.UnitTests/CompilerInstallationTests.cs @@ -69,13 +69,21 @@ public async Task CompilerInstallationRunsTheExpectedWorkloadCommandInLinuxForGc "sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y", "sudo apt update", "sudo apt install build-essential gcc-123 g++-123 gfortran-123 -y --quiet", + "sudo update-alternatives --remove-all gcc", + "sudo update-alternatives --remove-all cc", + "sudo update-alternatives --remove-all g++", + "sudo update-alternatives --remove-all gcov", + "sudo update-alternatives --remove-all gcc-ar", + "sudo update-alternatives --remove-all gcc-ranlib", + "sudo update-alternatives --remove-all gfortran", + "sudo update-alternatives --remove-all cpp", "sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-123 1230 " + $"--slave /usr/bin/g++ g++ /usr/bin/g++-123 " + $"--slave /usr/bin/gcov gcov /usr/bin/gcov-123 " + $"--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-123 " + $"--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-123 " + - $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-123", - "sudo update-alternatives --install /usr/bin/cpp cpp /usr/bin/cpp-123 1230", + $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-123 " + + $"--slave /usr/bin/cpp cpp /usr/bin/cpp-123", }; int commandExecuted = 0; @@ -107,7 +115,7 @@ public async Task CompilerInstallationRunsTheExpectedWorkloadCommandInLinuxForGc await compilerInstallation.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); } - Assert.AreEqual(5, commandExecuted); + Assert.AreEqual(12, commandExecuted); } [Test] @@ -242,13 +250,21 @@ public async Task CompilerInstallationInLinuxDefaultsToGcc10() "sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y", "sudo apt update", "sudo apt install build-essential gcc-10 g++-10 gfortran-10 -y --quiet", + "sudo update-alternatives --remove-all gcc", + "sudo update-alternatives --remove-all cc", + "sudo update-alternatives --remove-all g++", + "sudo update-alternatives --remove-all gcov", + "sudo update-alternatives --remove-all gcc-ar", + "sudo update-alternatives --remove-all gcc-ranlib", + "sudo update-alternatives --remove-all gfortran", + "sudo update-alternatives --remove-all cpp", "sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 " + $"--slave /usr/bin/g++ g++ /usr/bin/g++-10 " + $"--slave /usr/bin/gcov gcov /usr/bin/gcov-10 " + $"--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-10 " + $"--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-10 " + - $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-10", - "sudo update-alternatives --install /usr/bin/cpp cpp /usr/bin/cpp-10 100", + $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-10 " + + $"--slave /usr/bin/cpp cpp /usr/bin/cpp-10", }; int commandExecuted = 0; @@ -281,7 +297,7 @@ public async Task CompilerInstallationInLinuxDefaultsToGcc10() await compilerInstallation.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); } - Assert.AreEqual(5, commandExecuted); + Assert.AreEqual(12, commandExecuted); } [Test] diff --git a/src/VirtualClient/VirtualClient.Dependencies/CompilerInstallation.cs b/src/VirtualClient/VirtualClient.Dependencies/CompilerInstallation.cs index 935500de8..222cce610 100644 --- a/src/VirtualClient/VirtualClient.Dependencies/CompilerInstallation.cs +++ b/src/VirtualClient/VirtualClient.Dependencies/CompilerInstallation.cs @@ -167,7 +167,6 @@ protected async Task ConfirmGccVersionInstalledAsync(CancellationToken can using (IProcessProxy process = this.systemManager.ProcessManager.CreateProcess(compiler, "--version")) { this.Logger.LogTraceMessage($"Confirming expected compiler version installed..."); - Console.WriteLine(compiler + "1"); await process.StartAndWaitAsync(cancellationToken); @@ -237,18 +236,45 @@ private async Task InstallGccAsync(string gccVersion, EventContext telemetryCont private async Task SetGccPriorityAsync(string gccVersion, EventContext telemetryContext, CancellationToken cancellationToken) { + string[] compilers = + { + "gcc", + "cc", + "g++", + "gcov", + "gcc-ar", + "gcc-ranlib", + "gfortran", + "cpp" + }; + + // due to the following error: + // update-alternatives: error: alternative g++ can't be slave of gcc: it is a master alternative + // must remove alternatives from the VM to avoid errors, then set all of them together + + foreach (string compiler in compilers) + { + try + { + await this.ExecuteCommandAsync("update-alternatives", $"--remove-all {compiler}", Environment.CurrentDirectory, telemetryContext, cancellationToken); + } + catch + { + // the message is: + // "error: no alternatives for g++" + // so we can continue as normal; non-breaking + } + } + string updateAlternativeArgument = $"--install /usr/bin/gcc gcc /usr/bin/gcc-{gccVersion} {gccVersion}0 " + $"--slave /usr/bin/g++ g++ /usr/bin/g++-{gccVersion} " + $"--slave /usr/bin/gcov gcov /usr/bin/gcov-{gccVersion} " + $"--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-{gccVersion} " + $"--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-{gccVersion} " + - $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-{gccVersion}"; + $"--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-{gccVersion} " + + $"--slave /usr/bin/cpp cpp /usr/bin/cpp-{gccVersion}"; await this.ExecuteCommandAsync("update-alternatives", updateAlternativeArgument, Environment.CurrentDirectory, telemetryContext, cancellationToken); - - // For some update path, the cpp can't be update-alternative by a gcc, so needs a separate call. - string updateAlternativeArgumentCpp = $"--install /usr/bin/cpp cpp /usr/bin/cpp-{gccVersion} {gccVersion}0"; - await this.ExecuteCommandAsync("update-alternatives", updateAlternativeArgumentCpp, Environment.CurrentDirectory, telemetryContext, cancellationToken); } private async Task InstallAoccAsync(string aoccVersion, EventContext telemetryContext, CancellationToken cancellationToken)