Skip to content

Commit

Permalink
Add dependency helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Cliff Foster committed Feb 28, 2024
1 parent 25ba332 commit a60137d
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 13 deletions.
8 changes: 1 addition & 7 deletions cmake/idi/functions/framework/idi_init.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,7 @@ macro(idi_init)
# Define a nice short hand for 3rd party external library folders
set(IDICMAKE_EXTERNAL_LIB_DIR "${CMAKE_CURRENT_LIST_DIR}/lib")

FetchContent_Declare(Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.5.2
EXCLUDE_FROM_ALL
SYSTEM
)
FetchContent_MakeAvailable(Catch2)
idi_add_third_party_dependency(Catch2 https://github.com/catchorg/Catch2.git v3.5.2)

# Add the main source folder.
idi_cmake_hook(pre-source)
Expand Down
193 changes: 193 additions & 0 deletions cmake/idi/functions/idi_add_dependency.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#
# @author Cliff Foster (Nou) <cliff@idi-systems.com>
#
# @copyright Copyright (c) 2024 International Development & Integration Systems LLC
#
# Licensed under a modified MIT License, see TEMPLATE_LICENSE for full license details
#

# cpm_parse_option is provided from the CPM library under an MIT license
#
# CPM.cmake - CMake's missing package manager
# ===========================================
# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.
#
# MIT License

# splits a package option
function(cpm_parse_option OPTION)
string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}")
string(LENGTH "${OPTION}" OPTION_LENGTH)
string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH)
if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH)
# no value for key provided, assume user wants to set option to "ON"
set(OPTION_VALUE "ON")
else()
math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1")
string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE)
endif()
set(OPTION_KEY
"${OPTION_KEY}"
PARENT_SCOPE
)
set(OPTION_VALUE
"${OPTION_VALUE}"
PARENT_SCOPE
)
endfunction()

function(idi_get_repo_information REPO_DIR)
find_package(Git)
if(NOT Git_FOUND)
message(FATAL_ERROR "Git could not be found!")
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} "status" "--porcelain" WORKING_DIRECTORY ${REPO_DIR} OUTPUT_VARIABLE IDI_TEST_REPO_PORCELAIN)
if("${IDI_TEST_REPO_PORCELAIN}" STREQUAL "")
set(IDI_REPO_IS_PORCELAIN
true
PARENT_SCOPE
)
else()
set(IDI_REPO_IS_PORCELAIN
false
PARENT_SCOPE
)
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} "tag" "--points-at" "HEAD" WORKING_DIRECTORY ${REPO_DIR} OUTPUT_VARIABLE IDI_GET_REPO_TAG)
string(STRIP "${IDI_GET_REPO_TAG}" IDI_GET_REPO_TAG)
set(IDI_REPO_TAG
"${IDI_GET_REPO_TAG}"
PARENT_SCOPE
)
execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "HEAD" WORKING_DIRECTORY ${REPO_DIR} OUTPUT_VARIABLE IDI_GET_REPO_SHA1)
string(STRIP "${IDI_GET_REPO_SHA1}" IDI_GET_REPO_SHA1)
set(IDI_REPO_SHA1
"${IDI_GET_REPO_SHA1}"
PARENT_SCOPE
)
execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "--abbrev-ref" "HEAD" WORKING_DIRECTORY ${REPO_DIR} OUTPUT_VARIABLE IDI_GET_REPO_BRANCH)
string(STRIP "${IDI_GET_REPO_BRANCH}" IDI_GET_REPO_BRANCH)
set(IDI_REPO_BRANCH
"${IDI_GET_REPO_BRANCH}"
PARENT_SCOPE
)
endfunction()

