Skip to content

Convert non-Windows apphost to C#126367

Open
jkoritzinsky with Copilot wants to merge 81 commits into
mainfrom
copilot/rewrite-apphost-in-c
Open

Convert non-Windows apphost to C#126367
jkoritzinsky with Copilot wants to merge 81 commits into
mainfrom
copilot/rewrite-apphost-in-c

Conversation

Copilot AI commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Convert non-Windows apphost to C. On windows, we still have apphost.windows.cpp and it remains C++. dotnet and singlefilehost also remain C++.

  • Separate entry points for apphost and dotnet
    • apphost entry point is apphost.c, shared by the standalone apphost and singlefilehost.
    • dotnet entry point is dotnet.cpp
    • Remove corehost.cpp
  • hostfxr resolvers:
    • apphost resolver is now C
    • singlefilehost keeps its C++ resolver for statically-linked hostfxr
    • dotnet resolver is separate and under the dotnet folder

Copilot AI and others added 10 commits March 27, 2026 05:20
Create C source files for apphost that replace the C++ implementation:
- apphost_main.c: main entry point
- apphost_pal.c/h: platform abstraction layer (Unix)
- apphost_trace.c/h: tracing system
- apphost_utils.c/h: utility functions
- apphost_fx_ver.c/h: semantic version parsing
- apphost_fxr_resolver.c/h: hostfxr path resolution
- apphost_bundle_marker.c/h: bundle detection
- apphost_hostfxr_resolver.c/h: hostfxr loading

Uses dn-vector from src/native/containers for collections.
Windows builds retain existing C++ sources.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c33d365-8b70-4325-8eee-7f004ba86639

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
- Add stddef.h includes for size_t in headers
- Fix HAVE_DIRENT_D_TYPE guard to use config.h
- Fix dn_vector_at calls to pass element size
- Add test_only_getenv for test install location overrides
- Add test overrides in pal_get_dotnet_self_registered_dir and pal_get_default_installation_dir
- Add ctype.h include for tolower

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c33d365-8b70-4325-8eee-7f004ba86639

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
- Remove dead code block (always-false DIR_SEPARATOR check) in apphost_main.c
- Remove unused free_string_entry function in apphost_fxr_resolver.c
- Add explicit errno.h include in apphost_pal.c

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c33d365-8b70-4325-8eee-7f004ba86639

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Move C source files from apphost/standalone/ to hostmisc/:
- apphost_trace.c/h, apphost_pal.c/h, apphost_utils.c/h
- apphost_fx_ver.c/h, apphost_fxr_resolver.c/h, apphost_bundle_marker.c/h

Create hostmisc_c OBJECT library target in hostmisc/CMakeLists.txt
with proper include directories and dependencies.

Update apphost/standalone/CMakeLists.txt to use hostmisc_c and
dn-containers CMake targets instead of compiling C files directly.

Add dn-containers subdirectory to corehost and singlefilehost builds
for non-Windows platforms.

Update apphost_fxr_resolver.c to use <dn-vector.h> include path
consistent with the dn-containers CMake target.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6be87a85-902f-4646-92e6-2fb6783a5f57

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Rewrite bundle_marker.h as a C++ wrapper around the C implementation
in apphost_bundle_marker.c. Add extern "C" guards to
apphost_bundle_marker.h for C++ compatibility.

Remove bundle_marker.cpp since the C implementation in hostmisc_c
(apphost_bundle_marker.c) is now the single source of truth.

Update standalone/CMakeLists.txt and static/CMakeLists.txt to use
apphost_bundle_marker.c instead of the removed bundle_marker.cpp.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/65fd3a5e-99f8-4acc-830f-644976f2cfb1

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…mutex

- Removed trace.cpp (C++ implementation)
- Updated apphost_trace.h: Added pal_char_t typedef (wchar_t on Windows,
  char on Unix), extern C guards, va_list function variants
- Updated apphost_trace.c: Added Windows support (wide chars, OutputDebugStringW,
  WriteConsoleW), replaced spinlock with minipal mutex, added _v versions
  of variadic functions for C++ forwarding
- Updated trace.h: Now a thin C++ wrapper calling C functions via va_list
- Updated CMakeLists.txt: Use apphost_trace.c instead of trace.cpp, add
  minipal/mutex.c to both hostmisc and hostmisc_c"

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c57cab1-6ebb-4ab7-bbbf-38835b4336b3

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Inline the getenv and xtoi helpers directly in apphost_trace.c
to avoid depending on apphost_pal.c which is only in hostmisc_c."

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c57cab1-6ebb-4ab7-bbbf-38835b4336b3

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
- trace_error_v: Copy va_list before any consumption to avoid
  using a consumed va_list (undefined behavior per C11 §7.16.1)
