-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathPackageProject.cmake
210 lines (186 loc) · 7.51 KB
/
PackageProject.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# Uses ycm (permissive BSD-3-Clause license) and ForwardArguments (permissive
# MIT license)
function(fiction_package_project)
# if CMake version >= 3.18
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18")
cmake_policy(SET CMP0103 NEW) # disallow multiple calls with the same NAME
endif()
# if CMake version >= 3.24
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24")
cmake_policy(SET CMP0135 NEW) # enable new timestamp checking behavior for
# fetching content
endif()
set(_options ARCH_INDEPENDENT # default to false
)
set(_oneValueArgs
# default to the project_name:
NAME
COMPONENT
# default to project version:
VERSION
# default to semver
COMPATIBILITY
# default to ${CMAKE_BINARY_DIR}
CONFIG_EXPORT_DESTINATION
# default to ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${NAME}
# suitable for vcpkg, etc.
CONFIG_INSTALL_DESTINATION)
set(_multiValueArgs
# recursively found for the current folder if not specified
TARGETS
# a list of public/interface include directories or files
PUBLIC_INCLUDES
# the names of the INTERFACE/PUBLIC dependencies that are found using
# `CONFIG`
PUBLIC_DEPENDENCIES_CONFIGURED
# the INTERFACE/PUBLIC dependencies that are found by any means using
# `find_dependency`. the arguments must be specified within double quotes
# (e.g. "<dependency> 1.0.0 EXACT" or "<dependency> CONFIG").
PUBLIC_DEPENDENCIES
# the names of the PRIVATE dependencies that are found using `CONFIG`.
# Only included when BUILD_SHARED_LIBS is OFF.
PRIVATE_DEPENDENCIES_CONFIGURED
# PRIVATE dependencies that are only included when BUILD_SHARED_LIBS is
# OFF
PRIVATE_DEPENDENCIES)
cmake_parse_arguments(_PackageProject "${_options}" "${_oneValueArgs}"
"${_multiValueArgs}" "${ARGN}")
# Set default options
include(GNUInstallDirs) # Define GNU standard installation directories such as
# CMAKE_INSTALL_DATADIR
# set default packaged targets
if(NOT _PackageProject_TARGETS)
get_all_installable_targets(_PackageProject_TARGETS)
message(
STATUS
"package_project: considering ${_PackageProject_TARGETS} as the exported targets"
)
endif()
# default to the name of the project or the given name
if("${_PackageProject_NAME}" STREQUAL "")
set(_PackageProject_NAME ${PROJECT_NAME})
endif()
# ycm args
set(_PackageProject_NAMESPACE "${_PackageProject_NAME}::")
set(_PackageProject_VARS_PREFIX ${_PackageProject_NAME})
set(_PackageProject_EXPORT ${_PackageProject_NAME})
# default version to the project version
if("${_PackageProject_VERSION}" STREQUAL "")
set(_PackageProject_VERSION ${PROJECT_VERSION})
endif()
# default compatibility to SameMajorVersion
if("${_PackageProject_COMPATIBILITY}" STREQUAL "")
set(_PackageProject_COMPATIBILITY "SameMajorVersion")
endif()
# default to the build directory
if("${_PackageProject_CONFIG_EXPORT_DESTINATION}" STREQUAL "")
set(_PackageProject_CONFIG_EXPORT_DESTINATION "${CMAKE_BINARY_DIR}")
endif()
set(_PackageProject_EXPORT_DESTINATION
"${_PackageProject_CONFIG_EXPORT_DESTINATION}")
# use datadir (works better with vcpkg, etc)
if("${_PackageProject_CONFIG_INSTALL_DESTINATION}" STREQUAL "")
set(_PackageProject_CONFIG_INSTALL_DESTINATION
"${CMAKE_INSTALL_DATADIR}/${_PackageProject_NAME}")
endif()
# ycm args
set(_PackageProject_INSTALL_DESTINATION
"${_PackageProject_CONFIG_INSTALL_DESTINATION}")
# Installation of the public/interface includes
if(NOT "${_PackageProject_PUBLIC_INCLUDES}" STREQUAL "")
foreach(_INC ${_PackageProject_PUBLIC_INCLUDES})
# make include absolute
if(NOT IS_ABSOLUTE ${_INC})
set(_INC "${CMAKE_CURRENT_SOURCE_DIR}/${_INC}")
endif()
# install include
if(IS_DIRECTORY ${_INC})
# the include directories are directly installed to the install
# destination. If you want an `include` folder in the install
# destination, name your include directory as `include` (or install it
# manually using `install()` command).
install(DIRECTORY ${_INC} DESTINATION "./")
else()
install(FILES ${_INC} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
endif()
endforeach()
endif()
# Append the configured public dependencies
if(NOT "${_PackageProject_PUBLIC_DEPENDENCIES_CONFIGURED}" STREQUAL "")
set(_PUBLIC_DEPENDENCIES_CONFIG)
foreach(DEP ${_PackageProject_PUBLIC_DEPENDENCIES_CONFIGURED})
list(APPEND _PUBLIC_DEPENDENCIES_CONFIG "${DEP} CONFIG")
endforeach()
endif()
list(APPEND _PackageProject_PUBLIC_DEPENDENCIES
${_PUBLIC_DEPENDENCIES_CONFIG})
# ycm arg
set(_PackageProject_DEPENDENCIES ${_PackageProject_PUBLIC_DEPENDENCIES})
# Append the configured private dependencies
if(NOT "${_PackageProject_PRIVATE_DEPENDENCIES_CONFIGURED}" STREQUAL "")
set(_PRIVATE_DEPENDENCIES_CONFIG)
foreach(DEP ${_PackageProject_PRIVATE_DEPENDENCIES_CONFIGURED})
list(APPEND _PRIVATE_DEPENDENCIES_CONFIG "${DEP} CONFIG")
endforeach()
endif()
# ycm arg
list(APPEND _PackageProject_PRIVATE_DEPENDENCIES
${_PRIVATE_DEPENDENCIES_CONFIG})
# Installation of package (compatible with vcpkg, etc)
install(
TARGETS ${_PackageProject_TARGETS}
EXPORT ${_PackageProject_EXPORT}
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
PUBLIC_HEADER
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_PackageProject_NAME}"
COMPONENT dev)
# install the usage file
set(_targets_str "")
foreach(_target ${_PackageProject_TARGETS})
set(_targets_str "${_targets_str} ${_PackageProject_NAMESPACE}${_target}")
endforeach()
set(USAGE_FILE_CONTENT
"The package ${_PackageProject_NAME} provides CMake targets:
find_package(${_PackageProject_NAME} CONFIG REQUIRED)
target_link_libraries(main PRIVATE ${_targets_str})
")
install(CODE "MESSAGE(STATUS \"${USAGE_FILE_CONTENT}\")")
file(WRITE "${_PackageProject_EXPORT_DESTINATION}/usage"
"${USAGE_FILE_CONTENT}")
install(FILES "${_PackageProject_EXPORT_DESTINATION}/usage"
DESTINATION "${_PackageProject_CONFIG_INSTALL_DESTINATION}")
unset(_PackageProject_TARGETS)
# download ForwardArguments
FetchContent_Declare(
_fargs
URL https://github.com/polysquare/cmake-forward-arguments/archive/8c50d1f956172edb34e95efa52a2d5cb1f686ed2.zip
)
FetchContent_GetProperties(_fargs)
if(NOT _fargs_POPULATED)
FetchContent_Populate(_fargs)
endif()
include("${_fargs_SOURCE_DIR}/ForwardArguments.cmake")
# prepare the forward arguments for ycm
set(_FARGS_LIST)
cmake_forward_arguments(
_PackageProject
_FARGS_LIST
OPTION_ARGS
"${_options};"
SINGLEVAR_ARGS
"${_oneValueArgs};EXPORT_DESTINATION;INSTALL_DESTINATION;NAMESPACE;VARS_PREFIX;EXPORT"
MULTIVAR_ARGS
"${_multiValueArgs};DEPENDENCIES;PRIVATE_DEPENDENCIES")
# download ycm
FetchContent_Declare(
_ycm URL https://github.com/robotology/ycm/archive/refs/tags/v0.13.0.zip)
FetchContent_GetProperties(_ycm)
if(NOT _ycm_POPULATED)
FetchContent_Populate(_ycm)
endif()
include("${_ycm_SOURCE_DIR}/modules/InstallBasicPackageFiles.cmake")
install_basic_package_files(${_PackageProject_NAME} "${_FARGS_LIST}")
include("${_ycm_SOURCE_DIR}/modules/AddUninstallTarget.cmake")
endfunction()