Skip to content

[Build] Add per-file up-to-date check in CompileNativeAssembly#11055

Draft
davidnguyen-tech wants to merge 2 commits intodotnet:mainfrom
davidnguyen-tech:feature/compile-native-assembly-skip-unchanged
Draft

[Build] Add per-file up-to-date check in CompileNativeAssembly#11055
davidnguyen-tech wants to merge 2 commits intodotnet:mainfrom
davidnguyen-tech:feature/compile-native-assembly-skip-unchanged

Conversation

@davidnguyen-tech
Copy link
Copy Markdown
Member

Summary

Adds per-file timestamp comparison in the CompileNativeAssembly task to skip recompilation of .ll files whose .o output is already up-to-date. This avoids unnecessary llc invocations on incremental CoreCLR builds.

Problem

_CompileNativeAssemblySources recompiles ALL .ll.o files whenever ANY .ll file changes, because MSBuild's target-level Inputs/Outputs is all-or-nothing. On incremental CoreCLR builds, upstream generators already use Files.CopyIfStreamChanged to preserve timestamps on unchanged .ll files, but the CompileNativeAssembly task has no per-file granularity — it recompiles everything when the target runs.

Fix

Before running llc for each source file in RunAssembler(), check if the output .o file exists and its timestamp is ≥ the input .ll file's timestamp. If so, skip that file and emit a debug log message.

This preserves parallel compilation of changed files while skipping unchanged ones individually.

Expected Savings

On incremental CoreCLR builds where only typemaps change (due to assembly MVID changes), other .ll files (environment, marshal_methods, jni_remap) are skipped, saving roughly 50-70% of the ~2.85s _CompileNativeAssemblySources cost.

Testing

  • Added CompileNativeAssemblySourcesSkipsUnchangedFiles integration test that verifies:
    • _CompileNativeAssemblySources target still runs (not skipped at target level)
    • At least one .ll file is skipped at the per-file level (via log message assertion)

davidnguyen-tech and others added 2 commits March 30, 2026 19:16
When _CompileNativeAssemblySources runs, it recompiles ALL .ll files
even if only some have changed. This is because MSBuild's target-level
Inputs/Outputs is all-or-nothing — if any .ll file is newer than any
.o file, every file gets recompiled.

Add a per-file timestamp check in RunAssembler() — if the output .o is
newer than the input .ll, that file is skipped. This saves time on
incremental CoreCLR builds where upstream generators use
CopyIfStreamChanged to preserve .ll timestamps for unchanged files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add CompileNativeAssemblySourcesSkipsUnchangedFiles integration test
that verifies on incremental CoreCLR builds, unchanged .ll files are
not recompiled by the CompileNativeAssembly task while changed .ll
files are still correctly compiled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@davidnguyen-tech davidnguyen-tech force-pushed the feature/compile-native-assembly-skip-unchanged branch from 41fdedd to f644fca Compare March 30, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant