Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[runtime] Infrastructure to build runtime components using NativeAOT #98565

Merged
merged 85 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
663184e
wip: dotnet.sh build src/native/libhellomanaged/compile-native.proj w…
lambdageek Feb 14, 2024
d16749d
hide unnecesary dependencies
lambdageek Feb 15, 2024
ca01640
add compile-native.proj to runtime-prereqs.proj
lambdageek Feb 15, 2024
2ad4c85
make first builds work
lambdageek Feb 15, 2024
44ce176
add an include dir for libhellomanaged
lambdageek Feb 15, 2024
6aad355
wire in static lib support; use to call libhellomanaged from daccess
lambdageek Feb 15, 2024
eb56ef6
call hellomanaged_Hello from DAC DllMain
lambdageek Feb 15, 2024
225d05b
static linking of nativeAotFramework
lambdageek Feb 15, 2024
19d17ac
support for importing NativeAOT compiled shared libs
lambdageek Feb 16, 2024
c03b37e
build native libs as shared by default
lambdageek Feb 16, 2024
730dd07
WIP: first try at installing the native lib
lambdageek Feb 16, 2024
472ee21
relocatable linking for static libs
lambdageek Feb 16, 2024
51f56b1
cleanup shared lib version; add install_clr support
lambdageek Feb 16, 2024
b6c637c
rm TODO
lambdageek Feb 16, 2024
80c706d
don't build hellomanaged on platforms without NativeAOT
lambdageek Feb 16, 2024
1f6a9f7
fixup windows build
lambdageek Feb 16, 2024
26c33ab
fixup win implib
lambdageek Feb 16, 2024
f6dcfe8
disable more configurations
lambdageek Feb 16, 2024
b94c67a
try to workaround dotnet/msbuild#2811
lambdageek Feb 16, 2024
4c7793b
allow daccess to keep building if hellomanaged is not present
lambdageek Feb 16, 2024
ce900f1
always use lld on linux?
lambdageek Feb 16, 2024
37edeaf
put AdditionalProperties on the ProjectReference same as msbuild publish
lambdageek Feb 16, 2024
a24dc46
no x86 or riscv
lambdageek Feb 17, 2024
748a84d
linux-arm64 hack
lambdageek Feb 17, 2024
d77776e
HACK: installer
lambdageek Feb 20, 2024
e7eca1f
disable armel
lambdageek Feb 20, 2024
4149bea
remove bfd hack - it didn't work
lambdageek Feb 20, 2024
11c9d90
pass SysRoot and --gcc-toolchain to native build
lambdageek Feb 20, 2024
f664970
fix typo (RID is linux-riscv64 not linux-riscv)
lambdageek Feb 20, 2024
70bc9c7
set linker flavor if doing cross builds
lambdageek Feb 20, 2024
0f776cc
fix for cmake 3.20
lambdageek Feb 20, 2024
66f4b53
use GenerateFileFromTemplate for shared mode
lambdageek Feb 20, 2024
c32f8ac
use GenerateFileFromTemplate for static libs
lambdageek Feb 20, 2024
556d0b5
rename toplevel dir to src/native/managed
lambdageek Feb 20, 2024
fd04a07
allow csproj to specify cmake include dir for native library
lambdageek Feb 21, 2024
f6dd13f
fixup INCLUDE path for Windows
lambdageek Feb 21, 2024
b06ddeb
Use find_package to find native AOT libs
lambdageek Feb 21, 2024
533f183
Add README
lambdageek Feb 21, 2024
211d683
remove unused function
lambdageek Feb 21, 2024
70db261
libhellomanaged is optional
lambdageek Feb 21, 2024
f9b52d5
move user-facing cmake to eng/functions.cmake
lambdageek Feb 21, 2024
c3b231d
remove cruft
lambdageek Feb 21, 2024
014a674
fix windows paths
lambdageek Feb 21, 2024
0c96465
Use unix-style paths even on Windows; cmake prefers this
lambdageek Feb 21, 2024
bf6c499
dependency tracking and stripping
lambdageek Feb 21, 2024
44ba2cc
windows stripping support
lambdageek Feb 22, 2024
3184d6d
cleanup
lambdageek Feb 22, 2024
3835325
update README
lambdageek Feb 22, 2024
4b04029
remove FIXME
lambdageek Feb 22, 2024
77d9899
remove static linking support
lambdageek Feb 22, 2024
5a4be9a
use _IsPublishing for the publish target
lambdageek Feb 22, 2024
7ecdca0
set MSBuildRestoreSessionId when restoring
lambdageek Feb 22, 2024
238ee10
rename property to CLR_IMPORTED_COPY_TARGET
lambdageek Feb 22, 2024
d7a57b8
add a general purpose add_imported_library_clr cmake function
lambdageek Feb 23, 2024
bf5652f
Merge remote-tracking branch 'origin/main' into naot-runtime-lib
lambdageek Mar 4, 2024
0e05f17
move call to hellomanaged_Hello to CLRDataAccessCreateInstance
lambdageek Mar 4, 2024
481a77a
WIP: copy runtime components to final location in native-library.targets
lambdageek Mar 4, 2024
de1114b
add ::libs and ::headers imported lib targets
lambdageek Mar 5, 2024
0d21d2e
remove unused var
lambdageek Mar 5, 2024
7c409be
add TODOs for new approach
lambdageek Mar 5, 2024
2b0850a
remove import-nativeaot-library.cmake
lambdageek Mar 5, 2024
6dad61e
remove add_imported_library_clr cmake function
lambdageek Mar 5, 2024
e075acd
revert cmake changes for imported libs
lambdageek Mar 5, 2024
ce1c1c7
update README
lambdageek Mar 5, 2024
7eff8e6
just emit one cmake file
lambdageek Mar 5, 2024
182df7a
simplify the cmake template
lambdageek Mar 5, 2024
8eb8e36
rename some cmake vars
lambdageek Mar 5, 2024
dd50ff0
strip nativeoat-built componentlike coreclr does on mac/linux
lambdageek Mar 5, 2024
bdc85a0
fixup osx and linux builds
lambdageek Mar 5, 2024
6aae973
empty commit to trigger build
lambdageek Mar 6, 2024
003af6a
copy windows PDBs to final install destinations
lambdageek Mar 6, 2024
edbbe84
DRY
lambdageek Mar 6, 2024
adc9314
simplify example
lambdageek Mar 6, 2024
3a5353b
fixup comments and docs
lambdageek Mar 6, 2024
c7b6751
cleanup
lambdageek Mar 6, 2024
a07ecaa
set library name on linux and mac
lambdageek Mar 6, 2024
0cc4db4
remove example
lambdageek Mar 6, 2024
0f90a93
remove support for exporting a header target
lambdageek Mar 7, 2024
0a582c2
Revert "remove support for exporting a header target"
lambdageek Mar 7, 2024
937a173
native-library.targets: make SetupOSSpecificProps probe for objcopy
lambdageek Mar 7, 2024
0e3bed5
Remove cmake integration
lambdageek Mar 7, 2024
19724f1
fix comment
lambdageek Mar 8, 2024
0958981
rename InstallRuntimeComponentDestination
lambdageek Mar 8, 2024
f55ebcc
automatically include native-library.{props,targets}
lambdageek Mar 8, 2024
b97c391
switch compile-native.proj to the traversal sdk
lambdageek Mar 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 148 additions & 18 deletions eng/native/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -366,27 +366,126 @@ function(generate_exports_file_prefix inputFilename outputFilename prefix)
PROPERTIES GENERATED TRUE)
endfunction()

