Skip to content

Commit fea82d4

Browse files
committed
Merge branch 'main' into trim
2 parents 40a5db6 + de9c1fb commit fea82d4

File tree

36 files changed

+1416
-109
lines changed

36 files changed

+1416
-109
lines changed

Diff for: CODEOWNERS

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
/javascript/ @github/codeql-javascript
99
/python/ @github/codeql-python
1010
/ruby/ @github/codeql-ruby
11+
/rust/ @github/codeql-rust
1112
/swift/ @github/codeql-swift
1213
/misc/codegen/ @github/codeql-swift
1314
/java/kotlin-extractor/ @github/codeql-kotlin
@@ -41,6 +42,7 @@ MODULE.bazel @github/codeql-ci-reviewers
4142
/.github/workflows/go-* @github/codeql-go
4243
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
4344
/.github/workflows/ruby-* @github/codeql-ruby
45+
/.github/workflows/rust.yml @github/codeql-rust
4446
/.github/workflows/swift.yml @github/codeql-swift
4547

4648
# Misc

Diff for: csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs

+95-12
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ IEnumerable<string> IBuildActions.EnumerateDirectories(string dir)
162162

163163
bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon;
164164

165+
public bool IsMonoInstalled { get; set; }
166+
167+
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
168+
165169
public string PathCombine(params string[] parts)
166170
{
167171
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
@@ -424,8 +428,7 @@ private CSharpAutobuilder CreateAutoBuilder(bool isWindows,
424428
return new CSharpAutobuilder(actions, options);
425429
}
426430

427-
[Fact]
428-
public void TestDefaultCSharpAutoBuilder()
431+
private void SetupActionForDotnet()
429432
{
430433
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
431434
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
@@ -438,20 +441,80 @@ public void TestDefaultCSharpAutoBuilder()
438441
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SCRATCH_DIR"] = "scratch";
439442
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs\ntest.csproj";
440443
actions.EnumerateDirectories[@"C:\Project"] = "";
441-
var xml = new XmlDocument();
442-
xml.LoadXml(@"<Project Sdk=""Microsoft.NET.Sdk"">
443-
<PropertyGroup>
444-
<OutputType>Exe</OutputType>
445-
<TargetFramework>netcoreapp2.1</TargetFramework>
446-
</PropertyGroup>
444+
}
447445

448-
</Project>");
446+
private void CreateAndVerifyDotnetScript(XmlDocument xml)
447+
{
449448
actions.LoadXml[@"C:\Project\test.csproj"] = xml;
450449

451450
var autobuilder = CreateAutoBuilder(true);
452451
TestAutobuilderScript(autobuilder, 0, 4);
453452
}
454453

454+
[Fact]
455+
public void TestDefaultCSharpAutoBuilder1()
456+
{
457+
SetupActionForDotnet();
458+
var xml = new XmlDocument();
459+
xml.LoadXml(
460+
"""
461+
<Project Sdk="Microsoft.NET.Sdk">
462+
<PropertyGroup>
463+
<OutputType>Exe</OutputType>
464+
<TargetFramework>netcoreapp2.1</TargetFramework>
465+
</PropertyGroup>
466+
</Project>
467+
""");
468+
CreateAndVerifyDotnetScript(xml);
469+
}
470+
471+
[Fact]
472+
public void TestDefaultCSharpAutoBuilder2()
473+
{
474+
SetupActionForDotnet();
475+
var xml = new XmlDocument();
476+
477+
xml.LoadXml(
478+
"""
479+
<Project>
480+
<Sdk Name="Microsoft.NET.Sdk" />
481+
482+
<PropertyGroup>
483+
<OutputType>Exe</OutputType>
484+
<TargetFramework>net9.0</TargetFramework>
485+
<ImplicitUsings>enable</ImplicitUsings>
486+
<Nullable>enable</Nullable>
487+
</PropertyGroup>
488+
</Project>
489+
"""
490+
);
491+
CreateAndVerifyDotnetScript(xml);
492+
}
493+
494+
[Fact]
495+
public void TestDefaultCSharpAutoBuilder3()
496+
{
497+
SetupActionForDotnet();
498+
var xml = new XmlDocument();
499+
500+
xml.LoadXml(
501+
"""
502+
<Project>
503+
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
504+
505+
<PropertyGroup>
506+
<OutputType>Exe</OutputType>
507+
<TargetFramework>net9.0</TargetFramework>
508+
<ImplicitUsings>enable</ImplicitUsings>
509+
<Nullable>enable</Nullable>
510+
</PropertyGroup>
511+
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
512+
</Project>
513+
"""
514+
);
515+
CreateAndVerifyDotnetScript(xml);
516+
}
517+
455518
[Fact]
456519
public void TestLinuxCSharpAutoBuilder()
457520
{
@@ -797,11 +860,32 @@ public void TestDirsProjWindows()
797860
}
798861

799862
[Fact]
800-
public void TestDirsProjLinux()
863+
public void TestDirsProjLinux_WithMono()
801864
{
865+
actions.IsMonoInstalled = true;
866+
802867
actions.RunProcess[@"nuget restore C:\Project/dirs.proj -DisableParallelProcessing"] = 1;
803868
actions.RunProcess[@"mono scratch/.nuget/nuget.exe restore C:\Project/dirs.proj -DisableParallelProcessing"] = 0;
804869
actions.RunProcess[@"msbuild C:\Project/dirs.proj /t:rebuild"] = 0;
870+
871+
var autobuilder = TestDirsProjLinux();
872+
TestAutobuilderScript(autobuilder, 0, 3);
873+
}
874+
875+
[Fact]
876+
public void TestDirsProjLinux_WithoutMono()
877+
{
878+
actions.IsMonoInstalled = false;
879+
880+
actions.RunProcess[@"dotnet msbuild /t:restore C:\Project/dirs.proj"] = 0;
881+
actions.RunProcess[@"dotnet msbuild C:\Project/dirs.proj /t:rebuild"] = 0;
882+
883+
var autobuilder = TestDirsProjLinux();
884+
TestAutobuilderScript(autobuilder, 0, 2);
885+
}
886+
887+
private CSharpAutobuilder TestDirsProjLinux()
888+
{
805889
actions.FileExists["csharp.log"] = true;
806890
actions.FileExists[@"C:\Project/a/test.csproj"] = true;
807891
actions.FileExists[@"C:\Project/dirs.proj"] = true;
@@ -830,8 +914,7 @@ public void TestDirsProjLinux()
830914
</Project>");
831915
actions.LoadXml[@"C:\Project/dirs.proj"] = dirsproj;
832916

833-
var autobuilder = CreateAutoBuilder(false);
834-
TestAutobuilderScript(autobuilder, 0, 3);
917+
return CreateAutoBuilder(false);
835918
}
836919

837920
[Fact]

Diff for: csharp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs

+4
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ IEnumerable<string> IBuildActions.EnumerateDirectories(string dir)
150150

151151
bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon;
152152

153+
public bool IsMonoInstalled { get; set; }
154+
155+
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
156+
153157
string IBuildActions.PathCombine(params string[] parts)
154158
{
155159
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));

Diff for: csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs

+10-7
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ internal static class MsBuildCommandExtensions
1010
/// <summary>
1111
/// Appends a call to msbuild.
1212
/// </summary>
13-
/// <param name="cmdBuilder"></param>
14-
/// <param name="builder"></param>
1513
/// <returns></returns>
16-
public static CommandBuilder MsBuildCommand(this CommandBuilder cmdBuilder, IAutobuilder<AutobuildOptionsShared> builder)
14+
public static CommandBuilder MsBuildCommand(this CommandBuilder cmdBuilder, IAutobuilder<AutobuildOptionsShared> builder, bool preferDotnet)
1715
{
1816
// mono doesn't ship with `msbuild` on Arm-based Macs, but we can fall back to
1917
// msbuild that ships with `dotnet` which can be invoked with `dotnet msbuild`
2018
// perhaps we should do this on all platforms?
21-
return builder.Actions.IsRunningOnAppleSilicon()
19+
// Similarly, there's no point in trying to rely on mono if it's not installed.
20+
// In which case we can still fall back to `dotnet msbuild`.
21+
return preferDotnet
2222
? cmdBuilder.RunCommand("dotnet").Argument("msbuild")
2323
: cmdBuilder.RunCommand("msbuild");
2424
}
@@ -75,13 +75,16 @@ BuildScript GetNugetRestoreScript() =>
7575
QuoteArgument(projectOrSolution.FullPath).
7676
Argument("-DisableParallelProcessing").
7777
Script;
78+
79+
var preferDotnet = builder.Actions.IsRunningOnAppleSilicon() || !builder.Actions.IsWindows() && !builder.Actions.IsMonoInstalled();
80+
7881
var nugetRestore = GetNugetRestoreScript();
7982
var msbuildRestoreCommand = new CommandBuilder(builder.Actions).
80-
MsBuildCommand(builder).
83+
MsBuildCommand(builder, preferDotnet).
8184
Argument("/t:restore").
8285
QuoteArgument(projectOrSolution.FullPath);
8386

84-
if (builder.Actions.IsRunningOnAppleSilicon())
87+
if (preferDotnet)
8588
{
8689
// On Apple Silicon, only try package restore with `dotnet msbuild /t:restore`
8790
ret &= BuildScript.Try(msbuildRestoreCommand.Script);
@@ -119,7 +122,7 @@ BuildScript GetNugetRestoreScript() =>
119122
command.RunCommand("set Platform=&& type NUL", quoteExe: false);
120123
}
121124

122-
command.MsBuildCommand(builder);
125+
command.MsBuildCommand(builder, preferDotnet);
123126
command.QuoteArgument(projectOrSolution.FullPath);
124127

125128
var target = "rebuild";

Diff for: csharp/autobuilder/Semmle.Autobuild.Shared/Project.cs

+21-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.IO;
44
using System.Linq;
55
using System.Xml;
6-
using Semmle.Util.Logging;
76

87
namespace Semmle.Autobuild.Shared
98
{
@@ -26,6 +25,26 @@ public class Project<TAutobuildOptions> : ProjectOrSolution<TAutobuildOptions> w
2625
private readonly Lazy<List<Project<TAutobuildOptions>>> includedProjectsLazy;
2726
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjectsLazy.Value;
2827

28+
private static bool HasSdkAttribute(XmlElement xml) =>
29+
xml.HasAttribute("Sdk");
30+
31+
private static bool AnyElement(XmlNodeList l, Func<XmlElement, bool> f) =>
32+
l.OfType<XmlElement>().Any(f);
33+
34+
/// <summary>
35+
/// According to https://learn.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2022#reference-a-project-sdk
36+
/// there are three ways to reference a project SDK:
37+
/// 1. As an attribute on the <Project/>.
38+
/// 2. As a top level element of <Project>.
39+
/// 3. As an attribute on an <Import> element.
40+
///
41+
/// Returns true, if the Sdk attribute is used, otherwise false.
42+
/// </summary>
43+
private static bool ReferencesSdk(XmlElement xml) =>
44+
HasSdkAttribute(xml) || // Case 1
45+
AnyElement(xml.ChildNodes, e => e.Name == "Sdk") || // Case 2
46+
AnyElement(xml.GetElementsByTagName("Import"), HasSdkAttribute); // Case 3
47+
2948
public Project(Autobuilder<TAutobuildOptions> builder, string path) : base(builder, path)
3049
{
3150
ToolsVersion = new Version();
@@ -49,7 +68,7 @@ public Project(Autobuilder<TAutobuildOptions> builder, string path) : base(build
4968

5069
if (root?.Name == "Project")
5170
{
52-
if (root.HasAttribute("Sdk"))
71+
if (ReferencesSdk(root))
5372
{
5473
DotNetProject = true;
5574
return;

Diff for: csharp/extractor/Semmle.Util/BuildActions.cs

+24
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ public interface IBuildActions
125125
/// <returns>True if we are running on Apple Silicon.</returns>
126126
bool IsRunningOnAppleSilicon();
127127

128+
/// <summary>
129+
/// Checks if Mono is installed.
130+
/// </summary>
131+
bool IsMonoInstalled();
132+
128133
/// <summary>
129134
/// Combine path segments, Path.Combine().
130135
/// </summary>
@@ -261,6 +266,25 @@ bool IBuildActions.IsRunningOnAppleSilicon()
261266
}
262267
}
263268

269+
bool IBuildActions.IsMonoInstalled()
270+
{
271+
var thisBuildActions = (IBuildActions)this;
272+
273+
if (thisBuildActions.IsWindows())
274+
{
275+
return false;
276+
}
277+
278+
try
279+
{
280+
return 0 == thisBuildActions.RunProcess("mono", "--version", workingDirectory: null, env: null);
281+
}
282+
catch (Exception)
283+
{
284+
return false;
285+
}
286+
}
287+
264288
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
265289

266290
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,2 @@
1-
import pytest
2-
import runs_on
3-
4-
5-
# Skipping the test on macos-15, as we're running into trouble.
6-
@pytest.mark.only_if(not runs_on.macos_15)
71
def test(codeql, csharp):
82
codeql.database.create(_assert_failure=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Improved autobuilder logic for detecting whether a project references a SDK (and should be built using `dotnet`).

0 commit comments

Comments
 (0)