Skip to content

Commit

Permalink
Add explicit support for separators and multiple values as metadata. …
Browse files Browse the repository at this point in the history
…This allows us to escape properly.
  • Loading branch information
wasabii committed Mar 20, 2024
1 parent b0bbbf2 commit 1963e3b
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 42 deletions.
72 changes: 71 additions & 1 deletion src/IKVM.Clang.Sdk.Tasks/ClangExe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,81 @@ protected override string GenerateResponseFileCommands()
var sb = new StringBuilder();

foreach (var arg in Arguments)
sb.AppendLine(arg.ItemSpec);
{
if (arg.ItemSpec.Length > 0)
{
AppendEscaped(sb, arg.ItemSpec);

if (arg.GetMetadata("Value") is string value && value.Length > 0)
{
// separate the value
if (arg.GetMetadata("Seperator") is string seperator && seperator.Length > 0)
sb.Append(seperator);

AppendEscaped(sb, value);

// additional Value/Seperator metadata
for (int i = 2; i < 128; i++)
{
if (arg.GetMetadata($"Value{i}") is string nextValue && nextValue.Length > 0)
{
// seperate the second value
if (arg.GetMetadata($"Seperator{i}") is string nextSeperator && nextSeperator.Length > 0)
sb.Append(nextSeperator);

AppendEscaped(sb, nextValue);
}
else
{
// no more values, exit early
break;
}
}
}

sb.AppendLine();
}
}

return sb.ToString();
}

/// <summary>
/// Escapes the specified string if it contains any characters the require escaping.
/// </summary>
/// <param name="sb"></param>
/// <param name="value"></param>
/// <returns></returns>
static StringBuilder AppendEscaped(StringBuilder sb, string value)
{
var ws = false;

foreach (var c in value)
{
switch (c)
{
case '\"':
sb.Append('\\').Append(c);
break;
case '\\':
sb.Append("\\\\");
break;
default:
ws |= char.IsWhiteSpace(c);
sb.Append(c);
break;
}
}

if (ws)
{
sb.Insert(0, '\"');
sb.Append('\"');
}

return sb;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetIdentifiers>x86_64-pc-windows-msvc;i686-pc-windows-msvc;thumbv7-pc-windows-msvc;aarch64-pc-windows-msvc</TargetIdentifiers>
<Verbose>true</Verbose>
</PropertyGroup>
<PropertyGroup Condition="$(TargetIdentifier.Contains('-windows-'))">
<Subsystem>console</Subsystem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetIdentifiers>x86_64-pc-windows-msvc;i686-pc-windows-msvc;thumbv7-pc-windows-msvc;aarch64-pc-windows-msvc</TargetIdentifiers>
<Verbose>true</Verbose>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\SharedLibrary2\SharedLibrary2.clangproj">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetIdentifiers>x86_64-pc-windows-msvc;i686-pc-windows-msvc;thumbv7-pc-windows-msvc;aarch64-pc-windows-msvc</TargetIdentifiers>
<Verbose>true</Verbose>
</PropertyGroup>
<ItemGroup>
<Compile Include="hello2.c" />
Expand Down
9 changes: 5 additions & 4 deletions src/IKVM.Clang.Sdk.Tests/ProjectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ public static void ClassInitialize(TestContext context)
options.TargetsToBuild.Add("Clean");
options.TargetsToBuild.Add("Restore");
options.Arguments.Add("/v:d");
analyzer.Build(options).OverallSuccess.Should().Be(true);

var result = analyzer.Build(options);
context.AddResultFile(Path.Combine(WorkRoot, "msbuild.binlog"));
result.OverallSuccess.Should().Be(true);
}

[DataTestMethod]
Expand Down Expand Up @@ -166,9 +166,10 @@ public void CanBuildTestProject(EnvironmentPreference env, string tid)
options.TargetsToBuild.Add("Clean");
options.TargetsToBuild.Add("Build");
options.Arguments.Add("/v:d");
analyzer.Build(options).OverallSuccess.Should().BeTrue();

