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

Make corrosion_install install header files and export configurations #544

Merged
merged 10 commits into from
Sep 2, 2024
126 changes: 122 additions & 4 deletions cmake/Corrosion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ function(_corrosion_add_library_target)
if(has_staticlib)
add_library(${target_name}-static STATIC IMPORTED GLOBAL)
add_dependencies(${target_name}-static cargo-build_${target_name})
set_target_properties(${target_name}-static PROPERTIES COR_FILE_NAME ${static_lib_name})

_corrosion_set_imported_location("${target_name}-static" "IMPORTED_LOCATION"
"ARCHIVE_OUTPUT_DIRECTORY"
Expand All @@ -435,6 +436,7 @@ function(_corrosion_add_library_target)
if(has_cdylib)
add_library(${target_name}-shared SHARED IMPORTED GLOBAL)
add_dependencies(${target_name}-shared cargo-build_${target_name})
set_target_properties(${target_name}-shared PROPERTIES COR_FILE_NAME ${dynamic_lib_name})

# Todo: (Not new issue): What about IMPORTED_SONAME and IMPORTED_NO_SYSTEM?
_corrosion_set_imported_location("${target_name}-shared" "IMPORTED_LOCATION"
Expand All @@ -450,6 +452,7 @@ function(_corrosion_add_library_target)
"ARCHIVE_OUTPUT_DIRECTORY"
"${implib_name}"
)
set_target_properties(${target_name}-shared PROPERTIES COR_IMPLIB_FILE_NAME ${implib_name})
endif()

if(is_macos)
Expand Down Expand Up @@ -1098,18 +1101,23 @@ ANCHOR: corrosion-install
and is not officially released yet. Feedback and Suggestions are welcome.

```cmake
corrosion_install(TARGETS <target1> ... <targetN>
[[ARCHIVE|LIBRARY|RUNTIME]
corrosion_install(TARGETS <target1> ... <targetN> [EXPORT <export-name]
[[ARCHIVE|LIBRARY|RUNTIME|PUBLIC_HEADER]
[DESTINATION <dir>]
[PERMISSIONS <permissions...>]
[CONFIGURATIONS [Debug|Release|<other-configuration>]]
] [...])
```
* **TARGETS**: Target or targets to install.
* **ARCHIVE**/**LIBRARY**/**RUNTIME**: Designates that the following settings only apply to that specific type of object.
* **EXPORT**: Creates an export that can be installed with `install(EXPORT)`. Also creates a file at ${CMAKE_BINARY_DIR}/corrosion/<export-name>Corrosion.cmake that must be included in the installed config file.
* **ARCHIVE**/**LIBRARY**/**RUNTIME**/PUBLIC_HEADER: Designates that the following settings only apply to that specific type of object.
* **DESTINATION**: The subdirectory within the CMAKE_INSTALL_PREFIX that a specific object should be placed. Defaults to values from GNUInstallDirs.
* **PERMISSIONS**: The permissions of files copied into the install prefix.

Any `PUBLIC` or `INTERFACE` [file sets] will be installed.

[file sets]: https://cmake.org/cmake/help/latest/command/target_sources.html#file-sets

ANCHOR_END: corrosion-install
#]=======================================================================]
function(corrosion_install)
Expand Down Expand Up @@ -1159,8 +1167,12 @@ function(corrosion_install)

list(GET ARGN 0 EXPORT_NAME)
list(REMOVE_AT ARGN 0) # Pop <export-name>
message(FATAL_ERROR "EXPORT keyword not yet implemented!")
set(EXTRA_TARGETS_EXPORT_NAME ${EXPORT_NAME}Corrosion.cmake)
set(EXPORT_NAME EXPORT ${EXPORT_NAME})
gtker marked this conversation as resolved.
Show resolved Hide resolved
endif()
else()
# Prevent variable set in user code from interfering
set(EXPORT_NAME)
endif()

# Loop over all arguments and get options for each install target type
Expand Down Expand Up @@ -1293,6 +1305,20 @@ function(corrosion_install)
PERMISSIONS ${PERMISSIONS}
${CONFIGURATIONS}
)

