1################################################################################
2# CMake package infrastructure
3#
4# This file implements an infrastructure that eases development of
5# package .mk files for CMake packages. It should be used for all
6# packages that use CMake as their build system.
7#
8# See the Buildroot documentation for details on the usage of this
9# infrastructure
10#
11# In terms of implementation, this CMake infrastructure requires
12# the .mk file to only specify metadata information about the
13# package: name, version, download URL, etc.
14#
15# We still allow the package .mk file to override what the different
16# steps are doing, if needed. For example, if <PKG>_BUILD_CMDS is
17# already defined, it is used as the list of commands to perform to
18# build the package, instead of the default CMake behaviour. The
19# package can also define some post operation hooks.
20#
21################################################################################
22
23# Set compiler variables.
24ifeq ($(BR2_CCACHE),y)
25CMAKE_HOST_C_COMPILER = $(HOSTCC_NOCCACHE)
26CMAKE_HOST_CXX_COMPILER = $(HOSTCXX_NOCCACHE)
27CMAKE_HOST_C_COMPILER_LAUNCHER = $(HOST_DIR)/bin/ccache
28CMAKE_HOST_CXX_COMPILER_LAUNCHER = $(HOST_DIR)/bin/ccache
29else
30CMAKE_HOST_C_COMPILER = $(HOSTCC)
31CMAKE_HOST_CXX_COMPILER = $(HOSTCXX)
32endif
33
34ifneq ($(QUIET),)
35CMAKE_QUIET = -DCMAKE_RULE_MESSAGES=OFF -DCMAKE_INSTALL_MESSAGE=NEVER
36endif
37
38################################################################################
39# inner-cmake-package -- defines how the configuration, compilation and
40# installation of a CMake package should be done, implements a few hooks to
41# tune the build process and calls the generic package infrastructure to
42# generate the necessary make targets
43#
44#  argument 1 is the lowercase package name
45#  argument 2 is the uppercase package name, including a HOST_ prefix
46#             for host packages
47#  argument 3 is the uppercase package name, without the HOST_ prefix
48#             for host packages
49#  argument 4 is the type (target or host)
50################################################################################
51
52define inner-cmake-package
53
54$(3)_SUPPORTS_IN_SOURCE_BUILD ?= YES
55
56# The default backend, unless specified by the package
57$(3)_CMAKE_BACKEND ?= make
58
59ifeq ($$($(3)_SUPPORTS_IN_SOURCE_BUILD),YES)
60$(2)_BUILDDIR			= $$($(2)_SRCDIR)
61else
62$(2)_BUILDDIR			= $$($(2)_SRCDIR)/buildroot-build
63endif
64
65ifeq ($$($(3)_CMAKE_BACKEND),make)
66$(2)_GENERATOR = "Unix Makefiles"
67# $$(MAKE) can be 'make -jN', we just want 'make'  (possibly with a full path)
68$(2)_GENERATOR_PROGRAM = $$(firstword $$(MAKE))
69# Generator specific code (make) should be avoided,
70# but for now, copy them to the new variables.
71$(2)_BUILD_ENV ?= $$($(2)_MAKE_ENV)
72$(2)_BUILD_OPTS ?= -- $$($(2)_MAKE_OPTS)
73
74else ifeq ($$($(3)_CMAKE_BACKEND),ninja)
75$(2)_DEPENDENCIES += host-ninja
76$(2)_GENERATOR = "Ninja"
77$(2)_GENERATOR_PROGRAM = $$(HOST_DIR)/bin/ninja
78
79else
80$$(error Unsupported cmake backend "$$($(3)_CMAKE_BACKEND)")
81endif
82
83#
84# Configure step. Only define it if not already defined by the package
85# .mk file. And take care of the differences between host and target
86# packages.
87#
88ifndef $(2)_CONFIGURE_CMDS
89ifeq ($(4),target)
90
91# Configure package for target
92#
93# - We are passing BUILD_SHARED_LIBS because it is documented as a
94#   standard CMake variable to control the build of shared libraries
95#   (see https://cmake.org/cmake/help/v3.8/manual/cmake-variables.7.html#variables-that-change-behavior)
96# - We are not passing BUILD_STATIC_LIBS because it is *not*
97#   documented as a standard CMake variable. If a package supports it,
98#   it must handle it explicitly.
99#
100define $(2)_CONFIGURE_CMDS
101	(mkdir -p $$($$(PKG)_BUILDDIR) && \
102	cd $$($$(PKG)_BUILDDIR) && \
103	rm -f CMakeCache.txt && \
104	PATH=$$(BR_PATH) \
105	$$($$(PKG)_CONF_ENV) $$(BR2_CMAKE) $$($$(PKG)_SRCDIR) \
106		-G$$($$(PKG)_GENERATOR) \
107		-DCMAKE_MAKE_PROGRAM="$$($$(PKG)_GENERATOR_PROGRAM)" \
108		-DCMAKE_TOOLCHAIN_FILE="$$(HOST_DIR)/share/buildroot/toolchainfile.cmake" \
109		-DCMAKE_INSTALL_PREFIX="/usr" \
110		-DCMAKE_INSTALL_RUNSTATEDIR="/run" \
111		-DCMAKE_COLOR_MAKEFILE=OFF \
112		-DBUILD_DOC=OFF \
113		-DBUILD_DOCS=OFF \
114		-DBUILD_EXAMPLE=OFF \
115		-DBUILD_EXAMPLES=OFF \
116		-DBUILD_TEST=OFF \
117		-DBUILD_TESTS=OFF \
118		-DBUILD_TESTING=OFF \
119		-DBUILD_SHARED_LIBS=$$(if $$(BR2_STATIC_LIBS),OFF,ON) \
120		$$(CMAKE_QUIET) \
121		$$($$(PKG)_CONF_OPTS) \
122	)
123endef
124else
125
126# Configure package for host
127define $(2)_CONFIGURE_CMDS
128	(mkdir -p $$($$(PKG)_BUILDDIR) && \
129	cd $$($$(PKG)_BUILDDIR) && \
130	rm -f CMakeCache.txt && \
131	PATH=$$(BR_PATH) \
132	PKG_CONFIG="$$(PKG_CONFIG_HOST_BINARY)" \
133	PKG_CONFIG_SYSROOT_DIR="/" \
134	PKG_CONFIG_LIBDIR="$$(HOST_DIR)/lib/pkgconfig:$$(HOST_DIR)/share/pkgconfig" \
135	PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 \
136	PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 \
137	$$($$(PKG)_CONF_ENV) $$(BR2_CMAKE) $$($$(PKG)_SRCDIR) \
138		-G$$($$(PKG)_GENERATOR) \
139		-DCMAKE_MAKE_PROGRAM="$$($$(PKG)_GENERATOR_PROGRAM)" \
140		-DCMAKE_INSTALL_SO_NO_EXE=0 \
141		-DCMAKE_FIND_ROOT_PATH="$$(HOST_DIR)" \
142		-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM="BOTH" \
143		-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY="BOTH" \
144		-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE="BOTH" \
145		-DCMAKE_INSTALL_PREFIX="$$(HOST_DIR)" \
146		-DCMAKE_C_FLAGS="$$(HOST_CFLAGS)" \
147		-DCMAKE_CXX_FLAGS="$$(HOST_CXXFLAGS)" \
148		-DCMAKE_EXE_LINKER_FLAGS="$$(HOST_LDFLAGS)" \
149		-DCMAKE_SHARED_LINKER_FLAGS="$$(HOST_LDFLAGS)" \
150		-DCMAKE_ASM_COMPILER="$$(HOSTAS)" \
151		-DCMAKE_C_COMPILER="$$(CMAKE_HOST_C_COMPILER)" \
152		-DCMAKE_CXX_COMPILER="$$(CMAKE_HOST_CXX_COMPILER)" \
153		$(if $$(CMAKE_HOST_C_COMPILER_LAUNCHER),\
154			-DCMAKE_C_COMPILER_LAUNCHER="$$(CMAKE_HOST_C_COMPILER_LAUNCHER)" \
155			-DCMAKE_CXX_COMPILER_LAUNCHER="$$(CMAKE_HOST_CXX_COMPILER_LAUNCHER)" \
156		) \
157		-DCMAKE_COLOR_MAKEFILE=OFF \
158		-DBUILD_DOC=OFF \
159		-DBUILD_DOCS=OFF \
160		-DBUILD_EXAMPLE=OFF \
161		-DBUILD_EXAMPLES=OFF \
162		-DBUILD_TEST=OFF \
163		-DBUILD_TESTS=OFF \
164		-DBUILD_TESTING=OFF \
165		-DBUILD_SHARED_LIBS=ON \
166		$$(CMAKE_QUIET) \
167		$$($$(PKG)_CONF_OPTS) \
168	)
169endef
170endif
171endif
172
173# Since some CMake modules (even upstream ones) use pgk_check_modules
174# primitives to find {C,LD}FLAGS, add it to the dependency list.
175$(2)_DEPENDENCIES += host-pkgconf
176
177$(2)_DEPENDENCIES += $(BR2_CMAKE_HOST_DEPENDENCY)
178
179#
180# Build step. Only define it if not already defined by the package .mk
181# file.
182#
183ifndef $(2)_BUILD_CMDS
184ifeq ($(4),target)
185define $(2)_BUILD_CMDS
186	$$(TARGET_MAKE_ENV) $$($$(PKG)_BUILD_ENV) $$(BR2_CMAKE) --build $$($$(PKG)_BUILDDIR) -j$(PARALLEL_JOBS) $$($$(PKG)_BUILD_OPTS)
187endef
188else
189define $(2)_BUILD_CMDS
190	$$(HOST_MAKE_ENV) $$($$(PKG)_BUILD_ENV) $$(BR2_CMAKE) --build $$($$(PKG)_BUILDDIR) -j$(PARALLEL_JOBS) $$($$(PKG)_BUILD_OPTS)
191endef
192endif
193endif
194
195#
196# Host installation step. Only define it if not already defined by the
197# package .mk file.
198#
199ifndef $(2)_INSTALL_CMDS
200define $(2)_INSTALL_CMDS
201	$$(HOST_MAKE_ENV) $$($$(PKG)_BUILD_ENV) $$(BR2_CMAKE) --install $$($$(PKG)_BUILDDIR) $$($$(PKG)_INSTALL_OPTS)
202endef
203endif
204
205#
206# Staging installation step. Only define it if not already defined by
207# the package .mk file.
208#
209ifndef $(2)_INSTALL_STAGING_CMDS
210define $(2)_INSTALL_STAGING_CMDS
211	$$(TARGET_MAKE_ENV) $$($$(PKG)_BUILD_ENV) DESTDIR=$$(STAGING_DIR) $$(BR2_CMAKE) --install $$($$(PKG)_BUILDDIR) $$($$(PKG)_INSTALL_STAGING_OPTS)
212endef
213endif
214
215#
216# Target installation step. Only define it if not already defined by
217# the package .mk file.
218#
219ifndef $(2)_INSTALL_TARGET_CMDS
220define $(2)_INSTALL_TARGET_CMDS
221	$$(TARGET_MAKE_ENV) $$($$(PKG)_BUILD_ENV) DESTDIR=$$(TARGET_DIR) $$(BR2_CMAKE) --install $$($$(PKG)_BUILDDIR) $$($$(PKG)_INSTALL_TARGET_OPTS)
222endef
223endif
224
225# Call the generic package infrastructure to generate the necessary
226# make targets
227$(call inner-generic-package,$(1),$(2),$(3),$(4))
228
229endef
230
231################################################################################
232# cmake-package -- the target generator macro for CMake packages
233################################################################################
234
235cmake-package = $(call inner-cmake-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target)
236host-cmake-package = $(call inner-cmake-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host)
237
238################################################################################
239# Generation of the CMake toolchain file
240################################################################################
241
242# CMAKE_SYSTEM_PROCESSOR should match uname -m
243ifeq ($(BR2_ARM_CPU_ARMV4),y)
244CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT = armv4
245else ifeq ($(BR2_ARM_CPU_ARMV5),y)
246CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT = armv5
247else ifeq ($(BR2_ARM_CPU_ARMV6),y)
248CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT = armv6
249else ifeq ($(BR2_ARM_CPU_ARMV7A),y)
250CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT = armv7
251else ifeq ($(BR2_ARM_CPU_ARMV8A),y)
252CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT = armv8
253endif
254
255ifeq ($(BR2_arm),y)
256CMAKE_SYSTEM_PROCESSOR = $(CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT)l
257else ifeq ($(BR2_armeb),y)
258CMAKE_SYSTEM_PROCESSOR = $(CMAKE_SYSTEM_PROCESSOR_ARM_VARIANT)b
259else ifeq ($(call qstrip,$(BR2_ARCH)),powerpc64)
260CMAKE_SYSTEM_PROCESSOR = ppc64
261else ifeq ($(call qstrip,$(BR2_ARCH)),powerpc64le)
262CMAKE_SYSTEM_PROCESSOR = ppc64le
263else
264CMAKE_SYSTEM_PROCESSOR = $(BR2_ARCH)
265endif
266
267# In order to allow the toolchain to be relocated, we calculate the HOST_DIR
268# based on the toolchainfile.cmake file's location: $(HOST_DIR)/share/buildroot
269# In all the other variables, HOST_DIR will be replaced by RELOCATED_HOST_DIR,
270# so we have to strip "$(HOST_DIR)/" from the paths that contain it.
271define TOOLCHAIN_CMAKE_INSTALL_FILES
272	@mkdir -p $(HOST_DIR)/share/buildroot
273	sed \
274		-e 's#@@STAGING_SUBDIR@@#$(call qstrip,$(STAGING_SUBDIR))#' \
275		-e 's#@@TARGET_CFLAGS@@#$(call qstrip,$(TARGET_CFLAGS))#' \
276		-e 's#@@TARGET_CXXFLAGS@@#$(call qstrip,$(TARGET_CXXFLAGS))#' \
277		-e 's#@@TARGET_FCFLAGS@@#$(call qstrip,$(TARGET_FCFLAGS))#' \
278		-e 's#@@TARGET_LDFLAGS@@#$(call qstrip,$(TARGET_LDFLAGS))#' \
279		-e 's#@@TARGET_CC@@#$(subst $(HOST_DIR)/,,$(call qstrip,$(TARGET_CC)))#' \
280		-e 's#@@TARGET_CXX@@#$(subst $(HOST_DIR)/,,$(call qstrip,$(TARGET_CXX)))#' \
281		-e 's#@@TARGET_FC@@#$(subst $(HOST_DIR)/,,$(call qstrip,$(TARGET_FC)))#' \
282		-e 's#@@CMAKE_SYSTEM_PROCESSOR@@#$(call qstrip,$(CMAKE_SYSTEM_PROCESSOR))#' \
283		-e 's#@@TOOLCHAIN_HAS_CXX@@#$(if $(BR2_INSTALL_LIBSTDCPP),1,0)#' \
284		-e 's#@@TOOLCHAIN_HAS_FORTRAN@@#$(if $(BR2_TOOLCHAIN_HAS_FORTRAN),1,0)#' \
285		-e 's#@@CMAKE_BUILD_TYPE@@#$(if $(BR2_ENABLE_RUNTIME_DEBUG),Debug,Release)#' \
286		$(TOPDIR)/support/misc/toolchainfile.cmake.in \
287		> $(HOST_DIR)/share/buildroot/toolchainfile.cmake
288	$(Q)$(INSTALL) -D -m 0644 support/misc/Buildroot.cmake \
289		$(HOST_DIR)/share/buildroot/Platform/Buildroot.cmake
290endef
291
292TOOLCHAIN_POST_INSTALL_STAGING_HOOKS += TOOLCHAIN_CMAKE_INSTALL_FILES
293