function(__idi_add_dependency IDI_DEP_NAME IDI_DEP_URL IDI_DEP_TAG IDI_DEP_THIRD_PARTY)
set(multiValueArgs DEP_OPTIONS)
cmake_parse_arguments(IDI "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN} )

string(TOLOWER ${IDI_DEP_NAME} IDI_DEP_NAME_LOWER)

if(TARGET ${IDI_DEP_NAME})
message(STATUS "${IDI_DEP_NAME} already added, skipping.")
return()
endif()

set(IDI_DO_POPULATE false)

if(IDI_DEP_THIRD_PARTY)
set(IDI_DEP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/lib/.third-party/${IDI_DEP_NAME}")
set(IDI_DEP_BINARY_DIR "${CMAKE_BINARY_DIR}/_deps/${IDI_DEP_NAME_LOWER}")
if(EXISTS ${IDI_DEP_SOURCE_DIR} AND EXISTS "${IDI_DEP_SOURCE_DIR}/.git")

idi_get_repo_information(${IDI_DEP_SOURCE_DIR})

message("${IDI_DEP_NAME} IDI_REPO_IS_PORCELAIN: ${IDI_REPO_IS_PORCELAIN}")
message("${IDI_DEP_NAME} IDI_REPO_TAG: ${IDI_REPO_TAG}")
message("${IDI_DEP_NAME} IDI_REPO_SHA1: ${IDI_REPO_SHA1}")
message("${IDI_DEP_NAME} IDI_REPO_BRANCH: ${IDI_REPO_BRANCH}")

if(NOT IDI_REPO_IS_PORCELAIN)
message(WARNING "Third-party dependency '${IDI_DEP_NAME}' has uncomitted or untracked files.")
endif()

if (
(NOT ("${IDI_REPO_TAG}" STREQUAL "${IDI_DEP_TAG}")) AND
(NOT ("${IDI_REPO_SHA1}" STREQUAL "${IDI_DEP_TAG}")) AND
(NOT ("${IDI_REPO_BRANCH}" STREQUAL "${IDI_DEP_TAG}"))
)
set(IDI_DO_POPULATE true)
endif()

else()
set(IDI_DO_POPULATE true)
endif()
else()
set(IDI_DEP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/lib/${IDI_DEP_NAME}")
set(IDI_DEP_BINARY_DIR "${CMAKE_BINARY_DIR}/_deps/${IDI_DEP_NAME_LOWER}")
if(EXISTS ${IDI_DEP_SOURCE_DIR} AND EXISTS "${IDI_DEP_SOURCE_DIR}/.git")

idi_get_repo_information(${IDI_DEP_SOURCE_DIR})

message("${IDI_DEP_NAME} IDI_REPO_IS_PORCELAIN: ${IDI_REPO_IS_PORCELAIN}")
message("${IDI_DEP_NAME} IDI_REPO_TAG: ${IDI_REPO_TAG}")
message("${IDI_DEP_NAME} IDI_REPO_SHA1: ${IDI_REPO_SHA1}")
message("${IDI_DEP_NAME} IDI_REPO_BRANCH: ${IDI_REPO_BRANCH}")


if(NOT IDI_REPO_IS_PORCELAIN)
message(WARNING "First-party dependency '${IDI_DEP_NAME}' has uncomitted or untracked files.")
endif()

set(IDI_REPO_SAME_COMMIT true)

if (
(NOT ("${IDI_REPO_TAG}" STREQUAL "${IDI_DEP_TAG}")) AND
(NOT ("${IDI_REPO_SHA1}" STREQUAL "${IDI_DEP_TAG}")) AND
(NOT ("${IDI_REPO_BRANCH}" STREQUAL "${IDI_DEP_TAG}"))
)
message(WARNING "First-party dependency '${IDI_DEP_NAME}' is not on the same commit as defined by configuration. ${IDI_DEP_TAG} != ${IDI_REPO_TAG}|${IDI_REPO_SHA1}|${IDI_REPO_BRANCH}")
set(IDI_REPO_SAME_COMMIT false)
endif()

if(IDI_SYNC_DEPENDENCIES)
if(NOT IDI_REPO_IS_PORCELAIN)
message(FATAL_ERROR "Attempted to sync dependencies but first-party dependency '${IDI_DEP_NAME}' has uncomitted or untracked files, commit or stash changes and try again.")
else()
set(IDI_DO_POPULATE true)
endif()
endif()

else()
set(IDI_DO_POPULATE true)
endif()
endif()

if(${IDI_DO_POPULATE})
message(STATUS "Adding dependency '${IDI_DEP_NAME}' from ${IDI_DEP_URL} at tag ${IDI_DEP_TAG}")
FetchContent_Declare(
${IDI_DEP_NAME}
GIT_REPOSITORY ${IDI_DEP_URL}
GIT_TAG ${IDI_DEP_TAG}
SOURCE_DIR ${IDI_DEP_SOURCE_DIR}
EXCLUDE_FROM_ALL
SYSTEM
)

if(${${IDI_DEP_NAME_LOWER}_POPULATED})
message(STATUS "${IDI_DEP_NAME} already populated, skipping.")
return()
endif()

FetchContent_Populate(${IDI_DEP_NAME})
else()
message(STATUS "${IDI_DEP_NAME} already exists, skipping download.")
endif()

foreach(OPTION ${IDI_DEP_OPTIONS})
cpm_parse_option("${OPTION}")
set(${OPTION_KEY} "${OPTION_VALUE}")
endforeach()
add_subdirectory(${IDI_DEP_SOURCE_DIR} ${IDI_DEP_BINARY_DIR} EXCLUDE_FROM_ALL SYSTEM)
message(STATUS "Added dependency ${IDI_DEP_NAME}")
endfunction()

function(idi_add_third_party_dependency IDI_DEP_NAME IDI_DEP_URL IDI_DEP_TAG)
__idi_add_dependency(${IDI_DEP_NAME} ${IDI_DEP_URL} ${IDI_DEP_TAG} true ${ARGN})
endfunction()

function(idi_add_first_party_dependency IDI_DEP_NAME IDI_DEP_URL IDI_DEP_TAG)
__idi_add_dependency(${IDI_DEP_NAME} ${IDI_DEP_URL} ${IDI_DEP_TAG} false ${ARGN})
endfunction()
1 change: 1 addition & 0 deletions cmake/idi/idi-template.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ if(NOT IDICMAKE_DID_UPDATE)
"If you updated the template recently, also update the CMakeList.txt in the src/base component directory")
endif()

include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/idi/functions/idi_add_dependency.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/idi/functions/idi_add_sources.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/idi/functions/idi_add_subdirectory.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/idi/functions/idi_component_test.cmake)
Expand Down
1 change: 1 addition & 0 deletions cmake/idi/updater/updater_imp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ endif()
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/src/base/include/template_project" "${CMAKE_CURRENT_SOURCE_DIR}/src/base/include/${IDICMAKE_PROJECT_NAME}")
do_replace_file("CMakeLists.txt")
do_replace_file("src/CMakeLists.txt")
do_replace_file("lib/.gitignore")
6 changes: 1 addition & 5 deletions cmake/idi/updater/updater_version.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
# Licensed under a modified MIT License, see TEMPLATE_LICENSE for full license details
#
# This is the _framework_ **updater** version number, and is NOT related to the underlying project.
#
# If the local updater is older than the update's updater it will require the user to re-run the updater
# with a specific flag that allows for and consents to "remote code" execution.
#

# Any time the updater is changed this version should be incremented!!!
set(IDICMAKE_CPP_UPDATER_VERSION 2)
set(IDICMAKE_CPP_UPDATER_VERSION 3)
5 changes: 5 additions & 0 deletions lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Do not edit this file, it can/will be replaced by template updates.
*
!libraries.cmake
!README.mod
!.gitignore
3 changes: 2 additions & 1 deletion lib/libraries.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Include libraries here.
# Catch2 is included by deault, no need to re-add it here.

# add_subdirectory(${IDI_EXTERNAL_LIB_DIR}/lib_folder)
# idi_add_third_party_dependency(Catch2 https://github.com/catchorg/Catch2.git v3.5.2)

0 comments on commit a60137d

Please sign in to comment.