if(EXPORT_NAME)
get_target_property(COR_FILE_NAME ${INSTALL_TARGET}-static COR_FILE_NAME)
file(APPEND
${CMAKE_BINARY_DIR}/corrosion/${EXTRA_TARGETS_EXPORT_NAME}
"
add_library(${INSTALL_TARGET}-static STATIC IMPORTED)
set_target_properties(${INSTALL_TARGET}-static
PROPERTIES
IMPORTED_LOCATION \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_FILE_NAME}\"
)
"
)
endif()
else()
message(FATAL_ERROR "Unknown target type ${TARGET_TYPE} for install target ${INSTALL_TARGET}")
endif()
Expand Down Expand Up @@ -1331,7 +1357,99 @@ function(corrosion_install)
DESTINATION ${DESTINATION}
${CONFIGURATIONS}
)

if(EXPORT_NAME)
get_target_property(COR_FILE_NAME ${INSTALL_TARGET}-shared COR_FILE_NAME)
file(APPEND
${CMAKE_BINARY_DIR}/corrosion/${EXTRA_TARGETS_EXPORT_NAME}
"
add_library(${INSTALL_TARGET}-shared SHARED IMPORTED)
set_target_properties(${INSTALL_TARGET}-shared
PROPERTIES
IMPORTED_LOCATION \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_FILE_NAME}\"
)
"
)

get_target_property(COR_IMPLIB_FILE_NAME ${INSTALL_TARGET}-shared COR_IMPLIB_FILE_NAME)
if (NOT COR_IMPLIB_FILE_NAME MATCHES .*-NOTFOUND)
file(APPEND
${CMAKE_BINARY_DIR}/corrosion/${EXTRA_TARGETS_EXPORT_NAME}
"
set_target_properties(${INSTALL_TARGET}-shared
PROPERTIES
IMPORTED_IMPLIB \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_IMPLIB_FILE_NAME}\"
)"
)
endif()
endif()
endif()
endif()

# Executables can also have export tables, so they _might_ also need header files
if (DEFINED COR_INSTALL_PUBLIC_HEADER_DESTINATION)
set(DESTINATION ${COR_INSTALL_PUBLIC_HEADER_DESTINATION})
elseif (DEFINED COR_INSTALL_DEFAULT_DESTINATION)
set(DESTINATION ${COR_INSTALL_DEFAULT_DESTINATION})
else()
set(DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()

if (DEFINED COR_INSTALL_PUBLIC_HEADER_PERMISSIONS)
set(PERMISSIONS ${COR_INSTALL_PUBLIC_HEADER_PERMISSIONS})
elseif (DEFINED COR_INSTALL_DEFAULT_PERMISSIONS)
set(PERMISSIONS ${COR_INSTALL_DEFAULT_PERMISSIONS})
else()
# Directories need OWNER_EXECUTE in order to be deletable by owner
set(PERMISSIONS ${DEFAULT_PERMISSIONS} OWNER_EXECUTE)
endif()

if (DEFINED COR_INSTALL_PUBLIC_HEADER_CONFIGURATIONS)
set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_PUBLIC_HEADER_CONFIGURATIONS})
elseif (DEFINED COR_INSTALL_DEFAULT_CONFIGURATIONS)
set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_DEFAULT_CONFIGURATIONS})
else()
set(CONFIGURATIONS)
endif()

get_target_property(FILE_SET ${INSTALL_TARGET} INTERFACE_HEADER_SETS)
if(NOT FILE_SET OR FILE_SET MATCHES .*-NOTFOUND)
set(TARGET_HAS_FILE_SET FALSE)
else()
set(TARGET_HAS_FILE_SET TRUE)
endif()

if(NOT TARGET_HAS_FILE_SET)
if(EXPORT_NAME)
# We still need to generate a EXPORT but we can't do that with install(DIRECTORY)
install(TARGETS ${INSTALL_TARGET} ${EXPORT_NAME})
endif()

set(PUBLIC_HEADER_PROPERTIES INCLUDE_DIRECTORIES PUBLIC_INCLUDE_DIRECTORIES INTERFACE_INCLUDE_DIRECTORIES)
foreach(PUBLIC_HEADER_PROPERTY ${PUBLIC_HEADER_PROPERTIES})
get_target_property(PUBLIC_HEADER ${INSTALL_TARGET} ${PUBLIC_HEADER_PROPERTY})