function (get_symbol_file_name targetName outputSymbolFilename)
if (CLR_CMAKE_HOST_UNIX)
if (CLR_CMAKE_TARGET_APPLE)
set(strip_destination_file $<TARGET_FILE:${targetName}>.dwarf)
else ()
set(strip_destination_file $<TARGET_FILE:${targetName}>.dbg)
endif ()

set(${outputSymbolFilename} ${strip_destination_file} PARENT_SCOPE)
elseif(CLR_CMAKE_HOST_WIN32)
# We can't use the $<TARGET_PDB_FILE> generator expression here since
# the generator expression isn't supported on resource DLLs.
set(${outputSymbolFilename} $<TARGET_FILE_DIR:${targetName}>/$<TARGET_FILE_PREFIX:${targetName}>$<TARGET_FILE_BASE_NAME:${targetName}>.pdb PARENT_SCOPE)
define_property(TARGET PROPERTY CLR_IMPORTED_COPY_TARGET
BRIEF_DOCS "set to the COPY_TARGET option that was used to define the target using add_imported_library_clr"
FULL_DOCS "set to the COPY_TARGET option that was used to define the target using add_imported_library_clr"
"Since imported targets don't have build events, the COPY_TARGET's POST_BUILD event can be used instead")

# add_imported_library_clr(targetName COPY_TARGET copyTargetName IMPORTED_LOCATION importLocation)
#
# same as add_library(targetName SHARED IMPORTED GLOBAL) but it will first copy the library from
# importLocation into our build tree using the target copyTargetName. We do this so that we can
# strip the symbols from the library and place them into a separate symbol file.
#
# Incidentally this also makes cmake dependency analysis work correctly: if the imported library
# changes (for example, if it is built during an earlier stage of our build that cmake can't see,
# the dependencies of targetName will be rebuilt)
function(add_imported_library_clr targetName)
set(options)
set(oneValueArgs COPY_TARGET IMPORTED_LOCATION)
set(multiValueArgs)
cmake_parse_arguments(PARSE_ARGV 1 opt "${options}" "${oneValueArgs}" "${multiValueArgs}")
if ("${opt_COPY_TARGET}" STREQUAL "" OR "${opt_KEYWORDS_MISSING_VALUES}" MATCHES "COPY_TARGET")
message(FATAL_ERROR "add_imported_library_clr requires COPY_TARGET option")
endif()
if ("${opt_IMPORTED_LOCATION}" STREQUAL "" OR "${opt_KEYWORDS_MISSING_VALUES}" MATCHES "IMPORTED_LOCATION")
message(FATAL_ERROR "add_imported_library_clr requires IMPORTED_LOCATION option")
endif()
if (NOT "${opt_UNPARSED_ARGUMENTS}" STREQUAL "")
message(FATAL_ERROR "add_imported_library_clr called with unrecognized options ${opt_UNPARSED_ARGUMENTS}")
endif()

