From 731dc751f90eb4fb33df84b261a8d394ceacba2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Fri, 19 Apr 2024 16:14:27 -0400 Subject: [PATCH] [cdac] link a stub contract descriptor if cdac-build-tool is not available (#101297) * [cdac] link a stub contract descriptor if cdac-build-tool is not available Fixes builds that use src/coreclr/build-runtime.sh directly, or bringup scenarios without msbuild * Use DOTNET_HOST_PATH to run cdac-build-tool Related to https://github.com/dotnet/installer/pull/19534#issuecomment-2066570507 it's only unset by .NET Framework which is not supported by runtime.proj --------- Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 78 +++++++++++-------- .../runtimeinfo/contractdescriptorstub.c | 39 ++++++++++ src/coreclr/runtime.proj | 1 + 3 files changed, 85 insertions(+), 33 deletions(-) create mode 100644 src/coreclr/debug/runtimeinfo/contractdescriptorstub.c diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index 2a4cfc2dca3ff5..77ecf9a4dd9bad 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -38,45 +38,57 @@ endif() # publish runtimeinfo lib install_clr(TARGETS runtimeinfo DESTINATIONS lib COMPONENT runtime) -add_library(cdac_data_descriptor OBJECT datadescriptor.cpp) -# don't build the data descriptor before the VM (and any of its dependencies' generated headers) -add_dependencies(cdac_data_descriptor cee_wks_core) -if(CLR_CMAKE_TARGET_WIN32) - # turn off whole program optimization: - # 1. it creates object files that cdac-build-tool can't read - # 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped - target_compile_options(cdac_data_descriptor PRIVATE /GL-) -endif() -target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}) -target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) -target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc) - -set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac") -set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") -if("${CDAC_BUILD_TOOL_BINARY_PATH}" STREQUAL "" OR NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") - message(FATAL_ERROR "No cdac-build-tool set or ${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") -endif() -set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc") +# cDAC contract descriptor + +if (NOT CDAC_BUILD_TOOL_BINARY_PATH) + # if CDAC_BUILD_TOOL_BINARY_PATH is unspecified (for example for a build without a .NET SDK or msbuild), + # link a stub contract descriptor into the runtime + add_library_clr(cdac_contract_descriptor OBJECT contractdescriptorstub.c) + message(STATUS "Using a stub cDAC contract descriptor") +else() + # generate a contract descriptor using cdac-build-tool from a data descriptor and contract json file + + add_library(cdac_data_descriptor OBJECT datadescriptor.cpp) + # don't build the data descriptor before the VM (and any of its dependencies' generated headers) + add_dependencies(cdac_data_descriptor cee_wks_core) + if(CLR_CMAKE_TARGET_WIN32) + # turn off whole program optimization: + # 1. it creates object files that cdac-build-tool can't read + # 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped + target_compile_options(cdac_data_descriptor PRIVATE /GL-) + endif() + target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}) + target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) + target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc) + + set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac") + set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") + if(NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") + message(FATAL_ERROR "${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") + endif() -# generate the contract descriptor by running cdac-build-tool -# n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory -add_custom_command( + set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc") + + # generate the contract descriptor by running cdac-build-tool + # n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory + add_custom_command( OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}" VERBATIM - COMMAND dotnet ${CDAC_BUILD_TOOL_BINARY_PATH} compose -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -c "${CONTRACT_FILE}" $ + COMMAND ${CLR_DOTNET_HOST_PATH} ${CDAC_BUILD_TOOL_BINARY_PATH} compose -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -c "${CONTRACT_FILE}" $ DEPENDS cdac_data_descriptor cee_wks_core $ "${CONTRACT_FILE}" USES_TERMINAL -) + ) -# It is important that cdac_contract_descriptor is an object library; -# if it was static, linking it into the final dll would not export -# DotNetRuntimeContractDescriptor since it is not referenced anywhere. -add_library_clr(cdac_contract_descriptor OBJECT + # It is important that cdac_contract_descriptor is an object library; + # if it was static, linking it into the final dll would not export + # DotNetRuntimeContractDescriptor since it is not referenced anywhere. + add_library_clr(cdac_contract_descriptor OBJECT "${CONTRACT_DESCRIPTOR_OUTPUT}" contractpointerdata.cpp -) -target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}) -target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) -target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc) -add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core) + ) + target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}) + target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) + target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc) + add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core) +endif() diff --git a/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c b/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c new file mode 100644 index 00000000000000..59421a6692d2a7 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __attribute__((visibility("default"))) +#endif + +struct DotNetRuntimeContractDescriptor +{ + uint64_t magic; + uint32_t flags; + const uint32_t descriptor_size; + const char *descriptor; + const uint32_t pointer_data_count; + uint32_t pad0; + const uintptr_t *pointer_data; +}; + +extern const uintptr_t contractDescriptorPointerData[]; + +// just the placeholder pointer +const uintptr_t contractDescriptorPointerData[] = { (uintptr_t)0 }; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; + +#define STUB_DESCRIPTOR "{\"version\":0,\"baseline\":\"empty\",\"contracts\":{},\"types\":{},\"globals\":{}}" + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { + .magic = 0x0043414443434e44ull, // "DNCCDAC\0" + .flags = 0x1u & (sizeof(void*) == 4 ? 0x02u : 0x00u), + .descriptor_size = sizeof(STUB_DESCRIPTOR), + .descriptor = STUB_DESCRIPTOR, + .pointer_data_count = 1, + .pointer_data = &contractDescriptorPointerData[0], +}; diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index c231ebd07a80e8..814d4dba29f707 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -50,6 +50,7 @@ <_CoreClrBuildArg Condition="'$(HostCrossOS)' != ''" Include="-hostos $(HostCrossOS)" /> <_CoreClrBuildArg Include="-outputrid $(OutputRID)" /> <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> + <_CoreClrBuildArg Include="-cmakeargs "-DCLR_DOTNET_HOST_PATH=$(DOTNET_HOST_PATH)"" /> <_CoreClrBuildArg Include="-cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=$(RuntimeBinDir)cdac-build-tool\cdac-build-tool.dll"" />