Skip to content

Rewrite hostmisc C++ components to wrap C implementations#126367

Draft
Copilot wants to merge 15 commits intomainfrom
copilot/rewrite-apphost-in-c
Draft

Rewrite hostmisc C++ components to wrap C implementations#126367
Copilot wants to merge 15 commits intomainfrom
copilot/rewrite-apphost-in-c

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

Description

Eliminates code duplication between the C++ hostmisc library and the C hostmisc_c library by rewriting C++ components to delegate to existing C implementations.

fx_ver.cpp → wraps fx_ver.c

  • fx_ver_t::parse(), compare(), as_str() now delegate to c_fx_ver_parse(), c_fx_ver_compare(), c_fx_ver_as_str()
  • C struct renamed to c_fx_ver_t to avoid collision with the C++ class
  • Added palstr_to_narrow()/narrow_to_palstr() helpers for wchar_tchar conversion on Windows

utils.cpp → wraps utils.c (non-Windows only)

  • get_current_arch_name(), get_runtime_id(), get_host_version_description() delegate to C equivalents
  • get_dotnet_root_env_var_for_arch() kept as C++ — the C version doesn't accept an arch parameter

trace.cpp → removed (prior commit)

  • trace.h is now a thin C++ wrapper over trace.c
  • g_trace_lock uses minipal mutex APIs
  • trace.c uses pal functions (pal_getenv, pal_xtoi, pal_strlen, pal_str_vprintf, pal_strlen_vprintf, pal_str_printf) instead of platform-specific inline definitions
  • Thread-local storage uses PAL_THREAD_LOCAL macro from pal_c.h

Header updates

  • Added extern "C" guards to fx_ver_c.h, utils_c.h, pal_c.h
  • Added #ifndef macro guards in utils_c.h to prevent redefinition conflicts with utils.h

pal.h includes pal_c.h

  • pal.h now includes pal_c.h to get shared definitions instead of duplicating them
  • Removed duplicated _X, _STRINGIFY, DIR_SEPARATOR, DIR_SEPARATOR_STR, PATH_SEPARATOR, S_OK, E_NOTIMPL, E_FAIL, SUCCEEDED, LIB_PREFIX, LIB_FILE_EXT, LIB_NAME, LIB_FILE_NAME, LIB_FILE_NAME_X, LIBFXR_NAME, HOST_RID_PLATFORM, and PATH_MAX from pal.h

File naming convention

  • Dropped the apphost_ prefix from all hostmisc C files so they live next to their corresponding .cpp files (e.g., trace.c next to trace.h, utils.c next to utils.cpp)
  • C headers use a _c suffix to distinguish from C++ headers (e.g., trace_c.h, fx_ver_c.h, pal_c.h, utils_c.h, fxr_resolver_c.h, bundle_marker_c.h)

pal_c.h — cross-platform PAL for C

  • pal_c.h is the canonical location for the pal_char_t typedef (wchar_t on Windows, char on non-Windows), _X, _STRINGIFY, and PAL_THREAD_LOCAL macros
  • pal_c.h is structured to be includable on all platforms: cross-platform types/macros at the top, then platform-specific sections for Windows (windows.h, wide-char string ops, pal_getenv/pal_xtoi as static inlines) and non-Windows (configure.h, POSIX string ops, pal_getenv/pal_xtoi function declarations)
  • Cross-platform macros: DIR_SEPARATOR, PATH_SEPARATOR, LIB_PREFIX, LIB_FILE_EXT, HOST_RID_PLATFORM, LIBFXR_NAME
  • Cross-platform string ops: pal_strlen, pal_str_vprintf, pal_strlen_vprintf, pal_str_printf
  • Macro definitions use #ifndef guards to avoid redefinition conflicts with pal.h (C++ PAL)
  • trace_c.h includes pal_c.h for the typedef instead of defining pal_char_t locally
  • All function signatures in pal_c.h, pal.c, utils_c.h, and utils.c use pal_char_t instead of raw char