# Copy the imported library into our binary dir.
# We do this so that we may strip it and also so that cmake dependency tracking will be aware if the file changes

set(src "${opt_IMPORTED_LOCATION}")
cmake_path(GET src FILENAME srcFilename)

# for namespaced targets replace :: by _ - otherwise the make generator produces a Makefile rule that make doesn't like
string(REPLACE "::" "_" destSubdir "${targetName}")
set(dest "${CMAKE_CURRENT_BINARY_DIR}/imported_library/${destSubdir}/${srcFilename}")

add_custom_command(OUTPUT "${dest}"
DEPENDS "${src}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${src}" "${dest}"
)

if (CLR_CMAKE_HOST_WIN32)
cmake_path(REPLACE_EXTENSION opt_IMPORTED_LOCATION ".pdb" OUTPUT_VARIABLE srcPdb)
cmake_path(GET srcPdb FILENAME srcPdbFilename)
set(destPdb "${CMAKE_CURRENT_BINARY_DIR}/imported_library/${destSubdir}/${srcPdbFilename}")

add_custom_command(OUTPUT "${destPdb}"
DEPENDS "${srcPdb}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${srcPdb}" "${destPdb}"
)
endif()

if (CLR_CMAKE_HOST_WIN32)
add_custom_target("${opt_COPY_TARGET}" DEPENDS "${dest}" "${destPdb}")
else()
add_custom_target("${opt_COPY_TARGET}" DEPENDS "${dest}")
endif()

add_library(${targetName} SHARED IMPORTED GLOBAL)
add_dependencies(${targetName} "${opt_COPY_TARGET}")
set_property(TARGET ${targetName} PROPERTY IMPORTED_LOCATION "${dest}")
set_property(TARGET ${targetName} PROPERTY CLR_IMPORTED_COPY_TARGET "${opt_COPY_TARGET}")

strip_symbols(${targetName} symbolFile)
endfunction()

function(get_symbol_file_name targetName outputSymbolFilename)
get_target_property(importedCopyTarget "${targetName}" CLR_IMPORTED_COPY_TARGET) # see add_imported_library_clr
if ("${importedCopyTarget}" STREQUAL "importedCopyTarget-NOTFOUND")
if (CLR_CMAKE_HOST_UNIX)
if (CLR_CMAKE_TARGET_APPLE)
set(strip_destination_file $<TARGET_FILE:${targetName}>.dwarf)
else ()
set(strip_destination_file $<TARGET_FILE:${targetName}>.dbg)
endif ()

