summaryrefslogtreecommitdiffstats
path: root/cmake/Modules/MakeDistcheck.cmake
blob: 1f383a5994c8ebc6717e976fde13091d33d95c6d (plain)
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
# - adds support for the 'make distcheck' command      -*- cmake -*-
# Dependencies:
# 1. CPack generating ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz.
# 2. Having a "dist" target, e.g:
#    add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
# Usage:
#   add_distcheck()    ... called exactly once per project in the top-level
#                         CMakeLists.txt; it adds the 'dist' and 'distcheck'
#                         targets
#
# This module implements the 'make dist' and 'make distcheck'
# commands.
# It supports the following variables:
#
#   DISTCHECK_TMPDIR   ... directory for temporary files
#   DISTCHECK_FILENAME ... basename of existing tar.gz.; defaults to
#                         ${CPACK_SOURCE_PACKAGE_FILE_NAME}
#   DISTCHECK_CMAKEFLAGS
#                     ... flags which are given to 'cmake' by 'make distcheck'
#   DISTCHECK_BUILDTARGETS
#                     ... the build-targets tried by 'make distcheck';
#                         defaults to nothing (--> all)
#   DISTCHECK_INSTALLTARGETS
#                     ... the install-targets tried by 'make distcheck';
#                         defaults to 'install'
#
# Example:
#   --- top-level CMakeLists.txt ---
#   add_subdirectory(foo)
#   ...
#   ...
#   set(CPACK_PACKAGE_VERSION_MAJOR ${ECRIRE_VERSION_MAJOR})
#   set(CPACK_PACKAGE_VERSION_MINOR ${ECRIRE_VERSION_MINOR})
#   set(CPACK_PACKAGE_VERSION_PATCH ${ECRIRE_VERSION_MICRO})
#   set(CPACK_SOURCE_GENERATOR "TGZ")
#   set(CPACK_SOURCE_IGNORE_FILES
#      "${CMAKE_BINARY_DIR};/.git/;~$;${CPACK_SOURCE_IGNORE_FILES}")
#   include(CPack)
#   add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
#
#   find_package(Distcheck)
#   add_distcheck()
#
#
# Copyright (C) 2012 Tom Hacohen <tom@stosb.com>
# Based on the work done by:
# Copyright (C) 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
#
# Redistribution and use, with or without modification, are permitted
# provided that the following conditions are met:
# 
#    1. Redistributions must retain the above copyright notice, this
#       list of conditions and the following disclaimer.
#    2. The name of the author may not be used to endorse or promote
#       products derived from this software without specific prior
#       written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

macro(add_distcheck)
   set(MakeDist_FOUND 1)

   set(DISTCHECK_TMPDIR         "${CMAKE_BINARY_DIR}/.make-dist"                  CACHE PATH "directory for temporary files created by'make dist*'")
   set(DISTCHECK_FILENAME       ${CPACK_SOURCE_PACKAGE_FILE_NAME}                 CACHE PATH "basename of the tarball created by 'make dist'")
   set(DISTCHECK_CMAKEFLAGS                                                       CACHE STRING "flags which are given to 'cmake' by 'make distcheck'")
   set(DISTCHECK_BUILDTARGETS   ""                                                CACHE STRING "build-target(s) tried by 'make distcheck'")
   set(DISTCHECK_INSTALLTARGETS install                                           CACHE STRING "install-target(s) tried by 'make distcheck'")

   mark_as_advanced(DISTCHECK_TMPDIR DISTCHECK_FILENAME DISTCHECK_CMAKEFLAGS DISTCHECK_BUILDTARGETS DISTCHECK_INSTALLTARGETS)

   set(DISTCHECK_BASESOURCEDIR "${DISTCHECK_TMPDIR}/source")
   set(DISTCHECK_SOURCEDIR "${DISTCHECK_BASESOURCEDIR}/${DISTCHECK_FILENAME}")
   set(DISTCHECK_BUILDDIR "${DISTCHECK_TMPDIR}/build")
   set(DISTCHECK_INSTALLTARGETS "install")
   add_custom_target(distcheck
      # Create the tarball
      COMMAND ${CMAKE_MAKE_PROGRAM} dist

      # Create the temp dir.
      COMMAND chmod -Rf a+w "${DISTCHECK_TMPDIR}" 2>/dev/null || :
      COMMAND rm -rf "${DISTCHECK_TMPDIR}"
      COMMAND mkdir -p "${DISTCHECK_SOURCEDIR}" "${DISTCHECK_BUILDDIR}"

      # extract tarball
      COMMAND tar xzf ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz -C "${DISTCHECK_BASESOURCEDIR}"
      # write-protect sources to detect modifies-sourcetree bugs
      COMMAND chmod -R a-w "${DISTCHECK_SOURCEDIR}"

      COMMAND cd "${DISTCHECK_BUILDDIR}" && ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX:PATH="${DISTCHECK_TMPDIR}/install" ${DISTCHECK_CMAKEFLAGS} "${DISTCHECK_SOURCEDIR}"

      COMMAND cd "${DISTCHECK_BUILDDIR}"  && ${CMAKE_MAKE_PROGRAM} ${DISTCHECK_BUILDTARGETS}

      # execute 'make install' without DESTDIR
      COMMAND cd "${DISTCHECK_BUILDDIR}"  && ${CMAKE_MAKE_PROGRAM} ${DISTCHECK_INSTALLTARGETS} DESTDIR=
      # write protect installation path to detect writing outside of DESTDIR
      COMMAND chmod -R a-w "${DISTCHECK_TMPDIR}/install"
      # execute 'make install' with DESTDIR and move the files to a better location
      COMMAND cd "${DISTCHECK_BUILDDIR}"  && ${CMAKE_MAKE_PROGRAM} ${DISTCHECK_INSTALLTARGETS} DESTDIR="${DISTCHECK_TMPDIR}/install-tmp"
      COMMAND mv "${DISTCHECK_TMPDIR}/install-tmp/${DISTCHECK_TMPDIR}/install" "${DISTCHECK_TMPDIR}/install-destdir"

      # generate list of files which were installed by the both 'make
      # install' commands above and compare them
      COMMAND cd "${DISTCHECK_TMPDIR}/install"         && find -type f | sort > ../files.install
      COMMAND cd "${DISTCHECK_TMPDIR}/install-destdir" && find -type f | sort > ../files.destdir
      COMMAND cd "${DISTCHECK_TMPDIR}" && diff files.install files.destdir

      # cleanup tmpdir
      COMMAND chmod -R u+Xw "${DISTCHECK_TMPDIR}" 2>/dev/null || :
      COMMAND rm -rf "${DISTCHECK_TMPDIR}"
      )
endmacro(add_distcheck)