var result = analyzer.Build(options);
TestContext.AddResultFile(Path.Combine(WorkRoot, $"{tid}-msbuild.binlog"));
result.OverallSuccess.Should().BeTrue();

}

}
Expand Down
99 changes: 62 additions & 37 deletions src/IKVM.Clang.Sdk/Sdk/targets/IKVM.Clang.Core.targets
Original file line number Diff line number Diff line change
Expand Up @@ -418,72 +418,83 @@
<_Args Remove="@(_Args)" />
<_Args Include="-c" />
<_Args Include="-v" Condition=" '$(Verbose)' == 'true' " />
<_Args Include="--target=$(TargetTriple)" />
<_Args Include="--target" Value="$(TargetTriple)" Seperator="=" />
<_Args Include="-g" Condition=" '$(_DebugSymbols)' == 'true' " />

<_Args Include="-std=$(_LanguageStandard)" Condition=" '$(_LanguageStandard)' != '' " />
<_Args Include="-std" Value="$(_LanguageStandard)" Seperator="=" Condition=" '$(_LanguageStandard)' != '' " />
<_Args Include="-fPIC" Condition=" '$(_PositionIndependentCode)' == 'true' " />
<_Args Include="-fms-compatibility" Condition=" '$(_MsCompatibility)' == 'true' " />
<_Args Include="-fms-compatibility-version=$(_MsCompatibilityVersion)" Condition=" '$(_MsCompatibilityVersion)' != '' " />
<_Args Include="-fms-compatibility-version" Value="$(_MsCompatibilityVersion)" Seperator="=" Condition=" '$(_MsCompatibilityVersion)' != '' " />

<_Args Include="-x;c" Condition=" '$(_Language)' == 'C' " />
<_Args Include="-x;c++" Condition=" '$(_Language)' == 'C++' " />
<_Args Include="-xc" Condition=" '$(_Language)' == 'C' " />
<_Args Include="-xc++" Condition=" '$(_Language)' == 'C++' " />

<_SystemRootDirectories Remove="@(_SystemRootDirectories)" />
<_SystemRootDirectories Include="%(Compile.SystemRootDirectories)" />
<_SystemRootDirectories Include="@(SystemRootDirectories)" />
<_SystemRootDirectories Include="$(SystemRootDirectories)" />
<_Args Include="@(_SystemRootDirectories->Distinct()->Replace('\', '\\')->Replace('%22', '%5c%22')->'--sysroot &quot;%(Identity)&quot;')" Condition=" '@(_SystemRootDirectories)' != '' " />
<_SystemRootDirectoriesTemp Remove="@(_SystemRootDirectoriesTemp)" />
<_SystemRootDirectoriesTemp Include="@(_SystemRootDirectories->Distinct())" />
<_SystemRootDirectoriesArgs Remove="@(_SystemRootDirectoriesArgs)" />
<_SystemRootDirectoriesArgs Include="@(_SystemRootDirectoriesTemp->'--sysroot')" Value="%(_SystemRootDirectoriesTemp.Identity)" Seperator=" " />
<_Args Include="@(_SystemRootDirectoriesArgs)" />