set(${outputSymbolFilename} ${strip_destination_file} PARENT_SCOPE)
elseif(CLR_CMAKE_HOST_WIN32)
# We can't use the $<TARGET_PDB_FILE> generator expression here since
# the generator expression isn't supported on resource DLLs.
set(${outputSymbolFilename} $<TARGET_FILE_DIR:${targetName}>/$<TARGET_FILE_PREFIX:${targetName}>$<TARGET_FILE_BASE_NAME:${targetName}>.pdb PARENT_SCOPE)
endif()
else()
get_target_property(libraryType "${targetName}" TYPE)
message(TRACE "Target ${targetName} is imported of type ${libraryType}")
if ("${libraryType}" STREQUAL "SHARED_LIBRARY")
get_property(importedLocation TARGET ${targetName} PROPERTY IMPORTED_LOCATION)
message(TRACE "Target ${targetName} is imported from ${importedLocation}")
if (CLR_CMAKE_HOST_UNIX)
if (CLR_CMAKE_TARGET_APPLE)
set(importedLocation "${importedLocation}.dwarf")
else()
set(importedLocation "${importedLocation}.dbg")
endif()
elseif(CLR_CMAKE_HOST_WIN32)
cmake_path(REPLACE_EXTENSION importedLocation ".pdb")
endif()
set(${outputSymbolFilename} "${importedLocation}" PARENT_SCOPE)
message(TRACE "Target ${targetName} symbols will be in ${importedLocation}")
endif()
endif()
endfunction()

function(strip_symbols targetName outputFilename)
get_symbol_file_name(${targetName} strip_destination_file)
set(${outputFilename} ${strip_destination_file} PARENT_SCOPE)
if (CLR_CMAKE_HOST_UNIX)
set(strip_source_file $<TARGET_FILE:${targetName}>)
get_target_property(copy_target "${targetName}" CLR_IMPORTED_COPY_TARGET)
if ("${copy_target}" STREQUAL "copy_target-NOTFOUND")
# normal target, we will add the post-build event to it
set(strip_source_file $<TARGET_FILE:${targetName}>)
set(post_build_target "${targetName}")
else()
# for an imported library, we will add the post-build event on the copy target
get_property(strip_source_file TARGET ${targetName} PROPERTY IMPORTED_LOCATION)
set(post_build_target "${copy_target}")
endif()

if (CLR_CMAKE_TARGET_APPLE)

Expand Down Expand Up @@ -422,7 +521,7 @@ function(strip_symbols targetName outputFilename)
endif ()

