-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakePkgConfigTarget.cmake
More file actions
199 lines (190 loc) · 9.99 KB
/
MakePkgConfigTarget.cmake
File metadata and controls
199 lines (190 loc) · 9.99 KB
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
# FindBlasLapack.cmake
#
# Mark J. Olah (mjo@cs.unm DOT edu)
# Copyright 2019
# see file: LICENSE
#
# Enables use of pkg-config for modern CMake namespaced-targets, with cross-compiling awareness.
#
#
# make_pkg_config_target(target_var_name target_name [STATIC] pkg_config_names... )
# Options:
# STATIC - Find static libs. Will pass --static args to pkg_config
# DISABLE_PKGCONFIG - Disable usage of pkg-config. Will only add targets when ${VAR_NAME}_LIBRARIES and friends are already set.
# Single Value Args:
# VAR_NAME - Name to use for checking relevant CMake CACHE variables. Normally uppercase. [e.g., BLAS, LAPACK, BLAS_INT64, etc.]
# NAMESPACE - Namespace to create target at (:: optional)
# TARGET - Name of target to create (w/o namespace)
# Multi-value args:
# PCNAMES - List of pkg-config .pc names to check for in order. The first one found is used to set target properties.
#
# Sets cache variables:
# ${VAR_NAME}_FOUND - True if found either with pkg-config or through ${VAR_NAME}_LIBRARIES variables
# ${VAR_NAME}_PKGCONFIG_FOUND - True if found with pkg-config.
# ${VAR_NAME}_PKGCONFIG_NAME - pkg-config name found under if any.
#
#
#Helper:
#check_pkg_config(ret_var pcname pcflags...)
# Check if pcname is known to pkg-config
# Returns:
# Boolean: true if ${pcname}.pc file is found by pkg-config).
# Args:
# ret_var: return variable name.
# pcname: pkg-config name to look for (.pc file)
function(check_pkg_config ret_var pcname)
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --exists ${pcname} RESULT_VARIABLE _found)
if(_found EQUAL 0)
set(${ret_var} True PARENT_SCOPE)
else()
set(${ret_var} False PARENT_SCOPE)
endif()
endfunction()
#Helper:
#get_pkg_config(ret_var pcname pcflags...)
# Get the output of pkg-config
# Args:
# ret_var: return variable name
# pcname: pkg-config name to look for (.pc file)
# pcflags: pkg-config flags to pass
function(get_pkg_config ret_var pcname)
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${pcname} OUTPUT_VARIABLE _out RESULT_VARIABLE _ret OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_ret EQUAL 0)
separate_arguments(_out)
set(${ret_var} ${_out} PARENT_SCOPE)
else()
set(${ret_var} "" PARENT_SCOPE)
endif()
endfunction()
function(make_pkg_config_target)
set(options STATIC DISABLE_PKGCONFIG)
set(oneValueArgs VAR_NAME NAMESPACE TARGET)
set(multiValueArgs PCNAMES)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "[MakePkgConfigTarget:make_pkg_config_target] Unknown keywords given: \"${ARG_UNPARSED_ARGUMENTS}\"")
endif()
set(_FOUND False)
set(_FOUND_PKG_CONFIG False)
if(ARG_STATIC)
set(_static_flags --static)
else()
set(_static_flags)
endif()
string(REGEX REPLACE "::" "" ARG_NAMESPACE ${ARG_NAMESPACE})
set(target_name ${ARG_NAMESPACE}::${ARG_TARGET})
set(target_var_name ${ARG_VAR_NAME})
if(TARGET ${target_name} AND ${target_var_name}_FOUND)
return()
elseif(${target_var_name}_FOUND AND ${target_var_name}_LIBRARIES)
add_library(${target_name} SHARED IMPORTED)
set_target_properties(${target_name} PROPERTIES INTERFACE_LINK_LIBRARIES "${${target_var_name}_LIBRARIES}")
if(${target_var_name}_LINKER_FLAGS)
if(${CMAKE_VERSION} VERSION_GREATER "3.13.0")
target_link_options(${target_name} INTERFACE ${${target_var_name}_LINKER_FLAGS})
else()
set_property(TARGET ${target_name} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${${target_var_name}_LINKER_FLAGS}") #Older CMAKE don't have INTERFACE_LINK_OPTIONS
endif()
endif()
if(${target_var_name}_LINKER_DIRS)
if(${CMAKE_VERSION} VERSION_GREATER "3.13.0")
target_link_directories(${target_name} INTERFACE ${${target_var_name}_LINKER_DIRS})
else()
set_property(TARGET ${target_name} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${${target_var_name}_LINKER_DIRS}") #Older CMAKE don't have INTERFACE_LINK_DIRECTORIES
endif()
endif()
if(${target_var_name}_INCLUDE_DIRS)
set_target_properties(${target_name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${${target_var_name}_INCLUDE_DIRS}")
endif()
if(${target_var_name}_COMPILE_DEFINITIONS)
set_target_properties(${target_name} PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${${target_var_name}_COMPILE_DEFINITIONS}")
endif()
if(${target_var_name}_COMPILE_OPTIONS)
set_target_properties(${target_name} PROPERTIES INTERFACE_COMPILE_OPTIONS "${${target_var_name}_COMPILE_OPTIONS}")
endif()
message(STATUS "Found ${target_name} manually specified")
set(_FOUND True)
elseif(NOT DISABLE_PKGCONFIG) #Look in pkg_config
foreach(pkg_config_name IN LISTS ARG_PCNAMES)
check_pkg_config(_FOUND ${pkg_config_name})
if(_FOUND)
get_pkg_config(_INCLUDES ${pkg_config_name} "--cflags-only-I" ${_static_flags})
get_pkg_config(_CFLAGS ${pkg_config_name} "--cflags-only-other" ${_static_flags})
get_pkg_config(_LIB_DIRS ${pkg_config_name} "--libs-only-L" ${_static_flags})
get_pkg_config(_LIBS ${pkg_config_name} "--libs-only-l" ${_static_flags})
get_pkg_config(_LINKER_OPTS ${pkg_config_name} "--libs-only-other" ${_static_flags})
string(REGEX REPLACE "-I" "" _INCLUDES "${_INCLUDES}")
#Splitup compile definitions and options
set(_COMPILE_DEFINITIONS ${_CFLAGS})
set(_COMPILE_OPTIONS ${_CFLAGS})
if(_CFLAGS)
list(FILTER _COMPILE_OPTIONS EXCLUDE REGEX "^-D")
list(FILTER _COMPILE_DEFINITIONS INCLUDE REGEX "^-D")
string(REGEX REPLACE "-D" "" _COMPILE_DEFINITIONS "${_COMPILE_DEFINITIONS}")
endif()
string(REGEX REPLACE "-L" "" _LIB_DIRS "${_LIB_DIRS}")
string(REGEX REPLACE "-l" "" _LIBS "${_LIBS}")
set(_ABS_LIBS)
foreach(_lib IN LISTS _LIBS)
find_library(_lib_path ${_lib})
list(APPEND _ABS_LIBS ${_lib_path})
unset(_lib_path)
unset(_lib_path CACHE)
endforeach()
set(_LIBS ${_ABS_LIBS})
if(OPT_MakePkgConfigTarget_VERBOSE)
message(STATUS "[MakePkgConfigTarget] TARGET:${target_name} PCNAME:${pkg_config_name} def:${_COMPILE_DEFINITIONS} opt:${_COMPILE_OPTIONS} inc:${_INCLUDES} libopt:${_LINKER_OPTS} libdir:${_LIB_DIRS} libs:${_LIBS}")
endif()
add_library(${target_name} INTERFACE IMPORTED)
set_target_properties(${target_name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_INCLUDES}")
set_target_properties(${target_name} PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${_COMPILE_DEFINITIONS}")
set_target_properties(${target_name} PROPERTIES INTERFACE_COMPILE_OPTIONS "${_COMPILE_OPTIONS}")
if(${CMAKE_VERSION} VERSION_GREATER "3.13.0")
target_link_options(${target_name} INTERFACE ${_LINK_OPTS})
target_link_directories(${target_name} INTERFACE ${_LIB_DIRS})
target_link_libraries(${target_name} INTERFACE ${_LIBS})
else()
set_target_properties(${target_name} PROPERTIES INTERFACE_LINK_LIBRARIES "${_LINK_OPTS}") #Older CMAKE don't have INTERFACE_LINK_OPTIONS
set_target_properties(${target_name} PROPERTIES INTERFACE_LINK_LIBRARIES "${_LIB_DIRS}") #Older CMAKE don't have INTERFACE_LINK_DIRECTORIES
set_target_properties(${target_name} PROPERTIES INTERFACE_LINK_LIBRARIES "${_LIBS}") #Older CMAKE don't have INTERFACE_LINK_DIRECTORIES
endif()
set(_FOUND_PKG_CONFIG True)
set(${target_var_name}_PKGCONFIG_FOUND_NAME ${pkg_config_name} PARENT_SCOPE)
set(${target_var_name}_PKGCONFIG_FOUND_NAME ${pkg_config_name} CACHE STRING "${target_name} libraries: found using pkg-config name" FORCE)
mark_as_advanced(${target_var_name}_PKGCONFIG_FOUND_NAME)
message(STATUS "Found ${target_name} using pkg-config name: ${pkg_config_name} --- LIBS: ${_LIBS}")
break()
endif()
endforeach()
endif()
set(${target_var_name}_PKGCONFIG_FOUND ${_FOUND_PKG_CONFIG} PARENT_SCOPE)
set(${target_var_name}_PKGCONFIG_FOUND ${_FOUND_PKG_CONFIG} CACHE STRING "${target_name} libraries found using pkg-config" FORCE)
mark_as_advanced(${target_var_name}_PKGCONFIG_FOUND)
set(${target_var_name}_FOUND ${_FOUND} PARENT_SCOPE)
set(${target_var_name}_FOUND ${_FOUND} CACHE STRING "${target_name} libraries found." FORCE)
endfunction()
#Enable cross-compiling support for pkg-config via environment variables: https://autotools.io/pkgconfig/cross-compiling.html
if(NOT OPT_DISABLE_PKG_CONFIG AND CMAKE_CROSSCOMPILING)
set(_lib_dirs)
set(_sysroot)
if(CMAKE_SYSROOT)
list(APPEND _lib_dirs ${CMAKE_SYSROOT}/usr/lib/pkgconfig ${CMAKE_SYSROOT}/usr/share/pkgconfig)
set(_sysroot ${CMAKE_SYSROOT})
endif()
foreach(_dir IN LISTS CMAKE_FIND_ROOT_PATH)
list(APPEND _lib_dirs ${_dir}/lib/pkgconfig ${_dir}/share/pkgconfig ${_dir}/usr/lib/pkgconfig ${_dir}/usr/share/pkgconfig)
if(NOT _sysroot)
set(_sysroot ${_dir})
endif()
endforeach()
if(NOT _lib_dirs OR NOT _sysroot)
message(FATAL_ERROR "[BLASLAPACK] Cross-compiling but couldn't find valid CMAKE_SYSROOT or CMAKE_FIND_ROOT_PATH. Unknown how to find pkg-config repository.")
endif()
list(REMOVE_DUPLICATES _lib_dirs)
string(REPLACE ";" ":" _lib_dirs "${_lib_dirs}")
set(ENV{PKG_CONFIG_DIR} "")
set(ENV{PKG_CONFIG_LIBDIR} "${_lib_dirs}")
set(ENV{PKG_CONFIG_SYSROOT} "${_sysroot}")
unset(_lib_dirs)
unset(_sysroot)
endif()