if(NOT PUBLIC_HEADER MATCHES .*-NOTFOUND)
foreach(INCLUDE_DIRECTORY ${PUBLIC_HEADER})
install(
DIRECTORY ${INCLUDE_DIRECTORY}
DESTINATION .
FILE_PERMISSIONS ${PERMISSIONS}
DIRECTORY_PERMISSIONS ${PERMISSIONS}
${CONFIGURATIONS}
)
endforeach()
endif()
endforeach()
else()
install(
TARGETS ${INSTALL_TARGET}
${EXPORT_NAME}
FILE_SET HEADERS
DESTINATION ${DESTINATION}
PERMISSIONS ${PERMISSIONS}
${CONFIGURATIONS}
)
endif()
endforeach()

Expand Down
4 changes: 1 addition & 3 deletions doc/src/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ add_executable(your_cool_cpp_bin main.cpp)
# A target with the same name is now available in CMake and you can use it to link the rust library into
# your C/C++ CMake target(s).
target_link_libraries(your_cool_cpp_bin PUBLIC rust-lib)

# Rust libraries and executables can also be installed using `corrosion_install`.
corrosion_install(TARGETS rust-lib)
```


Please see the [Usage chapter](usage.md) for a complete discussion of possible configuration options.
78 changes: 78 additions & 0 deletions doc/src/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,84 @@ Corrosion provides `corrosion_install` to automatically install relevant files:

{{#include ../../cmake/Corrosion.cmake:corrosion-install}}

The example below shows how to import a rust library and make it available for install through CMake.

```cmake
include(FetchContent)

FetchContent_Declare(
Corrosion
GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
GIT_TAG v0.5 # Optionally specify a commit hash, version tag or branch here
)
# Set any global configuration variables such as `Rust_TOOLCHAIN` before this line!
FetchContent_MakeAvailable(Corrosion)

# Import targets defined in a package or workspace manifest `Cargo.toml` file
corrosion_import_crate(MANIFEST_PATH rust-lib/Cargo.toml)

# Add a manually written header file which will be exported
# Requires CMake >=3.23
target_sources(rust-lib INTERFACE
FILE_SET HEADERS
BASE_DIRS include
FILES
include/rust-lib/rust-lib.h
)

# OR for CMake <= 3.23
target_include_directories(is_odd INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_sources(is_odd
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/rust-lib/rust-lib.h>
$<INSTALL_INTERFACE:include/rust-lib/rust-lib.h>
)

# Rust libraries must be installed using `corrosion_install`.
corrosion_install(TARGETS rust-lib EXPORT RustLibTargets)

# Installs the main target
install(
EXPORT RustLibTargets
NAMESPACE RustLib::
DESTINATION lib/cmake/RustLib
)

# Necessary for packaging helper commands
include(CMakePackageConfigHelpers)
# Create a file for checking version compatibility
# Optional
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/RustLibConfigVersion.cmake"
VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)

# Configures the main config file that cmake loads
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/RustLibConfig.cmake"
INSTALL_DESTINATION lib/cmake/RustLib
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
# Config.cmake.in contains
# @PACKAGE_INIT@
#
# include(${CMAKE_CURRENT_LIST_DIR}/RustLibTargetsCorrosion.cmake)
# include(${CMAKE_CURRENT_LIST_DIR}/RustLibTargets.cmake)

# Install all generated files
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/RustLibConfigVersion.cmake
${CMAKE_CURRENT_BINARY_DIR}/RustLibConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/corrosion/RustLibTargetsCorrosion.cmake
DESTINATION lib/cmake/RustLib
)
```

[install commands]: https://cmake.org/cmake/help/latest/command/install.html

### Per Target options
Expand Down
1 change: 1 addition & 0 deletions test/corrosion_install/install_lib/rust_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set_target_properties(rust_lib-shared PROPERTIES IMPORTED_SONAME librust_lib.dylib)
endif()

target_sources(rust_lib INTERFACE include/rust_lib/rust_lib.hpp)

corrosion_install(TARGETS rust_lib)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include <cstdint.h>

extern "C" uint64_t add(uint64_t left, uint64_t right);