add_custom_command(
TARGET ${targetName}
TARGET ${post_build_target}
POST_BUILD
VERBATIM
COMMAND sh -c "echo Stripping symbols from $(basename '${strip_source_file}') into $(basename '${strip_destination_file}')"
Expand All @@ -432,7 +531,7 @@ function(strip_symbols targetName outputFilename)
else (CLR_CMAKE_TARGET_APPLE)

add_custom_command(
TARGET ${targetName}
TARGET ${post_build_target}
POST_BUILD
VERBATIM
COMMAND sh -c "echo Stripping symbols from $(basename '${strip_source_file}') into $(basename '${strip_destination_file}')"
Expand Down Expand Up @@ -533,15 +632,26 @@ function(install_clr)
endif()
add_dependencies(${INSTALL_CLR_COMPONENT} ${targetName})
endif()
get_target_property(targetType ${targetName} TYPE)
get_property(hasCopyTarget TARGET "${targetName}" PROPERTY CLR_IMPORTED_COPY_TARGET SET)
get_target_property(targetType "${targetName}" TYPE)
if (NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS AND NOT "${targetType}" STREQUAL "STATIC_LIBRARY")
get_symbol_file_name(${targetName} symbolFile)
endif()

foreach(destination ${destinations})
# We don't need to install the export libraries for our DLLs
# since they won't be directly linked against.
install(PROGRAMS $<TARGET_FILE:${targetName}> DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
if (NOT "${hasCopyTarget}")
install(PROGRAMS $<TARGET_FILE:${targetName}> DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
elseif("${targetType}" STREQUAL "SHARED_LIBRARY")
# for shared libraries added with add_imported_library_clr install the imported artifacts

if ("${CMAKE_VERSION}" VERSION_LESS "3.21")
install(PROGRAMS $<TARGET_PROPERTY:${targetName},IMPORTED_LOCATION> DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
else()
install(IMPORTED_RUNTIME_ARTIFACTS ${targetName} DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
endif()
endif()
if (NOT "${symbolFile}" STREQUAL "")
install_symbol_file(${symbolFile} ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
endif()
Expand Down Expand Up @@ -662,3 +772,23 @@ function(adhoc_sign_with_entitlements targetName entitlementsFile)
POST_BUILD
COMMAND codesign -s - -f --entitlements ${entitlementsFile} $<TARGET_FILE:${targetName}>)
endfunction()

# find_nativeaot_library(libraryName [REQUIRED])
#
# Imports a native library produced by NativeAOT (see src/native/managed).
# If the library is found, sets libraryName_FOUND to true, else false.
# If the library is found, a target libraryName::libraryName is defined.
# If REQUIRED is specified, it's a fatal error not to find the library, otherwise the library is considered optional.
#
# For implementation details see import-nativeaot-library.cmake
function(find_nativeaot_library libraryName)
cmake_parse_arguments(PARSE_ARGV 1 "findNativeAOT_opt" "REQUIRED" "" "")
if (NOT "${findNativeAOT_opt_REQUIRED}")
find_package(${libraryName} CONFIG NO_DEFAULT_PATH PATHS "${CLR_ARTIFACTS_OBJ_DIR}/cmake/find_package")
else()
find_package(${libraryName} CONFIG REQUIRED NO_DEFAULT_PATH PATHS "${CLR_ARTIFACTS_OBJ_DIR}/cmake/find_package")
endif()
set("${libraryName}_FOUND" "${${libraryName}_FOUND}" PARENT_SCOPE)
set("${libCmakeName}_CMAKE_FRAGMENT_PATH")
endfunction()

45 changes: 45 additions & 0 deletions eng/native/import-nativeaot-library.cmake
Copy link
Member

Choose a reason for hiding this comment

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

I think in the future, I'd almost rather have a "CMake module" file produced for the NativeAOT libraries instead of hard-coding it all here. I opened an issue related to this in DNNE a while back, AaronRobinsonMSFT/DNNE#185.

Copy link
Member Author

Choose a reason for hiding this comment

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

yea, this could be a separate NuGet. it should be possible to generate a cmake config, a rust crate, etc just by hooking something up after NativeAOT's publish target.

right now the cmake config isn't entirely self-contained most obviously it depends on eng/native/configureplatform.cmake but probably also some other of our variables are leaking in. But maybe it's possible to refactor it.

Also I didn't do multi-config generator support, which maybe people care about.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Infrastructure to import a native aot compiled library into a native build

# ## Implementation details used by libraryName-config.cmake find_package configuration
# ## files. Consumers don't need to do this directly.

# add_imported_nativeaot_library(targetName symbolPrefix [NAMESPACE namespace])
#
# adds a target targetName that can be used to reference a NativeAOTed library. symbolPrefix should
# be the ALLCAPS prefix of the variables that define the mode and paths for the library. They are
# typically set in the artifacts/obj/targetName/targetName.cmake fragment which should be included
# before calling this function.
function(add_imported_nativeaot_library targetNameIn symbolPrefix)
cmake_parse_arguments(PARSE_ARGV 2 "add_imported_opt" "" "NAMESPACE" "")
message(TRACE "${symbolPrefix}_MODE is ${${symbolPrefix}_MODE}")
set(targetName "${add_imported_opt_NAMESPACE}${targetNameIn}")
message(TRACE "Adding target ${targetName}")

if("${${symbolPrefix}_MODE}" STREQUAL "SHARED")
set(libName "${${symbolPrefix}_NAME}") # typically same as targetName
set(libPath "${${symbolPrefix}_LIBPATH}") # typically /.../artifacts/bin/<libName>/<config>/<rid>/publish
set(libFilename "${libName}${${symbolPrefix}_EXT}") # <libName>.dll, <libName>.so or <libName>.dylib
set(libFullPath "${libPath}/${libFilename}")

if(CLR_CMAKE_HOST_WIN32)
set(libPdbFullPath "${libPath}/${libName}.pdb")
endif()

# windows import library
set(libImpLibFullPath "${${symbolPrefix}_IMPLIBPATH}") # typically /.../artifacts/bin/<libName>/<config>/<rid>/native/<libName>.lib

set(copy_target_name "${targetNameIn}_copy_imported_library")

add_imported_library_clr(${targetName} COPY_TARGET ${copy_target_name} IMPORTED_LOCATION "${libFullPath}")
set_property(TARGET ${targetName} PROPERTY CLR_IMPORTED_NATIVEAOT_LIBRARY 1)

if("${CLR_CMAKE_HOST_WIN32}")
set_property(TARGET ${targetName} PROPERTY IMPORTED_IMPLIB "${libImpLibFullPath}")
endif()

set(libIncludePath "${${symbolPrefix}_INCLUDE}")
target_include_directories(${targetName} INTERFACE "${libIncludePath}")
else()
message(FATAL_ERROR "${symbolPrefix}_MODE must be SHARED")
endif()
endfunction()
9 changes: 9 additions & 0 deletions src/coreclr/debug/daccess/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_definitions(-DFEATURE_NO_HOST)

find_nativeaot_library(libhellomanaged)

include_directories(BEFORE ${VM_DIR})
include_directories(BEFORE ${VM_DIR}/${ARCH_SOURCES_DIR})
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
Expand Down Expand Up @@ -41,6 +43,13 @@ add_library_clr(daccess ${DACCESS_SOURCES})
set_target_properties(daccess PROPERTIES DAC_COMPONENT TRUE)
target_precompile_headers(daccess PRIVATE [["stdafx.h"]])

if("${libhellomanaged_FOUND}")
target_link_libraries(daccess PRIVATE libhellomanaged::libhellomanaged)
target_compile_definitions(daccess PRIVATE HAVE_LIBHELLOMANAGED)
# FIXME: can we put this with mscordaccore instead?
install_clr(TARGETS libhellomanaged::libhellomanaged DESTINATIONS . sharedFramework COMPONENT debug)
endif()

add_dependencies(daccess eventing_headers)

if(CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS)
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/debug/daccess/daccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ extern "C" bool TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddre
#include "dwbucketmanager.hpp"
#include "gcinterface.dac.h"

#ifdef HAVE_HELLOMANAGED
#include "libhellomanaged.h"
#endif

// To include definition of IsThrowableThreadAbortException
// #include <exstatecommon.h>

Expand Down Expand Up @@ -63,6 +67,10 @@ BOOL WINAPI DllMain(HANDLE instance, DWORD reason, LPVOID reserved)
#endif
}

#ifdef HAVE_HELLOMANAGED
hellomanaged_Hello();
#endif

#ifdef HOST_UNIX
int err = PAL_InitializeDLL();
if(err != 0)
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/runtime-prereqs.proj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
<Import Project="$(RepositoryEngineeringDir)versioning.targets" />
<Import Project="$(RepositoryEngineeringDir)nativepgo.targets" />

<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\native\managed\compile-native.proj" ReferenceOutputAssembly="false"/>
</ItemGroup>

<Target Name="BuildPrereqs" BeforeTargets="Build" DependsOnTargets="GenerateRuntimeVersionFile;GenerateNativeSourcelinkFile;OutputPgoPathForCI" />
<Import Project="Sdk.targets" Sdk="Microsoft.Build.NoTargets" />
<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@
<PlatformManifestFileEntry Include="mscordaccore.dll" IsNative="true" />
<PlatformManifestFileEntry Include="libmscordaccore.so" IsNative="true" />
<PlatformManifestFileEntry Include="libmscordaccore.dylib" IsNative="true" />
<!-- FIXME: do not merge -->
<PlatformManifestFileEntry Include="libhellomanaged.dll" IsNative="true" />
<PlatformManifestFileEntry Include="libhellomanaged.so" IsNative="true" />
<PlatformManifestFileEntry Include="libhellomanaged.dylib" IsNative="true" />
<!-- END FIXME: do not merge -->
<PlatformManifestFileEntry Include="mscordbi.dll" IsNative="true" />
<PlatformManifestFileEntry Include="libmscordbi.so" IsNative="true" />
<PlatformManifestFileEntry Include="libmscordbi.dylib" IsNative="true" />
Expand Down
3 changes: 3 additions & 0 deletions src/native/managed/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<Import Project="..\..\..\Directory.Build.props" />
</Project>
53 changes: 53 additions & 0 deletions src/native/managed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Native runtime component libraries using NativeAOT

This directory contains managed libraries that will be compiled using NativeAOT and can be used in runtime components.

## Using existing libraries

In a `CMakeLists.txt` add

``` cmake
find_nativeaot_library(libWhatever REQUIRED)
```

This will look for a cmake fragment file in
`artifacts/obj/cmake/find_package/libWhatever-config.cmake` that will import some variables from
`artifacts/obj/libWhatever/libWhatever.cmake` and defines a new `libWhatever::libWhatever` that can
be used as a dependency in `target_link_libraries()` or in a `install_clr()` command.


## Adding a new managed library

Add a new subdirectory to `src/native/managed` for your library with a `src` and `inc` subdirectories:

``` console
$ mkdir -p libMyNewLibrary/src libMyNewLibrary/inc
$ dotnet new classlib -n libMyNewLibrary -o libMyNewLibrary/src
```

In `src/native/managed/compile-native.proj`, add
`src/native/managed/libMyNewLibrary/src/libMyNewLibrary.csproj` to the `NativeLibsProjectsToBuild`
item group.

In `src/native/managed/libMyNewLibrary/src/libMyNewLibrary.csproj`:
1. Near the top, add `<Import Project="..\..\native-library.props" />`
2. Near the bottom, add `<Import Project="..\..\native-library.targets" />`
lambdageek marked this conversation as resolved.
Show resolved Hide resolved

The following is recommended:

1. The project should be called `libXXXX` - currently the infrastructure expects a `lib` prefix on all platforms.
2. The project should just have a single `EntryPoints.cs` that has a `static class` that provides
`[UnmanagedCallersOnly]` API entrypoints. The bulk of the code should be imported using
`ProjectReference` from another managed class library project. That managed project can be
tested using normal managed unit tests, consumed in other managed libraries, etc.
3. The `inc` directory if it exists will be added to the include path of any cmake targets that
depend on the native library. Typically the directory should contain a `libMyNewLibrary.h` header
file with a C declaration for each entrypoint. If you want ot have more include directories, add
them all to the `NativeLibraryCmakeFragmentIncludePath` item. In that case `inc` won't be added
by default.

Limitations:

Currently only shared library output is supported. In principle static linking is possible, but the
infrastructure is not finished yet. Additionally, mixing Debug/Release configurations with static
linking will not be supported on Windows.
Copy link
Member

@am11 am11 Feb 24, 2024

Choose a reason for hiding this comment

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

How do you feel about inlining these templates in MSBuild (to reduce number of moving parts)? It's just something which we considered in part infra work. e.g. in cmake we need to use the config.in template files, it is a natural fit in that world. In MSBuild, what comes natural is to write bunch of lines from targets directly somewhere under obj/ directory; without introducing some external template system.

Copy link
Member Author

Choose a reason for hiding this comment

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

@am11 an earlier version of this PR used WriteLinesToFile instead of GenerateFileFromTemplate. I thought the template approach was cleaner. But I could change it back.

Copy link
Member

Choose a reason for hiding this comment

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

An alternative (to avoid external template and intermediate file writes) is to include src/native/managed/**/ in some root-level CMakeLists via GLOB_RECURSE, and pass values of additional properties from msbuild to cmake via this command-line args.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This is a Config-style package configuration file for cmake's find_package command for ${libArtifactName}
set(CMAKE_FRAGMENT_PATH "${libArtifactConfigFragment}")

include("`${CLR_ENG_NATIVE_DIR}/import-nativeaot-library.cmake")

include("`${CMAKE_FRAGMENT_PATH}")

# adds a ${libArtifactName}::${libArtifactName} target
add_imported_nativeaot_library("${libArtifactName}" "${libCmakeName}" NAMESPACE "${libArtifactName}::")

Loading
Loading