- trace_warning: Delegate to trace_warning_v instead of duplicating
  the implementation inline

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2c57cab1-6ebb-4ab7-bbbf-38835b4336b3

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
- fx_ver.cpp: Rewrite to delegate to apphost_fx_ver.c for parse(),
  compare(), and as_str() operations. Handles char/wchar_t conversion
  for Windows compatibility.
- utils.cpp: On non-Windows, delegate get_current_arch_name(),
  get_runtime_id(), get_host_version_description(), and
  get_dotnet_root_env_var_for_arch() to apphost_utils.c.
- apphost_fx_ver.h: Add extern "C" guards, rename to c_fx_ver_t to
  avoid collision with C++ fx_ver_t struct.
- apphost_utils.h: Add extern "C" guards, guard macros with #ifndef
  to avoid conflicts with utils.h.
- apphost_pal.h: Add extern "C" guards.
- CMakeLists.txt: Add apphost_fx_ver.c to all platforms, add
  apphost_pal.c and apphost_utils.c on non-Windows.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/15a555ca-6237-4c3e-9a6a-93b3c993d1e9

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
- Revert get_dotnet_root_env_var_for_arch to C++ implementation
  since the C version ignores the arch parameter
- Replace 'auto' with explicit 'pal::char_t' in palstr_to_narrow

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/15a555ca-6237-4c3e-9a6a-93b3c993d1e9

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
@elinor-fung

This comment was marked as resolved.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

Rename all hostmisc C files per review feedback:
- apphost_trace.c → trace.c, apphost_trace.h → trace_c.h
- apphost_fx_ver.c → fx_ver.c, apphost_fx_ver.h → fx_ver_c.h
- apphost_pal.c → pal.c, apphost_pal.h → pal_c.h
- apphost_utils.c → utils.c, apphost_utils.h → utils_c.h
- apphost_fxr_resolver.c → fxr_resolver.c, apphost_fxr_resolver.h → fxr_resolver_c.h
- apphost_bundle_marker.c → bundle_marker.c, apphost_bundle_marker.h → bundle_marker_c.h

Update all #include directives, CMakeLists.txt references, header guards,
and comments to use the new names.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/869a7b2a-c34a-4b37-ab96-28caca72225e

Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>

Copilot AI commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

@copilot rename the hostmisc C files prefixed with apphost_ to drop the apphost_ prefix. They should be .c versions living next to their corresponding .cpp files. For the header files, they can ha...

Done in 7b1a73c. Renamed all hostmisc C files to drop the apphost_ prefix (e.g., apphost_trace.ctrace.c) and headers to use _c suffix (e.g., apphost_trace.htrace_c.h). Updated all #include directives, CMakeLists.txt references, and header guards.

Comment thread src/native/corehost/hostmisc/pal.c Outdated
Move the pal_char_t typedef from trace_c.h to pal_c.h as the canonical
location. Define it cross-platform (wchar_t on Windows, char on non-Windows)
with #ifndef guards to avoid redefinition conflicts with pal.h (C++ PAL).

Update function signatures in pal_c.h, pal.c, utils_c.h, and utils.c to
use pal_char_t instead of raw char for platform string parameters.