Dynamic path buffer allocation

  • Changed hostfxr_resolver_t struct to use char* pointers instead of fixed char[4096] arrays for dotnet_root and fxr_path
  • Changed fxr_resolver_try_get_path API to return dynamically allocated strings via char** output parameters (caller must free)
  • Converted local path buffers in apphost_main.c, apphost_hostfxr_resolver.c, and fxr_resolver.c from stack-allocated APPHOST_PATH_MAX arrays to heap-allocated buffers with malloc/free
  • Added utils_file_exists_in_dir_alloc and utils_get_directory_alloc helper functions that return dynamically allocated strings
  • hostfxr_resolver_cleanup now frees the dynamically allocated dotnet_root and fxr_path strings

Build

  • fx_ver.c added to hostmisc on all platforms
  • pal.c, utils.c added on non-Windows only

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>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@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.

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>
{
void* hostfxr_dll;
char dotnet_root[4096];
char fxr_path[4096];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Please adjust these buffers to be dynamically allocated in case the path is longer than this buffer length (throughout).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 2b8c310. Changed hostfxr_resolver_t to use char* with dynamic allocation. Changed fxr_resolver_try_get_path API to return malloc'd strings via char** (caller frees). Converted all local path buffers in apphost_main.c, apphost_hostfxr_resolver.c, and fxr_resolver.c to use malloc/free. Added utils_file_exists_in_dir_alloc and utils_get_directory_alloc helpers that return dynamically allocated strings.

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>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@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...

Already done in 7b1a73c.

Comment on lines +11 to +44
#if defined(_WIN32)
#include <windows.h>
#define trace_getenv(name, buf, buf_len) (GetEnvironmentVariableW(name, buf, (DWORD)(buf_len)) > 0)
#define trace_xtoi(s) _wtoi(s)
#define trace_vsnprintf_len(fmt, args) _vscwprintf(fmt, args)
#define trace_vsnprintf(buf, count, fmt, args) _vsnwprintf_s(buf, count, _TRUNCATE, fmt, args)
#define trace_snprintf(buf, count, fmt, ...) _snwprintf_s(buf, count, _TRUNCATE, fmt, __VA_ARGS__)
#define trace_strlen wcslen
#else
#define trace_xtoi(s) atoi(s)
#define trace_vsnprintf_len(fmt, args) vsnprintf(NULL, 0, fmt, args)
#define trace_vsnprintf(buf, count, fmt, args) vsnprintf(buf, (size_t)(count), fmt, args)
#define trace_snprintf(buf, count, fmt, ...) snprintf(buf, (size_t)(count), fmt, __VA_ARGS__)
#define trace_strlen strlen

static bool trace_getenv(const char* name, char* recv, size_t recv_len)
{
if (recv_len > 0)
recv[0] = '\0';

const char* result = getenv(name);
if (result != NULL && result[0] != '\0')
{
size_t len = strlen(result);
if (len >= recv_len)
return false;

memcpy(recv, result, len + 1);
return true;
}

return false;
}
#endif
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot these should use pal functions instead of having platform-specific definitions inside trace.c

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in e665819. Replaced all platform-specific macros in trace.c (lines 11-44) with pal functions from pal_c.h: trace_getenvpal_getenv, trace_xtoipal_xtoi, trace_vsnprintf_lenpal_strlen_vprintf, trace_vsnprintfpal_str_vprintf, trace_snprintfpal_str_printf, trace_strlenpal_strlen. Also replaced the platform-specific thread-local storage with a PAL_THREAD_LOCAL macro.

#define PAL_CHAR_T_DEFINED
typedef wchar_t pal_char_t;
#endif
#ifndef _X
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Make pal.h include pal_c.h and remove the duplicated defines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in e665819. pal.h now includes pal_c.h and all duplicated defines have been removed: _X, _STRINGIFY, DIR_SEPARATOR, PATH_SEPARATOR, S_OK, E_NOTIMPL, E_FAIL, SUCCEEDED, LIB_PREFIX, LIB_FILE_EXT, LIB_NAME, LIB_FILE_NAME, LIB_FILE_NAME_X, LIBFXR_NAME, HOST_RID_PLATFORM, PATH_MAX, and configure.h.

…functions

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/37b4c326-f8c9-4b5f-bbf3-20b79f13538a

Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
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.

3 participants