diff --git a/nuget/Microsoft.WSL.Containers/build/Microsoft.WSL.Containers.common.targets b/nuget/Microsoft.WSL.Containers/build/Microsoft.WSL.Containers.common.targets
index 2454f2555..810c31260 100644
--- a/nuget/Microsoft.WSL.Containers/build/Microsoft.WSL.Containers.common.targets
+++ b/nuget/Microsoft.WSL.Containers/build/Microsoft.WSL.Containers.common.targets
@@ -7,4 +7,116 @@
+
+
+
+
+
+
+
+ $(OutDir)
+ $(ProgramW6432)\WSL\wslc.exe
+ wslc
+
+
+
+
+
+ latest
+ $(WslcImageOutputDir)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WslcSourceDirs Include="$(_WslcSourceDir.Split(';'))" />
+ <_WslcSourceFiles Include="$(_WslcDockerfile)" />
+ <_WslcSourceFiles Include="%(_WslcSourceDirs.Identity)\**\*" Condition="'%(_WslcSourceDirs.Identity)' != ''" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/Microsoft.WSL.Containers/build/native/Microsoft.WSL.Containers.targets b/nuget/Microsoft.WSL.Containers/build/native/Microsoft.WSL.Containers.targets
index 09823c7b0..a9cf3c22e 100644
--- a/nuget/Microsoft.WSL.Containers/build/native/Microsoft.WSL.Containers.targets
+++ b/nuget/Microsoft.WSL.Containers/build/native/Microsoft.WSL.Containers.targets
@@ -23,4 +23,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WslcTlogSourceDirs Include="$(_WslcSourceDir.Split(';'))" />
+ <_WslcTlogInputs Include="$(_WslcDockerfile)" />
+ <_WslcTlogInputs Condition="'%(_WslcTlogSourceDirs.Identity)' != ''" Include="%(_WslcTlogSourceDirs.Identity)\**\*" />
+
+
+
+ <_WslcDockerfileFullPath>$([System.IO.Path]::GetFullPath('$(_WslcDockerfile)'))
+ <_WslcMarkerFullPath>$([System.IO.Path]::GetFullPath('$(IntDir)wslc_$(_WslcName).marker'))
+ <_WslcTarFullPath>$([System.IO.Path]::GetFullPath('$(WslcImageOutputDir)$(_WslcName).tar'))
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/Microsoft.WSL.Containers/build/net/Microsoft.WSL.Containers.targets b/nuget/Microsoft.WSL.Containers/build/net/Microsoft.WSL.Containers.targets
index 245e57a2c..cb1500527 100644
--- a/nuget/Microsoft.WSL.Containers/build/net/Microsoft.WSL.Containers.targets
+++ b/nuget/Microsoft.WSL.Containers/build/net/Microsoft.WSL.Containers.targets
@@ -11,4 +11,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WslcUpToDateDirs Include="%(WslcImage.Sources)" Separator=";" />
+
+
+
+
\ No newline at end of file
diff --git a/nuget/Microsoft.WSL.Containers/buildTransitive/Microsoft.WSL.Containers.targets b/nuget/Microsoft.WSL.Containers/buildTransitive/Microsoft.WSL.Containers.targets
new file mode 100644
index 000000000..b5ada5ff6
--- /dev/null
+++ b/nuget/Microsoft.WSL.Containers/buildTransitive/Microsoft.WSL.Containers.targets
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/nuget/Microsoft.WSL.Containers/buildTransitive/native/Microsoft.WSL.Containers.targets b/nuget/Microsoft.WSL.Containers/buildTransitive/native/Microsoft.WSL.Containers.targets
new file mode 100644
index 000000000..0f50deabc
--- /dev/null
+++ b/nuget/Microsoft.WSL.Containers/buildTransitive/native/Microsoft.WSL.Containers.targets
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/nuget/Microsoft.WSL.Containers/cmake/Microsoft.WSL.ContainersConfig.cmake b/nuget/Microsoft.WSL.Containers/cmake/Microsoft.WSL.ContainersConfig.cmake
index 0ea5f0642..07a38e4ae 100644
--- a/nuget/Microsoft.WSL.Containers/cmake/Microsoft.WSL.ContainersConfig.cmake
+++ b/nuget/Microsoft.WSL.Containers/cmake/Microsoft.WSL.ContainersConfig.cmake
@@ -55,3 +55,92 @@ unset(_wslcsdk_arch)
unset(_wslcsdk_root)
unset(_wslcsdk_include_dir)
unset(_wslcsdk_lib_dir)
+
+# ============================================================================
+# Container Image Build Targets
+# ============================================================================
+#
+# Provides the wslc_add_image() function for declaring container image
+# build targets with incremental rebuild support.
+#
+# Usage:
+# find_package(Microsoft.WSL.Containers REQUIRED)
+#
+# wslc_add_image(
+# NAME my-server
+# DOCKERFILE container/Dockerfile
+# CONTEXT container/
+# SOURCES container/src/*.cpp container/src/*.h
+# TAG latest
+# OUTPUT ${CMAKE_BINARY_DIR}/images
+# )
+#
+# # With explicit image registry/name (IMAGE defaults to NAME if omitted):
+# wslc_add_image(
+# NAME my-server
+# IMAGE ghcr.io/myorg/my-server
+# TAG v1.2.3
+# DOCKERFILE container/Dockerfile
+# CONTEXT container/
+# )
+
+function(wslc_add_image)
+ cmake_parse_arguments(
+ PARSE_ARGV 0 ARG
+ "" # options (none)
+ "NAME;IMAGE;TAG;DOCKERFILE;CONTEXT;OUTPUT" # one-value keywords
+ "SOURCES" # multi-value keywords
+ )
+
+ # Validate required arguments
+ if(NOT ARG_NAME)
+ message(FATAL_ERROR "wslc_add_image: NAME is required")
+ endif()
+ if(NOT ARG_DOCKERFILE)
+ message(FATAL_ERROR "wslc_add_image: DOCKERFILE is required")
+ endif()
+ if(NOT ARG_CONTEXT)
+ message(FATAL_ERROR "wslc_add_image: CONTEXT is required")
+ endif()
+
+ # Defaults
+ if(NOT ARG_IMAGE)
+ set(ARG_IMAGE "${ARG_NAME}")
+ endif()
+ if(NOT ARG_TAG)
+ set(ARG_TAG "latest")
+ endif()
+ if(NOT ARG_OUTPUT)
+ set(ARG_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
+
+ # Find wslc CLI
+ if(NOT WSLC_CLI_PATH)
+ find_program(WSLC_CLI_PATH wslc PATHS "$ENV{ProgramW6432}/WSL" "$ENV{ProgramFiles}/WSL")
+ if(NOT WSLC_CLI_PATH)
+ message(FATAL_ERROR "wslc CLI not found. Install WSL by running: wsl --install --no-distribution")
+ endif()
+ endif()
+
+ set(_image_ref "${ARG_IMAGE}:${ARG_TAG}")
+ set(_marker "${CMAKE_CURRENT_BINARY_DIR}/wslc_${ARG_NAME}.marker")
+ set(_tar_output "${ARG_OUTPUT}/${ARG_NAME}.tar")
+
+ # Resolve source globs to file lists
+ file(GLOB_RECURSE _resolved_sources CONFIGURE_DEPENDS ${ARG_SOURCES})
+
+ add_custom_command(
+ OUTPUT "${_marker}"
+ COMMAND "${WSLC_CLI_PATH}" image build -t "${_image_ref}" -f "${ARG_DOCKERFILE}" "${ARG_CONTEXT}"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${ARG_OUTPUT}"
+ COMMAND "${WSLC_CLI_PATH}" image save -o "${_tar_output}" "${_image_ref}"
+ COMMAND ${CMAKE_COMMAND} -E touch "${_marker}"
+ DEPENDS ${_resolved_sources} "${ARG_DOCKERFILE}"
+ COMMENT "WSLC: Building and saving image '${_image_ref}' to '${_tar_output}'..."
+ VERBATIM
+ )
+
+ add_custom_target(wslc_image_${ARG_NAME} ALL
+ DEPENDS "${_marker}"
+ )
+endfunction()