У меня есть странное решение, где мне нужен один из проектов для «компиляции» файлов в другом.MSBuild пользовательская задача в зависимости от другого проекта
Компилятор (показать здесь минимальный пример) выглядит следующим образом (MSBuild пользовательских задач):
public class MyCompileTask : Task
{
[Required]
public ITaskItem[] InputFiles { get; set; }
[Output]
public ITaskItem[] OutputFiles { get; set; }
public override bool Execute()
{
var generatedFileNames = new List<string>();
foreach (var inputFile in this.InputFiles)
{
var inputFileName = inputFile.ItemSpec;
var outputFileName = Path.ChangeExtension(inputFileName, ".res.txt");
var source = File.ReadAllText(inputFileName);
var compiled = source.ToUpper();
File.WriteAllText(outputFileName, compiled + "\n\n" + DateTime.Now);
generatedFileNames.Add(outputFileName);
}
this.OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray();
return true;
}
}
Как вы видите, это uppercases только содержание входных файлов.
Это был проект A - библиотека «компилятор».
Проект B, на данный момент основное приложение, имеет файл «lorem.txt», который должен быть «скомпилирован» в «lorem.res.txt» и помещен как EmbeddedResource в B.exe/B.dll.
В B.csproj я добавил следующее:.
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);InvokeMyCompile</CoreCompileDependsOn>
</PropertyGroup>
<UsingTask TaskName="MyCompiler.MyCompileTask" AssemblyFile="$(MSBuildProjectDirectory)\..\MyCompiler\bin\$(Configuration)\MyCompiler.dll" />
<Target Name="MyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt">
<MyCompileTask InputFiles="lorem.txt">
<Output TaskParameter="OutputFiles" PropertyName="OutputFiles" />
</MyCompileTask>
</Target>
<Target Name="InvokeMyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt">
<Exec Command=""$(MSBuildBinPath)\MSBuild.exe" /t:MyCompile "$(ProjectDir)$(ProjectFileName)"" />
</Target>
(2 слоев мишеней и явный вызов MSBuild.exe обходной путь to another problem В самом деле, большая часть этого примера украден из этого Q .)
Важнейшая часть работ, то есть когда я меняю lorem.txt и строю, lorem.res.txt восстанавливается.
Однако:
- Когда lorem.res.txt физически удален, накопление ничего не делает (говорит, что это уточненный), пока я на самом деле обновить проект в VS. Таким образом, MSBuild не «знает», что для создания проекта на самом деле требуется lorem.res.txt.
- Что еще более важно, когда я меняю что-либо в проекте A, проект B перекомпилирует, но не перезапускает компиляцию lorem.txt -> lorem.res.txt. Поэтому MSBuild не «знает», что преобразование зависит от другого проекта.
Как объявить эти зависимости в файле csproj?
Бонусный вопрос: как пометить выходной файл (lorem.res.txt) как сгенерированный EmbeddedResource, поэтому мне не нужно отслеживать его в VS, но он все еще помещается в сборку?
Добавление MyCompiler.dll к входам может иметь дело с последней точкой. Кроме того, вместо использования CoreCompileDependsOn вы можете просто добавить * BeforeTargets = "Build" * к цели, поэтому выполнение не зависит от возможных других механизмов, определяющих, является ли проект актуальным или нет. – stijn
Что вы подразумеваете под «Как объявить эти зависимости в файле csproj?» –
Вы решаете проблему, если проблема все еще существует, пожалуйста, сообщите мне об этом. –