cmake-utils.eclass: Use bash internal testing instead of has()
[gentoo.git] / eclass / cmake-utils.eclass
1 # Copyright 1999-2016 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Id$
4
5 # @ECLASS: cmake-utils.eclass
6 # @MAINTAINER:
7 # kde@gentoo.org
8 # @AUTHOR:
9 # Tomáš Chvátal <scarabeus@gentoo.org>
10 # Maciej Mrozowski <reavertm@gentoo.org>
11 # (undisclosed contributors)
12 # Original author: Zephyrus (zephyrus@mirach.it)
13 # @BLURB: common ebuild functions for cmake-based packages
14 # @DESCRIPTION:
15 # The cmake-utils eclass makes creating ebuilds for cmake-based packages much easier.
16 # It provides all inherited features (DOCS, HTML_DOCS, PATCHES) along with out-of-source
17 # builds (default), in-source builds and an implementation of the well-known use_enable
18 # and use_with functions for CMake.
19
20 if [[ -z ${_CMAKE_UTILS_ECLASS} ]]; then
21 _CMAKE_UTILS_ECLASS=1
22
23
24 # @ECLASS-VARIABLE: BUILD_DIR
25 # @DESCRIPTION:
26 # Build directory where all cmake processed files should be generated.
27 # For in-source build it's fixed to ${CMAKE_USE_DIR}.
28 # For out-of-source build it can be overridden, by default it uses
29 # ${WORKDIR}/${P}_build.
30 #
31 # This variable has been called CMAKE_BUILD_DIR formerly.
32 # It is set under that name for compatibility.
33
34 # @ECLASS-VARIABLE: CMAKE_BINARY
35 # @DESCRIPTION:
36 # Eclass can use different cmake binary than the one provided in by system.
37 : ${CMAKE_BINARY:=cmake}
38
39 # @ECLASS-VARIABLE: CMAKE_BUILD_TYPE
40 # @DESCRIPTION:
41 # Set to override default CMAKE_BUILD_TYPE. Only useful for packages
42 # known to make use of "if (CMAKE_BUILD_TYPE MATCHES xxx)".
43 # If about to be set - needs to be set before invoking cmake-utils_src_configure.
44 # You usualy do *NOT* want nor need to set it as it pulls CMake default build-type
45 # specific compiler flags overriding make.conf.
46 : ${CMAKE_BUILD_TYPE:=Gentoo}
47
48 # @ECLASS-VARIABLE: CMAKE_IN_SOURCE_BUILD
49 # @DESCRIPTION:
50 # Set to enable in-source build.
51
52 # @ECLASS-VARIABLE: CMAKE_MAKEFILE_GENERATOR
53 # @DESCRIPTION:
54 # Specify a makefile generator to be used by cmake.
55 # At this point only "emake" and "ninja" are supported.
56 : ${CMAKE_MAKEFILE_GENERATOR:=emake}
57
58 # @ECLASS-VARIABLE: CMAKE_MIN_VERSION
59 # @DESCRIPTION:
60 # Specify the minimum required CMake version.
61 : ${CMAKE_MIN_VERSION:=2.8.12}
62
63 # @ECLASS-VARIABLE: CMAKE_REMOVE_MODULES
64 # @DESCRIPTION:
65 # Do we want to remove anything? yes or whatever else for no
66 : ${CMAKE_REMOVE_MODULES:=yes}
67
68 # @ECLASS-VARIABLE: CMAKE_REMOVE_MODULES_LIST
69 # @DESCRIPTION:
70 # Space-separated list of CMake modules that will be removed in $S during src_prepare,
71 # in order to force packages to use the system version.
72 : ${CMAKE_REMOVE_MODULES_LIST:=FindBLAS FindLAPACK}
73
74 # @ECLASS-VARIABLE: CMAKE_USE_DIR
75 # @DESCRIPTION:
76 # Sets the directory where we are working with cmake.
77 # For example when application uses autotools and only one
78 # plugin needs to be done by cmake.
79 # By default it uses ${S}.
80
81 # @ECLASS-VARIABLE: CMAKE_VERBOSE
82 # @DESCRIPTION:
83 # Set to OFF to disable verbose messages during compilation
84 : ${CMAKE_VERBOSE:=ON}
85
86 # @ECLASS-VARIABLE: CMAKE_WARN_UNUSED_CLI
87 # @DESCRIPTION:
88 # Warn about variables that are declared on the command line
89 # but not used. Might give false-positives.
90 # "no" to disable (default) or anything else to enable.
91 : ${CMAKE_WARN_UNUSED_CLI:=no}
92
93 # @ECLASS-VARIABLE: PREFIX
94 # @DESCRIPTION:
95 # Eclass respects PREFIX variable, though it's not recommended way to set
96 # install/lib/bin prefixes.
97 # Use -DCMAKE_INSTALL_PREFIX=... CMake variable instead.
98 : ${PREFIX:=/usr}
99
100 # @ECLASS-VARIABLE: WANT_CMAKE
101 # @DESCRIPTION:
102 # Specify if cmake-utils eclass should depend on cmake optionally or not.
103 # This is useful when only part of application is using cmake build system.
104 # Valid values are: always [default], optional (where the value is the useflag
105 # used for optionality)
106 #
107 # This is banned in EAPI 6 and later.
108 : ${WANT_CMAKE:=always}
109
110 # @ECLASS-VARIABLE: CMAKE_EXTRA_CACHE_FILE
111 # @DESCRIPTION:
112 # Specifies an extra cache file to pass to cmake. This is the analog of EXTRA_ECONF
113 # for econf and is needed to pass TRY_RUN results when cross-compiling.
114 # Should be set by user in a per-package basis in /etc/portage/package.env.
115
116 case ${EAPI} in
117         2|3|4|5|6) : ;;
118         *) die "EAPI=${EAPI:-0} is not supported" ;;
119 esac
120
121 inherit toolchain-funcs multilib flag-o-matic eutils versionator
122
123 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
124
125 CMAKEDEPEND=""
126 case ${WANT_CMAKE} in
127         always)
128                 ;;
129         *)
130                 [[ ${EAPI} == [2345] ]] || die "WANT_CMAKE is banned in EAPI 6 and later"
131                 IUSE+=" ${WANT_CMAKE}"
132                 CMAKEDEPEND+="${WANT_CMAKE}? ( "
133                 ;;
134 esac
135
136 case ${CMAKE_MAKEFILE_GENERATOR} in
137         emake)
138                 CMAKEDEPEND+=" sys-devel/make"
139                 ;;
140         ninja)
141                 CMAKEDEPEND+=" dev-util/ninja"
142                 ;;
143         *)
144                 eerror "Unknown value for \${CMAKE_MAKEFILE_GENERATOR}"
145                 die "Value ${CMAKE_MAKEFILE_GENERATOR} is not supported"
146                 ;;
147 esac
148
149 if [[ ${PN} != cmake ]]; then
150         CMAKEDEPEND+=" >=dev-util/cmake-${CMAKE_MIN_VERSION}"
151 fi
152
153 CMAKEDEPEND+=" userland_GNU? ( >=sys-apps/findutils-4.4.0 )"
154
155 [[ ${WANT_CMAKE} = always ]] || CMAKEDEPEND+=" )"
156
157 DEPEND="${CMAKEDEPEND}"
158 unset CMAKEDEPEND
159
160 # Internal functions used by cmake-utils_use_*
161 _cmake_use_me_now() {
162         debug-print-function ${FUNCNAME} "$@"
163
164         local arg=$2
165         [[ ! -z $3 ]] && arg=$3
166
167         [[ ${EAPI} == [2345] ]] || die "${FUNCNAME[1]} is banned in EAPI 6 and later: use -D$1${arg}=\"\$(usex $2)\" instead"
168
169         local uper capitalised x
170         [[ -z $2 ]] && die "cmake-utils_use-$1 <USE flag> [<flag name>]"
171         if [[ ! -z $3 ]]; then
172                 # user specified the use name so use it
173                 echo "-D$1$3=$(use $2 && echo ON || echo OFF)"
174         else
175                 # use all various most used combinations
176                 uper=$(echo ${2} | tr '[:lower:]' '[:upper:]')
177                 capitalised=$(echo ${2} | sed 's/\<\(.\)\([^ ]*\)/\u\1\L\2/g')
178                 for x in $2 $uper $capitalised; do
179                         echo "-D$1$x=$(use $2 && echo ON || echo OFF) "
180                 done
181         fi
182 }
183 _cmake_use_me_now_inverted() {
184         debug-print-function ${FUNCNAME} "$@"
185
186         local arg=$2
187         [[ ! -z $3 ]] && arg=$3
188
189         if [[ ${EAPI} != [2345] ]] && [[ "${FUNCNAME[1]}" != cmake-utils_use_find_package ]] ; then
190                 die "${FUNCNAME[1]} is banned in EAPI 6 and later: use -D$1${arg}=\"\$(usex $2)\" insteadss"
191         fi
192
193         local uper capitalised x
194         [[ -z $2 ]] && die "cmake-utils_use-$1 <USE flag> [<flag name>]"
195         if [[ ! -z $3 ]]; then
196                 # user specified the use name so use it
197                 echo "-D$1$3=$(use $2 && echo OFF || echo ON)"
198         else
199                 # use all various most used combinations
200                 uper=$(echo ${2} | tr '[:lower:]' '[:upper:]')
201                 capitalised=$(echo ${2} | sed 's/\<\(.\)\([^ ]*\)/\u\1\L\2/g')
202                 for x in $2 $uper $capitalised; do
203                         echo "-D$1$x=$(use $2 && echo OFF || echo ON) "
204                 done
205         fi
206 }
207
208 # Determine using IN or OUT source build
209 _cmake_check_build_dir() {
210         : ${CMAKE_USE_DIR:=${S}}
211         if [[ -n ${CMAKE_IN_SOURCE_BUILD} ]]; then
212                 # we build in source dir
213                 BUILD_DIR="${CMAKE_USE_DIR}"
214         else
215                 # Respect both the old variable and the new one, depending
216                 # on which one was set by the ebuild.
217                 if [[ ! ${BUILD_DIR} && ${CMAKE_BUILD_DIR} ]]; then
218                         eqawarn "The CMAKE_BUILD_DIR variable has been renamed to BUILD_DIR."
219                         eqawarn "Please migrate the ebuild to use the new one."
220
221                         # In the next call, both variables will be set already
222                         # and we'd have to know which one takes precedence.
223                         _RESPECT_CMAKE_BUILD_DIR=1
224                 fi
225
226                 if [[ ${_RESPECT_CMAKE_BUILD_DIR} ]]; then
227                         BUILD_DIR=${CMAKE_BUILD_DIR:-${WORKDIR}/${P}_build}
228                 else
229                         : ${BUILD_DIR:=${WORKDIR}/${P}_build}
230                 fi
231         fi
232
233         # Backwards compatibility for getting the value.
234         CMAKE_BUILD_DIR=${BUILD_DIR}
235
236         mkdir -p "${BUILD_DIR}" || die
237         echo ">>> Working in BUILD_DIR: \"$BUILD_DIR\""
238 }
239
240 # Determine which generator to use
241 _cmake_generator_to_use() {
242         local generator_name
243
244         case ${CMAKE_MAKEFILE_GENERATOR} in
245                 ninja)
246                         # if ninja is enabled but not installed, the build could fail
247                         # this could happen if ninja is manually enabled (eg. make.conf) but not installed
248                         if ! has_version dev-util/ninja; then
249                                 die "CMAKE_MAKEFILE_GENERATOR is set to ninja, but ninja is not installed. Please install dev-util/ninja or unset CMAKE_MAKEFILE_GENERATOR."
250                         fi
251                         generator_name="Ninja"
252                         ;;
253                 emake)
254                         generator_name="Unix Makefiles"
255                         ;;
256                 *)
257                         eerror "Unknown value for \${CMAKE_MAKEFILE_GENERATOR}"
258                         die "Value ${CMAKE_MAKEFILE_GENERATOR} is not supported"
259                         ;;
260         esac
261
262         echo ${generator_name}
263 }
264
265 # @FUNCTION: cmake_comment_add_subdirectory
266 # @USAGE: <subdirectory>
267 # @DESCRIPTION:
268 # Comment out an add_subdirectory call in CMakeLists.txt in the current directory
269 cmake_comment_add_subdirectory() {
270         if [[ -z ${1} ]]; then
271                 die "comment_add_subdirectory must be passed the directory name to comment"
272         fi
273
274         if [[ -e "CMakeLists.txt" ]]; then
275                 sed -e "/add_subdirectory[[:space:]]*([[:space:]]*${1//\//\\/}[[:space:]]*)/I s/^/#DONOTCOMPILE /" \
276                         -i CMakeLists.txt || die "failed to comment add_subdirectory(${1})"
277         fi
278 }
279
280 # @FUNCTION: comment_add_subdirectory
281 # @USAGE: <subdirectory>
282 # @DESCRIPTION:
283 # Comment out an add_subdirectory call in CMakeLists.txt in the current directory
284 # Banned in EAPI 6 and later - use cmake_comment_add_subdirectory instead.
285 comment_add_subdirectory() {
286         [[ ${EAPI} == [2345] ]] || die "comment_add_subdirectory is banned in EAPI 6 and later - use cmake_comment_add_subdirectory instead"
287
288         cmake_comment_add_subdirectory "$@"
289 }
290
291 # @FUNCTION: cmake-utils_use_with
292 # @USAGE: <USE flag> [flag name]
293 # @DESCRIPTION:
294 # Based on use_with. See ebuild(5).
295 #
296 # `cmake-utils_use_with foo FOO` echoes -DWITH_FOO=ON if foo is enabled
297 # and -DWITH_FOO=OFF if it is disabled.
298 cmake-utils_use_with() { _cmake_use_me_now WITH_ "$@" ; }
299
300 # @FUNCTION: cmake-utils_use_enable
301 # @USAGE: <USE flag> [flag name]
302 # @DESCRIPTION:
303 # Based on use_enable. See ebuild(5).
304 #
305 # `cmake-utils_use_enable foo FOO` echoes -DENABLE_FOO=ON if foo is enabled
306 # and -DENABLE_FOO=OFF if it is disabled.
307 cmake-utils_use_enable() { _cmake_use_me_now ENABLE_ "$@" ; }
308
309 # @FUNCTION: cmake-utils_use_find_package
310 # @USAGE: <USE flag> <package name>
311 # @DESCRIPTION:
312 # Based on use_enable. See ebuild(5).
313 #
314 # `cmake-utils_use_find_package foo LibFoo` echoes -DCMAKE_DISABLE_FIND_PACKAGE_LibFoo=OFF
315 # if foo is enabled and -DCMAKE_DISABLE_FIND_PACKAGE_LibFoo=ON if it is disabled.
316 # This can be used to make find_package optional.
317 cmake-utils_use_find_package() {
318         if [[ ${EAPI} != [2345] ]] && [[ "$#" != 2 ]] ; then
319                 die "Usage: cmake-utils_use_find_package <USE flag> <package name>"
320         fi
321
322         _cmake_use_me_now_inverted CMAKE_DISABLE_FIND_PACKAGE_ "$@" ;
323 }
324
325 # @FUNCTION: cmake-utils_use_disable
326 # @USAGE: <USE flag> [flag name]
327 # @DESCRIPTION:
328 # Based on inversion of use_enable. See ebuild(5).
329 #
330 # `cmake-utils_use_enable foo FOO` echoes -DDISABLE_FOO=OFF if foo is enabled
331 # and -DDISABLE_FOO=ON if it is disabled.
332 cmake-utils_use_disable() { _cmake_use_me_now_inverted DISABLE_ "$@" ; }
333
334 # @FUNCTION: cmake-utils_use_no
335 # @USAGE: <USE flag> [flag name]
336 # @DESCRIPTION:
337 # Based on use_disable. See ebuild(5).
338 #
339 # `cmake-utils_use_no foo FOO` echoes -DNO_FOO=OFF if foo is enabled
340 # and -DNO_FOO=ON if it is disabled.
341 cmake-utils_use_no() { _cmake_use_me_now_inverted NO_ "$@" ; }
342
343 # @FUNCTION: cmake-utils_use_want
344 # @USAGE: <USE flag> [flag name]
345 # @DESCRIPTION:
346 # Based on use_enable. See ebuild(5).
347 #
348 # `cmake-utils_use_want foo FOO` echoes -DWANT_FOO=ON if foo is enabled
349 # and -DWANT_FOO=OFF if it is disabled.
350 cmake-utils_use_want() { _cmake_use_me_now WANT_ "$@" ; }
351
352 # @FUNCTION: cmake-utils_use_build
353 # @USAGE: <USE flag> [flag name]
354 # @DESCRIPTION:
355 # Based on use_enable. See ebuild(5).
356 #
357 # `cmake-utils_use_build foo FOO` echoes -DBUILD_FOO=ON if foo is enabled
358 # and -DBUILD_FOO=OFF if it is disabled.
359 cmake-utils_use_build() { _cmake_use_me_now BUILD_ "$@" ; }
360
361 # @FUNCTION: cmake-utils_use_has
362 # @USAGE: <USE flag> [flag name]
363 # @DESCRIPTION:
364 # Based on use_enable. See ebuild(5).
365 #
366 # `cmake-utils_use_has foo FOO` echoes -DHAVE_FOO=ON if foo is enabled
367 # and -DHAVE_FOO=OFF if it is disabled.
368 cmake-utils_use_has() { _cmake_use_me_now HAVE_ "$@" ; }
369
370 # @FUNCTION: cmake-utils_use_use
371 # @USAGE: <USE flag> [flag name]
372 # @DESCRIPTION:
373 # Based on use_enable. See ebuild(5).
374 #
375 # `cmake-utils_use_use foo FOO` echoes -DUSE_FOO=ON if foo is enabled
376 # and -DUSE_FOO=OFF if it is disabled.
377 cmake-utils_use_use() { _cmake_use_me_now USE_ "$@" ; }
378
379 # @FUNCTION: cmake-utils_use
380 # @USAGE: <USE flag> [flag name]
381 # @DESCRIPTION:
382 # Based on use_enable. See ebuild(5).
383 #
384 # `cmake-utils_use foo FOO` echoes -DFOO=ON if foo is enabled
385 # and -DFOO=OFF if it is disabled.
386 cmake-utils_use() { _cmake_use_me_now "" "$@" ; }
387
388 # @FUNCTION: cmake-utils_useno
389 # @USAGE: <USE flag> [flag name]
390 # @DESCRIPTION:
391 # Based on use_enable. See ebuild(5).
392 #
393 # `cmake-utils_useno foo NOFOO` echoes -DNOFOO=OFF if foo is enabled
394 # and -DNOFOO=ON if it is disabled.
395 cmake-utils_useno() { _cmake_use_me_now_inverted "" "$@" ; }
396
397 # Internal function for modifying hardcoded definitions.
398 # Removes dangerous definitions that override Gentoo settings.
399 _cmake_modify-cmakelists() {
400         debug-print-function ${FUNCNAME} "$@"
401
402         # Only edit the files once
403         grep -qs "<<< Gentoo configuration >>>" "${CMAKE_USE_DIR}"/CMakeLists.txt && return 0
404
405         # Comment out all set (<some_should_be_user_defined_variable> value)
406         # TODO Add QA checker - inform when variable being checked for below is set in CMakeLists.txt
407         find "${CMAKE_USE_DIR}" -name CMakeLists.txt \
408                 -exec sed -i -e '/^[[:space:]]*[sS][eE][tT][[:space:]]*([[:space:]]*CMAKE_BUILD_TYPE.*)/{s/^/#IGNORE /g}' {} + \
409                 -exec sed -i -e '/^[[:space:]]*[sS][eE][tT][[:space:]]*([[:space:]]*CMAKE_COLOR_MAKEFILE.*)/{s/^/#IGNORE /g}' {} + \
410                 -exec sed -i -e '/^[[:space:]]*[sS][eE][tT][[:space:]]*([[:space:]]*CMAKE_INSTALL_PREFIX.*)/{s/^/#IGNORE /g}' {} + \
411                 -exec sed -i -e '/^[[:space:]]*[sS][eE][tT][[:space:]]*([[:space:]]*CMAKE_VERBOSE_MAKEFILE.*)/{s/^/#IGNORE /g}' {} + \
412                 || die "${LINENO}: failed to disable hardcoded settings"
413
414         # NOTE Append some useful summary here
415         cat >> "${CMAKE_USE_DIR}"/CMakeLists.txt <<- _EOF_ || die
416
417                 MESSAGE(STATUS "<<< Gentoo configuration >>>
418                 Build type      \${CMAKE_BUILD_TYPE}
419                 Install path    \${CMAKE_INSTALL_PREFIX}
420                 Compiler flags:
421                 C               \${CMAKE_C_FLAGS}
422                 C++             \${CMAKE_CXX_FLAGS}
423                 Linker flags:
424                 Executable      \${CMAKE_EXE_LINKER_FLAGS}
425                 Module          \${CMAKE_MODULE_LINKER_FLAGS}
426                 Shared          \${CMAKE_SHARED_LINKER_FLAGS}\n")
427         _EOF_
428 }
429
430 # temporary function for moving cmake cleanups from from src_configure -> src_prepare.
431 # bug #378850
432 _cmake_cleanup_cmake() {
433         : ${CMAKE_USE_DIR:=${S}}
434
435         if [[ "${CMAKE_REMOVE_MODULES}" == "yes" ]] ; then
436                 local name
437                 for name in ${CMAKE_REMOVE_MODULES_LIST} ; do
438                         find "${S}" -name ${name}.cmake -exec rm -v {} + || die
439                 done
440         fi
441
442         # check if CMakeLists.txt exist and if no then die
443         if [[ ! -e ${CMAKE_USE_DIR}/CMakeLists.txt ]] ; then
444                 eerror "Unable to locate CMakeLists.txt under:"
445                 eerror "\"${CMAKE_USE_DIR}/CMakeLists.txt\""
446                 eerror "Consider not inheriting the cmake eclass."
447                 die "FATAL: Unable to find CMakeLists.txt"
448         fi
449
450         # Remove dangerous things.
451         _cmake_modify-cmakelists
452 }
453
454 enable_cmake-utils_src_prepare() {
455         debug-print-function ${FUNCNAME} "$@"
456
457         pushd "${S}" > /dev/null || die
458
459         if [[ ${EAPI} != [2345] ]]; then
460                 default_src_prepare
461                 _cmake_cleanup_cmake
462         else
463                 debug-print "$FUNCNAME: PATCHES=$PATCHES"
464                 [[ ${PATCHES[@]} ]] && epatch "${PATCHES[@]}"
465
466                 debug-print "$FUNCNAME: applying user patches"
467                 epatch_user
468         fi
469
470         popd > /dev/null || die
471 }
472
473 # @VARIABLE: mycmakeargs
474 # @DEFAULT_UNSET
475 # @DESCRIPTION:
476 # Optional cmake defines as a bash array. Should be defined before calling
477 # src_configure.
478 # @CODE
479 # src_configure() {
480 #       local mycmakeargs=(
481 #               $(cmake-utils_use_with openconnect)
482 #       )
483 #
484 #       cmake-utils_src_configure
485 # }
486 # @CODE
487
488 enable_cmake-utils_src_configure() {
489         debug-print-function ${FUNCNAME} "$@"
490
491         [[ ${EAPI} == [2345] ]] && _cmake_cleanup_cmake
492
493         _cmake_check_build_dir
494
495         # Fix xdg collision with sandbox
496         local -x XDG_CONFIG_HOME="${T}"
497
498         # @SEE CMAKE_BUILD_TYPE
499         if [[ ${CMAKE_BUILD_TYPE} = Gentoo ]]; then
500                 # Handle release builds
501                 if ! has debug ${IUSE//+} || ! use debug; then
502                         local CPPFLAGS=${CPPFLAGS}
503                         append-cppflags -DNDEBUG
504                 fi
505         fi
506
507         # Prepare Gentoo override rules (set valid compiler, append CPPFLAGS etc.)
508         local build_rules=${BUILD_DIR}/gentoo_rules.cmake
509         # Since cmake-3.4.0_rc1 "<FLAGS>" no longer contains includes and thus
510         # we need to add "<INCLUDES>"
511         local includes=
512         if [[ ${PN} == cmake ]] ; then
513                 if $(version_is_at_least 3.4.0 $(get_version_component_range 1-3 ${PV})) ; then
514                         includes="<INCLUDES>"
515                 fi
516         elif ROOT=/ has_version \>=dev-util/cmake-3.4.0_rc1 ; then
517                 includes="<INCLUDES>"
518         fi
519         cat > "${build_rules}" <<- _EOF_ || die
520                 SET (CMAKE_AR $(type -P $(tc-getAR)) CACHE FILEPATH "Archive manager" FORCE)
521                 SET (CMAKE_ASM_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> ${includes} ${CFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "ASM compile command" FORCE)
522                 SET (CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> ${includes} ${CPPFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "C compile command" FORCE)
523                 SET (CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> <DEFINES> ${includes} ${CPPFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "C++ compile command" FORCE)
524                 SET (CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> <DEFINES> ${includes} ${FCFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "Fortran compile command" FORCE)
525                 SET (CMAKE_RANLIB $(type -P $(tc-getRANLIB)) CACHE FILEPATH "Archive index generator" FORCE)
526                 SET (PKG_CONFIG_EXECUTABLE $(type -P $(tc-getPKG_CONFIG)) CACHE FILEPATH "pkg-config executable" FORCE)
527         _EOF_
528
529         local toolchain_file=${BUILD_DIR}/gentoo_toolchain.cmake
530         cat > ${toolchain_file} <<- _EOF_ || die
531                 SET (CMAKE_C_COMPILER $(tc-getCC))
532                 SET (CMAKE_CXX_COMPILER $(tc-getCXX))
533                 SET (CMAKE_Fortran_COMPILER $(tc-getFC))
534         _EOF_
535
536         if tc-is-cross-compiler; then
537                 local sysname
538                 case "${KERNEL:-linux}" in
539                         Cygwin) sysname="CYGWIN_NT-5.1" ;;
540                         HPUX) sysname="HP-UX" ;;
541                         linux) sysname="Linux" ;;
542                         Winnt)
543                                 sysname="Windows"
544                                 cat >> "${toolchain_file}" <<- _EOF_ || die
545                                         SET (CMAKE_RC_COMPILER $(tc-getRC))
546                                 _EOF_
547                                 ;;
548                         *) sysname="${KERNEL}" ;;
549                 esac
550
551                 cat >> "${toolchain_file}" <<- _EOF_ || die
552                         SET (CMAKE_SYSTEM_NAME "${sysname}")
553                 _EOF_
554
555                 if [ "${SYSROOT:-/}" != "/" ] ; then
556                         # When cross-compiling with a sysroot (e.g. with crossdev's emerge wrappers)
557                         # we need to tell cmake to use libs/headers from the sysroot but programs from / only.
558                         cat >> "${toolchain_file}" <<- _EOF_ || die
559                                 set(CMAKE_FIND_ROOT_PATH "${SYSROOT}")
560                                 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
561                                 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
562                                 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
563                         _EOF_
564                 fi
565         fi
566
567         [[ ${EAPI} == 2 ]] && ! use prefix && local EPREFIX=
568
569         if [[ ${EPREFIX} ]]; then
570                 cat >> "${build_rules}" <<- _EOF_ || die
571                         # in Prefix we need rpath and must ensure cmake gets our default linker path
572                         # right ... except for Darwin hosts
573                         IF (NOT APPLE)
574                         SET (CMAKE_SKIP_RPATH OFF CACHE BOOL "" FORCE)
575                         SET (CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH "${EPREFIX}/usr/${CHOST}/lib/gcc;${EPREFIX}/usr/${CHOST}/lib;${EPREFIX}/usr/$(get_libdir);${EPREFIX}/$(get_libdir)"
576                         CACHE STRING "" FORCE)
577
578                         ELSE ()
579
580                         SET(CMAKE_PREFIX_PATH "${EPREFIX}${PREFIX}" CACHE STRING "" FORCE)
581                         SET(CMAKE_SKIP_BUILD_RPATH OFF CACHE BOOL "" FORCE)
582                         SET(CMAKE_SKIP_RPATH OFF CACHE BOOL "" FORCE)
583                         SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE CACHE BOOL "")
584                         SET(CMAKE_INSTALL_RPATH "${EPREFIX}${PREFIX}/lib;${EPREFIX}/usr/${CHOST}/lib/gcc;${EPREFIX}/usr/${CHOST}/lib;${EPREFIX}/usr/$(get_libdir);${EPREFIX}/$(get_libdir)" CACHE STRING "" FORCE)
585                         SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE BOOL "" FORCE)
586                         SET(CMAKE_INSTALL_NAME_DIR "${EPREFIX}${PREFIX}/lib" CACHE STRING "" FORCE)
587
588                         ENDIF (NOT APPLE)
589                 _EOF_
590         fi
591
592         # Common configure parameters (invariants)
593         local common_config=${BUILD_DIR}/gentoo_common_config.cmake
594         local libdir=$(get_libdir)
595         cat > "${common_config}" <<- _EOF_ || die
596                 SET (LIB_SUFFIX ${libdir/lib} CACHE STRING "library path suffix" FORCE)
597                 SET (CMAKE_INSTALL_LIBDIR ${libdir} CACHE PATH "Output directory for libraries")
598         _EOF_
599         [[ "${NOCOLOR}" = true || "${NOCOLOR}" = yes ]] && echo 'SET (CMAKE_COLOR_MAKEFILE OFF CACHE BOOL "pretty colors during make" FORCE)' >> "${common_config}"
600
601         # Convert mycmakeargs to an array, for backwards compatibility
602         # Make the array a local variable since <=portage-2.1.6.x does not
603         # support global arrays (see bug #297255).
604         local mycmakeargstype=$(declare -p mycmakeargs 2>&-)
605         if [[ "${mycmakeargstype}" != "declare -a mycmakeargs="* ]]; then
606                 if [[ -n "${mycmakeargstype}" ]] ; then
607                         if [[ ${EAPI} != [2345] ]]; then
608                                 eqawarn "Declaring mycmakeargs as a variable is deprecated. Please use an array instead."
609                         else
610                                 die "Declaring mycmakeargs as a variable is banned in EAPI=${EAPI}. Please use an array instead."
611                         fi
612                 fi
613                 local mycmakeargs_local=(${mycmakeargs})
614         else
615                 local mycmakeargs_local=("${mycmakeargs[@]}")
616         fi
617
618         if [[ ${CMAKE_WARN_UNUSED_CLI} == no ]] ; then
619                 local warn_unused_cli="--no-warn-unused-cli"
620         else
621                 local warn_unused_cli=""
622         fi
623
624         # Common configure parameters (overridable)
625         # NOTE CMAKE_BUILD_TYPE can be only overriden via CMAKE_BUILD_TYPE eclass variable
626         # No -DCMAKE_BUILD_TYPE=xxx definitions will be in effect.
627         local cmakeargs=(
628                 ${warn_unused_cli}
629                 -C "${common_config}"
630                 -G "$(_cmake_generator_to_use)"
631                 -DCMAKE_INSTALL_PREFIX="${EPREFIX}${PREFIX}"
632                 "${mycmakeargs_local[@]}"
633                 -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
634                 -DCMAKE_INSTALL_DO_STRIP=OFF
635                 -DCMAKE_USER_MAKE_RULES_OVERRIDE="${build_rules}"
636                 -DCMAKE_TOOLCHAIN_FILE="${toolchain_file}"
637                 "${MYCMAKEARGS}"
638         )
639
640         if [[ -n "${CMAKE_EXTRA_CACHE_FILE}" ]] ; then
641                 cmakeargs+=( -C "${CMAKE_EXTRA_CACHE_FILE}" )
642         fi
643
644         pushd "${BUILD_DIR}" > /dev/null || die
645         debug-print "${LINENO} ${ECLASS} ${FUNCNAME}: mycmakeargs is ${mycmakeargs_local[*]}"
646         echo "${CMAKE_BINARY}" "${cmakeargs[@]}" "${CMAKE_USE_DIR}"
647         "${CMAKE_BINARY}" "${cmakeargs[@]}" "${CMAKE_USE_DIR}" || die "cmake failed"
648         popd > /dev/null || die
649 }
650
651 enable_cmake-utils_src_compile() {
652         debug-print-function ${FUNCNAME} "$@"
653
654         cmake-utils_src_make "$@"
655 }
656
657 _ninjaopts_from_makeopts() {
658         if [[ ${NINJAOPTS+set} == set ]]; then
659                 return 0
660         fi
661         local ninjaopts=()
662         set -- ${MAKEOPTS}
663         while (( $# )); do
664                 case $1 in
665                         -j|-l|-k)
666                                 ninjaopts+=( $1 $2 )
667                                 shift 2
668                                 ;;
669                         -j*|-l*|-k*)
670                                 ninjaopts+=( $1 )
671                                 shift 1
672                                 ;;
673                         *) shift ;;
674                 esac
675         done
676         export NINJAOPTS="${ninjaopts[*]}"
677 }
678
679 # @FUNCTION: _cmake_ninja_src_make
680 # @INTERNAL
681 # @DESCRIPTION:
682 # Build the package using ninja generator
683 _cmake_ninja_src_make() {
684         debug-print-function ${FUNCNAME} "$@"
685
686         [[ -e build.ninja ]] || die "build.ninja not found. Error during configure stage."
687
688         _ninjaopts_from_makeopts
689
690         if [[ "${CMAKE_VERBOSE}" != "OFF" ]]; then
691                 set -- ninja ${NINJAOPTS} -v "$@"
692         else
693                 set -- ninja ${NINJAOPTS} "$@"
694         fi
695
696         echo "$@"
697         "$@" || die
698 }
699
700 # @FUNCTION: _cmake_emake_src_make
701 # @INTERNAL
702 # @DESCRIPTION:
703 # Build the package using make generator
704 _cmake_emake_src_make() {
705         debug-print-function ${FUNCNAME} "$@"
706
707         [[ -e Makefile ]] || die "Makefile not found. Error during configure stage."
708
709         if [[ "${CMAKE_VERBOSE}" != "OFF" ]]; then
710                 emake VERBOSE=1 "$@" || die
711         else
712                 emake "$@" || die
713         fi
714
715 }
716
717 # @FUNCTION: cmake-utils_src_make
718 # @DESCRIPTION:
719 # Function for building the package. Automatically detects the build type.
720 # All arguments are passed to emake.
721 cmake-utils_src_make() {
722         debug-print-function ${FUNCNAME} "$@"
723
724         _cmake_check_build_dir
725         pushd "${BUILD_DIR}" > /dev/null || die
726
727         _cmake_${CMAKE_MAKEFILE_GENERATOR}_src_make "$@"
728
729         popd > /dev/null || die
730 }
731
732 enable_cmake-utils_src_test() {
733         debug-print-function ${FUNCNAME} "$@"
734
735         _cmake_check_build_dir
736         pushd "${BUILD_DIR}" > /dev/null || die
737         [[ -e CTestTestfile.cmake ]] || { echo "No tests found. Skipping."; return 0 ; }
738
739         [[ -n ${TEST_VERBOSE} ]] && myctestargs+=( --extra-verbose --output-on-failure )
740
741         if ctest "${myctestargs[@]}" "$@" ; then
742                 einfo "Tests succeeded."
743                 popd > /dev/null || die
744                 return 0
745         else
746                 if [[ -n "${CMAKE_YES_I_WANT_TO_SEE_THE_TEST_LOG}" ]] ; then
747                         # on request from Diego
748                         eerror "Tests failed. Test log ${BUILD_DIR}/Testing/Temporary/LastTest.log follows:"
749                         eerror "--START TEST LOG--------------------------------------------------------------"
750                         cat "${BUILD_DIR}/Testing/Temporary/LastTest.log"
751                         eerror "--END TEST LOG----------------------------------------------------------------"
752                         die "Tests failed."
753                 else
754                         die "Tests failed. When you file a bug, please attach the following file: \n\t${BUILD_DIR}/Testing/Temporary/LastTest.log"
755                 fi
756
757                 # die might not die due to nonfatal
758                 popd > /dev/null || die
759                 return 1
760         fi
761 }
762
763 enable_cmake-utils_src_install() {
764         debug-print-function ${FUNCNAME} "$@"
765
766         _cmake_check_build_dir
767         pushd "${BUILD_DIR}" > /dev/null || die
768         DESTDIR="${D}" ${CMAKE_MAKEFILE_GENERATOR} install "$@" || die "died running ${CMAKE_MAKEFILE_GENERATOR} install"
769         popd > /dev/null || die
770
771         pushd "${S}" > /dev/null || die
772         einstalldocs
773         popd > /dev/null || die
774 }
775
776 # @FUNCTION: cmake-utils_src_prepare
777 # @DESCRIPTION:
778 # Apply ebuild and user patches.
779 cmake-utils_src_prepare() {
780         _cmake_execute_optionally "src_prepare" "$@"
781 }
782
783 # @FUNCTION: cmake-utils_src_configure
784 # @DESCRIPTION:
785 # General function for configuring with cmake. Default behaviour is to start an
786 # out-of-source build.
787 cmake-utils_src_configure() {
788         _cmake_execute_optionally "src_configure" "$@"
789 }
790
791 # @FUNCTION: cmake-utils_src_compile
792 # @DESCRIPTION:
793 # General function for compiling with cmake.
794 # Automatically detects the build type. All arguments are passed to emake.
795 cmake-utils_src_compile() {
796         _cmake_execute_optionally "src_compile" "$@"
797 }
798
799 # @FUNCTION: cmake-utils_src_test
800 # @DESCRIPTION:
801 # Function for testing the package. Automatically detects the build type.
802 cmake-utils_src_test() {
803         _cmake_execute_optionally "src_test" "$@"
804 }
805
806 # @FUNCTION: cmake-utils_src_install
807 # @DESCRIPTION:
808 # Function for installing the package. Automatically detects the build type.
809 cmake-utils_src_install() {
810         _cmake_execute_optionally "src_install" "$@"
811 }
812
813 # Optionally executes phases based on WANT_CMAKE variable/USE flag.
814 _cmake_execute_optionally() {
815         local phase="$1" ; shift
816         if [[ ${WANT_CMAKE} = always ]]; then
817                 enable_cmake-utils_${phase} "$@"
818         else
819                 use ${WANT_CMAKE} && enable_cmake-utils_${phase} "$@"
820         fi
821 }
822
823 fi