|
| 1 | +# Copyright (c) 2016 Thilo Schuchort |
| 2 | +# |
| 3 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 4 | +# of this software and associated documentation files (the "Software"), to deal |
| 5 | +# in the Software without restriction, including without limitation the rights |
| 6 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 7 | +# copies of the Software, and to permit persons to whom the Software is |
| 8 | +# furnished to do so, subject to the following conditions: |
| 9 | +# |
| 10 | +# The above copyright notice and this permission notice shall be included in |
| 11 | +# all copies or substantial portions of the Software. |
| 12 | +# |
| 13 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 14 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 15 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 16 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 17 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 18 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 19 | +# THE SOFTWARE. |
| 20 | + |
| 21 | +cmake_minimum_required(VERSION 2.8.8) |
| 22 | + |
| 23 | +include(${PROJECT_SOURCE_DIR}/cmake/Utils.cmake) |
| 24 | +include(CMakeParseArguments) |
| 25 | + |
| 26 | +find_package(Git) |
| 27 | +if(NOT GIT_FOUND) |
| 28 | + message(FATAL_ERROR "git not found!") |
| 29 | +endif() |
| 30 | + |
| 31 | + |
| 32 | +# clone a git repo into a directory at configure time |
| 33 | +# this can be useful for including cmake-library projects that contain *.cmake files |
| 34 | +# the function will automatically init git submodules too |
| 35 | +# |
| 36 | +# ATTENTION: CMakeLists-files in the cloned repo will NOT be build automatically |
| 37 | +# |
| 38 | +# why not use ExternalProject_Add you ask? because we need to run this at configure time |
| 39 | +# |
| 40 | +# USAGE: |
| 41 | +# git_clone( |
| 42 | +# PROJECT_NAME <project name> |
| 43 | +# GIT_URL <url> |
| 44 | +# [GIT_TAG|GIT_BRANCH|GIT_COMMIT <symbol>] |
| 45 | +# [DIRECTORY <dir>] |
| 46 | +# [QUIET] |
| 47 | +# ) |
| 48 | +# |
| 49 | +# |
| 50 | +# ARGUMENTS: |
| 51 | +# PROJECT_NAME |
| 52 | +# name of the project that will be used in output variables. |
| 53 | +# must be the same as the git directory/repo name |
| 54 | +# |
| 55 | +# GIT_URL |
| 56 | +# url to the git repo |
| 57 | +# |
| 58 | +# GIT_TAG|GIT_BRANCH|GIT_COMMIT |
| 59 | +# optional |
| 60 | +# the tag/branch/commit to checkout |
| 61 | +# default is master |
| 62 | +# |
| 63 | +# DIRECTORY |
| 64 | +# optional |
| 65 | +# the directory the project will be cloned into |
| 66 | +# default is the build directory, similar to ExternalProject (${CMAKE_BINARY_DIR}) |
| 67 | +# |
| 68 | +# QUIET |
| 69 | +# optional |
| 70 | +# don't print status messages |
| 71 | +# |
| 72 | +# |
| 73 | +# OUTPUT VARIABLES: |
| 74 | +# <project name>_SOURCE_DIR |
| 75 | +# top level source directory of the cloned project |
| 76 | +# |
| 77 | +# |
| 78 | +# EXAMPLE: |
| 79 | +# git_clone( |
| 80 | +# PROJECT_NAME testProj |
| 81 | +# GIT_URL https://github.com/test/test.git |
| 82 | +# GIT_COMMIT a1b2c3 |
| 83 | +# DIRECTORY ${CMAKE_BINARY_DIR} |
| 84 | +# QUIET |
| 85 | +# ) |
| 86 | +# |
| 87 | +# include(${testProj_SOURCE_DIR}/cmake/myFancyLib.cmake) |
| 88 | + |
| 89 | +function(git_clone) |
| 90 | + |
| 91 | + cmake_parse_arguments( |
| 92 | + PARGS # prefix of output variables |
| 93 | + "QUIET" # list of names of the boolean arguments (only defined ones will be true) |
| 94 | + "PROJECT_NAME;GIT_URL;GIT_TAG;GIT_BRANCH;GIT_COMMIT;DIRECTORY" # list of names of mono-valued arguments |
| 95 | + "" # list of names of multi-valued arguments (output variables are lists) |
| 96 | + ${ARGN} # arguments of the function to parse, here we take the all original ones |
| 97 | + ) # remaining unparsed arguments can be found in PARGS_UNPARSED_ARGUMENTS |
| 98 | + |
| 99 | + if(NOT PARGS_PROJECT_NAME) |
| 100 | + message(FATAL_ERROR "You must provide a project name") |
| 101 | + endif() |
| 102 | + |
| 103 | + if(NOT PARGS_GIT_URL) |
| 104 | + message(FATAL_ERROR "You must provide a git url") |
| 105 | + endif() |
| 106 | + |
| 107 | + if(NOT PARGS_DIRECTORY) |
| 108 | + set(PARGS_DIRECTORY ${CMAKE_BINARY_DIR}) |
| 109 | + endif() |
| 110 | + |
| 111 | + set(${PARGS_PROJECT_NAME}_SOURCE_DIR |
| 112 | + ${PARGS_DIRECTORY}/${PARGS_PROJECT_NAME} |
| 113 | + CACHE INTERNAL "" FORCE) # makes var visible everywhere because PARENT_SCOPE wouldn't include this scope |
| 114 | + |
| 115 | + set(SOURCE_DIR ${PARGS_PROJECT_NAME}_SOURCE_DIR) |
| 116 | + |
| 117 | + # check that only one of GIT_TAG xor GIT_BRANCH xor GIT_COMMIT was passed |
| 118 | + at_most_one(at_most_one_tag ${PARGS_GIT_TAG} ${PARGS_GIT_BRANCH} ${PARGS_GIT_COMMIT}) |
| 119 | + |
| 120 | + if(NOT at_most_one_tag) |
| 121 | + message(FATAL_ERROR "you can only provide one of GIT_TAG, GIT_BRANCH or GIT_COMMIT") |
| 122 | + endif() |
| 123 | + |
| 124 | + if(NOT PARGS_QUIET) |
| 125 | + message(STATUS "downloading/updating ${PARGS_PROJECT_NAME}") |
| 126 | + endif() |
| 127 | + |
| 128 | + # first clone the repo |
| 129 | + if(EXISTS ${${SOURCE_DIR}}) |
| 130 | + if(NOT PARGS_QUIET) |
| 131 | + message(STATUS "${PARGS_PROJECT_NAME} directory found, pulling...") |
| 132 | + endif() |
| 133 | + |
| 134 | + execute_process( |
| 135 | + COMMAND ${GIT_EXECUTABLE} pull origin master |
| 136 | + COMMAND ${GIT_EXECUTABLE} submodule update --remote |
| 137 | + WORKING_DIRECTORY ${${SOURCE_DIR}} |
| 138 | + OUTPUT_VARIABLE git_output) |
| 139 | + else() |
| 140 | + if(NOT PARGS_QUIET) |
| 141 | + message(STATUS "${PARGS_PROJECT_NAME} directory not found, cloning...") |
| 142 | + endif() |
| 143 | + |
| 144 | + execute_process( |
| 145 | + COMMAND ${GIT_EXECUTABLE} clone ${PARGS_GIT_URL} --recursive |
| 146 | + WORKING_DIRECTORY ${PARGS_DIRECTORY} |
| 147 | + OUTPUT_VARIABLE git_output) |
| 148 | + endif() |
| 149 | + |
| 150 | + if(NOT PARGS_QUIET) |
| 151 | + message("${git_output}") |
| 152 | + endif() |
| 153 | + |
| 154 | + # now checkout the right commit |
| 155 | + if(PARGS_GIT_TAG) |
| 156 | + execute_process( |
| 157 | + COMMAND ${GIT_EXECUTABLE} fetch --all --tags --prune |
| 158 | + COMMAND ${GIT_EXECUTABLE} checkout tags/${PARGS_GIT_TAG} -b tag_${PARGS_GIT_TAG} |
| 159 | + WORKING_DIRECTORY ${${SOURCE_DIR}} |
| 160 | + OUTPUT_VARIABLE git_output) |
| 161 | + elseif(PARGS_GIT_BRANCH OR PARGS_GIT_COMMIT) |
| 162 | + execute_process( |
| 163 | + COMMAND ${GIT_EXECUTABLE} checkout ${PARGS_GIT_BRANCH} |
| 164 | + WORKING_DIRECTORY ${${SOURCE_DIR}} |
| 165 | + OUTPUT_VARIABLE git_output) |
| 166 | + else() |
| 167 | + message(STATUS "no tag specified, defaulting to master") |
| 168 | + execute_process( |
| 169 | + COMMAND ${GIT_EXECUTABLE} checkout master |
| 170 | + WORKING_DIRECTORY ${${SOURCE_DIR}} |
| 171 | + OUTPUT_VARIABLE git_output) |
| 172 | + endif() |
| 173 | + |
| 174 | + if(NOT PARGS_QUIET) |
| 175 | + message("${git_output}") |
| 176 | + endif() |
| 177 | +endfunction() |
0 commit comments