Make trace_c.h include pal_c.h for the typedef instead of defining it
locally. Restructure pal_c.h to be includable on all platforms (cross-
platform types at top, POSIX-specific parts guarded with #if !defined(_WIN32)).

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/88526fd5-afd6-42dc-b551-5b6cd904b449

Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Comment thread src/native/corehost/apphost/standalone/apphost_hostfxr_resolver.h Outdated
Change hostfxr_resolver_t struct to use char* instead of char[4096].
Change fxr_resolver_try_get_path API to return malloc'd strings via char**
instead of writing to fixed-size caller-provided buffers.
Convert local path buffers in apphost_main.c and fxr_resolver.c to use
malloc/free instead of stack-allocated fixed arrays.
Add utils_file_exists_in_dir_alloc and utils_get_directory_alloc helpers
that return dynamically allocated strings.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/84b0096a-a181-477e-a6b7-04df74e9919c

Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
elinor-fung and others added 2 commits July 2, 2026 13:54
createdump_static is only built and linked on macOS and non-x86/non-Android
Linux, but apphost_static_init's guard had been widened to HOST_UNIX, so it
referenced initialize_static_createdump on other Unix targets (e.g. FreeBSD)
where the library isn't linked. Define FEATURE_STATIC_CREATEDUMP from the same
CMake condition that links createdump_static and gate the call on it, so the
guard and the link cannot drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…uard

- static hostfxr_resolver_init: allocate dotnet_root/fxr_path into locals and
  assign them into the resolver only after both allocations succeed, so it is
  never left partially initialized on OOM.
- utils_get_host_version_description: guard against a NULL or zero-length output
  buffer before formatting, matching the other utils_* helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/native/corehost/apphost/apphost.c Outdated
Drop utils_get_host_version_description and emit the version string
directly at the trace call: VER_PRODUCTVERSION_STR on Windows, sccsid
on Unix. Addresses PR feedback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 3

Comment thread src/native/corehost/hostmisc/pal.windows.c Outdated
Comment thread src/native/corehost/hostmisc/pal.windows.c
Comment thread src/native/corehost/apphost/apphost.c
elinor-fung and others added 2 commits July 2, 2026 17:03
- apphost: reject an empty embedded binding, preserving the prior
  behavior where an empty app DLL name failed conversion on Windows.
- pal.windows: initialize the out handle to NULL so callers never
  observe an uninitialized value after a failed load, and free the
  loaded module if pinning it fails.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Provide a Unix implementation of pal_utf8_to_palstr (a length-checked
copy, since pal_char_t is already UTF-8 char there) so callers no longer
need a platform ifdef around the Windows conversion and a Unix memcpy.
The embedded-path handling in apphost and the standalone resolver now
just call the PAL helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/native/corehost/apphost/apphost.c Outdated
Copilot AI and others added 3 commits July 6, 2026 19:46
Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Concatenate HOST_VERSION/REPO_COMMIT_HASH (and VER_PRODUCTVERSION_STR on
Windows) directly into the trace format string instead of formatting
them into a buffer with pal_str_printf. These are all compile-time
macros, so the message is built at compile time.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 1

Comment thread src/native/corehost/apphost/standalone/apphost_hostfxr_resolver.c
elinor-fung and others added 4 commits July 8, 2026 13:44
- Use DIR_SEPARATOR directly for the embedded-name separator check
  instead of probing for both / and \ (the Windows loop above already
  normalizes / to DIR_SEPARATOR).
- Build the app-relative .NET path with the existing
  utils_append_path_alloc helper instead of open-coding the allocation.
- Rename need_newer_framework_error to report_outdated_framework_error
  and size its download URL buffer with MAX_DOWNLOAD_URL_LEN.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The dotnet muxer's fxr_resolver_try_get_path ignores the search
location argument, so the single-use s_dotnet_search_location constant
added no value. Pass fxr_search_location_default directly instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Cache the bundle_marker_is_bundle() result in exe_start instead of
  calling it twice.
- Use pal_strdup in the static resolver instead of open-coding the
  size calculation, allocation, and copy.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Hoist the .NET search embed size to a file-scope EMBED_DOTNET_SEARCH_SIZE
  define so the embed array and the app_relative_dotnet buffer share one
  constant instead of a duplicated literal.
- Drop the unused <cinttypes> include from the dotnet muxer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 2

Comment thread src/native/corehost/hostmisc/pal.windows.c Outdated
Comment thread src/native/corehost/hostmisc/pal.unix.c Outdated
Define pal_proc_t (FARPROC on Windows, void* on Unix) mirroring
pal::proc_t, and return it from pal_get_symbol. On Windows this removes
the union in pal_get_symbol and avoids any data/function pointer
conversion: the resolved symbol stays a function pointer that callers
cast directly to the target function type. The pal_dll_t and pal_proc_t
typedefs live in the existing platform ifdef sections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 1

Comment thread src/native/corehost/hostmisc/pal.windows.cpp
- pal_load_library takes a pal_dll_t* instead of void**, so the C++
  pal::load_library wrapper no longer reinterpret_casts an HMODULE* to
  void** and writes a void* through a mismatched pointer type. The
  apphost resolver's hostfxr handle becomes pal_dll_t to match.
- Remove the redundant pal::proc_t typedef; pal::get_symbol returns the
  C pal_proc_t directly, so no reinterpret_cast is needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 0 new

@elinor-fung

Copy link
Copy Markdown
Member

@copilot what is the size impact of this change on non-Windows apphosts?

Copilot AI commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot what is the size impact of this change on non-Windows apphosts?

On a local linux-x64 Release build, comparing the current branch to the pre-PR baseline (ad0692a2a5, before the apphost conversion commits), the non-Windows apphost is smaller now:

  • apphost: 39,352 -> 31,944 bytes (-7,408, -18.8%)
  • .text in apphost: 18,330 -> 14,493 (-3,837)
  • singlefilehost: 10,809,016 -> 10,808,312 bytes (-704, effectively flat)

So the earlier size regression was transient while dn-containers was still in the picture. With the latest branch state, I’m not seeing a net size increase for the non-Windows apphost on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

6 participants