<_IncludeSystemRootDirectories Remove="@(_IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="%(Compile.IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="@(IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="$(IncludeSystemRootDirectories)" />
<_Args Include="@(_IncludeSystemRootDirectories->Distinct()->Replace('\', '\\')->Replace('%22', '%5c%22')->'-isysroot &quot;%(Identity)&quot;')" Condition=" '@(_IncludeSystemRootDirectories)' != '' " />
<_IncludeSystemRootDirectoriesTemp Remove="@(_IncludeSystemRootDirectoriesTemp)" />
<_IncludeSystemRootDirectoriesTemp Include="@(_IncludeSystemRootDirectories->Distinct())" />
<_IncludeSystemRootDirectoriesArgs Remove="@(_IncludeSystemRootDirectoriesArgs)" />
<_IncludeSystemRootDirectoriesArgs Include="@(_IncludeSystemRootDirectoriesTemp->'--isysroot')" Value="%(_IncludeSystemRootDirectoriesTemp.Identity)" Seperator=" " />
<_Args Include="@(_IncludeSystemRootDirectoriesArgs)" />

<_SystemIncludeDirectories Remove="@(_SystemIncludeDirectories)" />
<_SystemIncludeDirectories Include="%(Compile.SystemIncludeDirectories)" />
<_SystemIncludeDirectories Include="@(SystemIncludeDirectories)" />
<_SystemIncludeDirectories Include="$(SystemIncludeDirectories)" />
<_Args Include="@(_SystemIncludeDirectories->Distinct()->Replace('\', '\\')->Replace('%22', '%5c%22')->'-isystem &quot;%(Identity)&quot;')" Condition=" '@(_SystemIncludeDirectories)' != '' " />
<_SystemIncludeDirectoriesTemp Remove="@(_SystemIncludeDirectoriesTemp)" />
<_SystemIncludeDirectoriesTemp Include="@(_SystemIncludeDirectories->Distinct())" />
<_SystemIncludeDirectoriesArgs Remove="@(_SystemIncludeDirectoriesArgs)" />
<_SystemIncludeDirectoriesArgs Include="@(_SystemIncludeDirectoriesTemp->'-isystem')" Value="%(_SystemIncludeDirectoriesTemp.Identity)" Seperator=" " />
<_Args Include="@(_SystemIncludeDirectoriesArgs)" />

<_IncludeDirectories Remove="@(_IncludeDirectories)" />
<_IncludeDirectories Include="%(Compile.IncludeDirectories)" />
<_IncludeDirectories Include="@(IncludeDirectories)" />
<_IncludeDirectories Include="$(IncludeDirectories)" />
<_IncludeDirectories Include="@(ImportedIncludeDirectories)" />
<_Args Include="@(_IncludeDirectories->Distinct()->Replace('\', '\\')->Replace('%22', '%5c%22')->'-I &quot;%(Identity)&quot;')" Condition=" '@(_IncludeDirectories)' != '' " />
<_IncludeDirectoriesTemp Remove="@(_IncludeDirectoriesTemp)" />
<_IncludeDirectoriesTemp Include="@(_IncludeDirectories->Distinct())" />
<_IncludeDirectoriesArgs Remove="@(_IncludeDirectoriesArgs)" />
<_IncludeDirectoriesArgs Include="@(_IncludeDirectoriesTemp->'-I')" Value="%(_IncludeDirectoriesTemp.Identity)" Seperator="" />
<_Args Include="@(_IncludeDirectoriesArgs)" />

<_PreprocessorDefinitions Remove="@(_PreprocessorDefinitions)" />
<_PreprocessorDefinitions Include="%(Compile.PreprocessorDefinitions)" />
<_PreprocessorDefinitions Include="@(PreprocessorDefinitions)" />
<_PreprocessorDefinitions Include="$(PreprocessorDefinitions)" />
<_PreprocessorDefinitionsEscaped Remove="@(_PreprocessorDefinitionsEscaped)" />
<_PreprocessorDefinitionsEscaped Include="@(_PreprocessorDefinitions)" EscapedValue="$([System.String]::Copy('%(_PreprocessorDefinitions.Value)').Replace('%22', '%5c%22'))" />
<_Args Include="@(_PreprocessorDefinitionsEscaped->Distinct()->'-D %(Identity)')" Condition=" '@(_PreprocessorDefinitionsEscaped)' != '' And %(_PreprocessorDefinitionsEscaped.EscapedValue) == '' " />
<_Args Include="@(_PreprocessorDefinitionsEscaped->Distinct()->'-D %(Identity)=%(EscapedValue)')" Condition=" '@(_PreprocessorDefinitionsEscaped)' != '' And %(_PreprocessorDefinitionsEscaped.EscapedValue) != '' " />
<_PreprocessorDefinitionsArgs Remove="@(_PreprocessorDefinitionsArgs)" />
<_PreprocessorDefinitionsArgs Include="@(_PreprocessorDefinitions->'-D')" Value="%(_PreprocessorDefinitions.Identity)" Seperator="" Value2="%(_PreprocessorDefinitions.Value)" Seperator2="=" />
<_Args Include="@(_PreprocessorDefinitionsArgs)" />

<_AdditionalOptions Remove="@(_AdditionalOptions)" />
<_AdditionalOptions Include="%(Compile.AdditionalCompileOptions)" />
<_AdditionalOptions Include="@(AdditionalCompileOptions)" />
<_AdditionalOptions Include="$(AdditionalCompileOptions)" />
<_Args Include="@(_AdditionalOptions)" />

<_SourcePath Remove="@(_SourcePath)" />
<_SourcePath Include="$(_SourcePath)" />
<_Args Include="@(_SourcePath->Distinct()->Replace('\', '\\')->'&quot;%(Identity)&quot;')" Condition=" '@(_SourcePath)' != '' " />
<_Args Include="$(_SourcePath)" />

<_ObjectPath Remove="@(_ObjectPath)" />
<_ObjectPath Include="$(_ObjectPath)" />
<_Args Include="@(_ObjectPath->Distinct()->Replace('\', '\\')->'-o &quot;%(Identity)&quot;')" Condition=" '@(_ObjectPath)' != '' " />
<_Args Include="-o" Value="$(_ObjectPath)" Seperator=" " />
</ItemGroup>

<ClangExe ToolExe="$(ClangToolExe)" Arguments="@(_Args)" />

<ItemGroup>
<FileWrites Include="$(_ObjectPath)" />
</ItemGroup>

<CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''" />
</Target>

Expand Down Expand Up @@ -511,56 +522,70 @@
<_Args Include="-shared" Condition=" '$(OutputType)' == 'library' " />
<_Args Include="-static" Condition=" '$(OutputType)' == 'staticlibrary' " />
<_Args Include="-v" Condition=" '$(Verbose)' == 'true' " />
<_Args Include="--target=$(TargetTriple)" />
<_Args Include="-fuse-ld=lld" Condition=" '$(UseLld)' == 'true' " />
<_Args Include="--target" Value="$(TargetTriple)" Seperator="=" />
<_Args Include="-fuse-ld" Value="lld" Seperator="=" Condition=" '$(UseLld)' == 'true' " />
<_Args Include="-g" Condition=" '$(DebugSymbols)' == 'true' " />

<_Args Include="-Xlinker /subsystem:$(Subsystem)" Condition=" '$(Subsystem)' != '' " />
<_Args Include="-Wl,/subsystem:$(Subsystem)" Condition=" '$(Subsystem)' != '' " />

<_SystemRootDirectories Remove="@(_SystemRootDirectories)" />
<_SystemRootDirectories Include="%(Compile.SystemRootDirectories)" />
<_SystemRootDirectories Include="@(SystemRootDirectories)" />
<_SystemRootDirectories Include="$(SystemRootDirectories)" />
<_Args Include="@(_SystemRootDirectories->Distinct()->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'--sysroot &quot;%(Identity)&quot;')" Condition=" '@(_SystemRootDirectories)' != '' " />
<_SystemRootDirectoriesTemp Remove="@(_SystemRootDirectoriesTemp)" />
<_SystemRootDirectoriesTemp Include="@(_SystemRootDirectories->Distinct())" />
<_SystemRootDirectoriesArgs Remove="@(_SystemRootDirectoriesArgs)" />
<_SystemRootDirectoriesArgs Include="@(_SystemRootDirectoriesTemp->'--sysroot')" Value="%(_SystemRootDirectoriesTemp.Identity)" Seperator=" " />
<_Args Include="@(_SystemRootDirectoriesArgs)" />

<_IncludeSystemRootDirectories Remove="@(_IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="%(Compile.IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="@(IncludeSystemRootDirectories)" />
<_IncludeSystemRootDirectories Include="$(IncludeSystemRootDirectories)" />
<_Args Include="@(_IncludeSystemRootDirectories->Distinct()->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'-isysroot &quot;%(Identity)&quot;')" Condition=" '@(_IncludeSystemRootDirectories)' != '' " />
<_IncludeSystemRootDirectoriesTemp Remove="@(_IncludeSystemRootDirectoriesTemp)" />
<_IncludeSystemRootDirectoriesTemp Include="@(_IncludeSystemRootDirectories->Distinct())" />
<_IncludeSystemRootDirectoriesArgs Remove="@(_IncludeSystemRootDirectoriesArgs)" />
<_IncludeSystemRootDirectoriesArgs Include="@(_IncludeSystemRootDirectoriesTemp->'--isysroot')" Value="%(_IncludeSystemRootDirectoriesTemp.Identity)" Seperator=" " />
<_Args Include="@(_IncludeSystemRootDirectoriesArgs)" />

<_LibraryDirectories Remove="@(_LibraryDirectories)" />
<_LibraryDirectories Include="@(LibraryDirectories)" />
<_LibraryDirectories Include="$(LibraryDirectories)" />
<_LibraryDirectories Include="@(ImportedLibraryDirectories)" />
<_Args Include="@(_LibraryDirectories->Distinct()->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'-L &quot;%(Identity)&quot;')" Condition=" '@(_LibraryDirectories)' != '' " />
<_LibraryDirectoriesTemp Remove="@(_LibraryDirectoriesTemp)" />
<_LibraryDirectoriesTemp Include="@(_LibraryDirectories->Distinct())" />
<_LibraryDirectoriesArgs Remove="@(_LibraryDirectoriesArgs)" />
<_LibraryDirectoriesArgs Include="@(_LibraryDirectoriesTemp->'-L')" Value="%(_LibraryDirectoriesTemp.Identity)" Seperator="" />
<_Args Include="@(_LibraryDirectoriesArgs)" />

<_Dependencies Remove="@(_Dependencies)" />
<_Dependencies Include="@(Dependencies)" />
<_Dependencies Include="$(Dependencies)" />
<_Dependencies Include="@(ImportedDependencies)" />
<_Args Include="@(_Dependencies->Distinct()->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'-l &quot;%(Identity)&quot;')" Condition=" '@(_Dependencies)' != '' " />
<_DependenciesTemp Remove="@(_DependenciesTemp)" />
<_DependenciesTemp Include="@(_Dependencies->Distinct())" />
<_DependenciesArgs Remove="@(_DependenciesArgs)" />
<_DependenciesArgs Include="@(_DependenciesTemp->'-l')" Value="%(_DependenciesTemp.Identity)" Seperator="" />
<_Args Include="@(_DependenciesArgs)" />

<_AdditionalOptions Remove="@(_AdditionalOptions)" />
<_AdditionalOptions Include="@(AdditionalLinkOptions)" />
<_AdditionalOptions Include="$(AdditionalLinkOptions)" />
<_Args Include="@(_AdditionalOptions)" />

<_ObjectPath Remove="@(_ObjectPath)" />
<_ObjectPath Include="@(Compile->'%(ObjectPath)')" />
<_Args Include="@(_ObjectPath->Distinct()->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'&quot;%(Identity)&quot;')" />
<_Args Include="@(Compile->'%(ObjectPath)')" />

<_Output Remove="@(_Output)" />
<_Output Include="$(IntermediateOutputPath)$(TargetFileName)" />
<_Args Include="@(_Output->Replace('%5c', '%5c%5c')->Replace('%22', '%5c%22')->'-o &quot;%(Identity)&quot;')" />
<_Args Include="-o" Value="$(IntermediateOutputPath)$(TargetFileName)" Seperator=" " />
</ItemGroup>

<ClangExe ToolExe="$(ClangToolExe)" Arguments="@(_Args)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)$(TargetFileName)" />
<FileWrites Include="$(IntermediateOutputPath)$(LibraryFileName)" />
<FileWrites Include="$(IntermediateOutputPath)$(DebugSymbolsFileName)" />
</ItemGroup>

<CallTarget Targets="$(TargetsTriggeredByLinking)" Condition="'$(TargetsTriggeredByLinking)' != ''" />
</Target>

Expand Down

0 comments on commit 1963e3b

Please sign in to comment.