Initial commit; standardizing these scripts from various projects

This commit is contained in:
S David 2024-05-16 18:56:21 -04:00
commit c0c014487f
6 changed files with 299 additions and 0 deletions

52
BuildOptions.cmake Normal file
View File

@ -0,0 +1,52 @@
function(use_ccache)
option(USE_CCACHE
"Use ccache compiler cache to speed up builds.\nEnabled by default if ccache is found"
ON
)
if (USE_CCACHE)
message(CHECK_START "Detecting cacche")
find_program(CCACHE_PATH ccache)
if(CCACHE_PATH)
message(CHECK_PASS("found"))
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
endif()
list(APPEND CMAKE_MESSAGE_INDENT " ")
message(STATUS "(set -DUSE_CCACHE=Off to disable)")
list(POP_BACK CMAKE_MESSAGE_INDENT)
endif()
endfunction()
function(check_and_set_linker)
option(USE_MOLD "Use the mold/sold parallel linker for faster builds" ON)
if(USE_MOLD)
# Determine if the compiler is GCC or Clang
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
message(STATUS "Detected GCC/Clang, checking for mold/sold linker...")
# Check for mold linker on general systems and ld64.mold on macOS
if(APPLE)
find_program(MOLD_LINKER ld64.mold)
set(CMAKE_LINKER_TYPE SOLD)
else()
find_program(MOLD_LINKER mold)
set(CMAKE_LINKER_TYPE MOLD)
endif()
if(MOLD_LINKER)
message(STATUS "LINKER_TYPE set to ${CMAKE_LINKER_TYPE} for faster builds")
list(APPEND CMAKE_MESSAGE_INDENT " ")
message(STATUS "(set -DUSE_MOLD=OFF to disable)")
list(POP_BACK CMAKE_MESSAGE_INDENT)
else()
message(STATUS " -- No suitable mold linker found. Using default linker.")
endif()
else()
message(STATUS "Compiler is neither GCC nor Clang. Skipping mold linker check.")
endif()
endif()
endfunction()

102
BuildProperties.cmake Normal file
View File

@ -0,0 +1,102 @@
# BuildPreferences.cmake
# Copyright (c) 2024 Saul D Beniquez
# License: MIT
#
# This module defines a function prevent_in_source_build() that prevents in-source builds
# and sets a policy for CMake version 3.24.0 and above.
function(prevent_in_source_build)
# Prevent in-source builds
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Source and build directories cannot be the same.")
endif()
endfunction()
function(disable_deprecated_features)
# Use new timestamp behavior when extracting files archives
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
endfunction()
function(set_artifact_dir path)
# Set local variable, not necessary to be parent scope since it's not used outside this function
set(ARTIFACT_DIR "${path}")
# Set project-specific artifact directory in parent scope
set(${PROJECT_NAME}_ARTIFACT_DIR "${path}" PARENT_SCOPE)
set(${PROJECT_NAME}_INCLUDE_OUTPUT_DIR "${path}/include" PARENT_SCOPE)
# Set output directories in parent scope using the provided path directly
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${path}/lib" PARENT_SCOPE)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${path}/lib" PARENT_SCOPE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${path}/bin" PARENT_SCOPE)
endfunction()
function(package_library_headers LibraryTarget)
if (NOT DEFINED ${PROJECT_NAME}_INCLUDE_OUTPUT_DIR)
message(FATAL_ERROR "Before calling package_library_headers, set the artifact directory using set_artifact_dir()")
endif()
# Create the custom target name
set(target_name "${LibraryTarget}_copy_include_directory")
set(output_dir "${${PROJECT_NAME}_INCLUDE_OUTPUT_DIR}")
# Create a list to hold custom commands
set(custom_commands
COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir}/${LibraryTarget} )
set(is_glob false)
# Iterate over each argument to copy them
foreach(item IN LISTS ARGN)
if (IS_DIRECTORY ${item})
get_filename_component(item_name ${item} NAME)
list(APPEND custom_commands
COMMAND ${CMAKE_COMMAND} -E copy_directory ${item} ${output_dir}/${LibraryTarget}/${item_name}
)
else()
if (${is_glob})
file(GLOB glob_files ${item})
list(APPEND expanded_items ${glob_files})
message(STATUS "glob_files" ${glob_files})
set(is_glob false)
foreach(expanded IN LISTS expanded_items)
get_filename_component(item_name ${expanded} NAME)
list(APPEND custom_commands
COMMAND ${CMAKE_COMMAND} -E copy ${expanded} ${output_dir}/${LibraryTarget}/${item_name}
)
endforeach()
elseif (item STREQUAL "GLOB")
set(is_glob true)
else()
get_filename_component(item_name ${item} NAME)
list(APPEND custom_commands
COMMAND ${CMAKE_COMMAND} -E copy ${item} ${output_dir}/${LibraryTarget}/${item_name}
)
endif()
endif()
endforeach()
# Create the target to copy directories and files
add_custom_target(${target_name} ALL
${custom_commands}
COMMENT "Copying files and directories to ${output_dir}/include/${LibraryTarget}/"
)
# Add the custom target as a dependency of the library target
add_dependencies(${LibraryTarget} ${target_name})
endfunction()
function(disable_tests_if_subproject)
option(BUILD_TESTING "Build unit tests" ON)
if (DEFINED PROJECT_NAME)
set(BUILD_TESTING OFF PARENT_SCOPE)
endif()
endfunction()
# vim: ts=4 sts=4 sw=4 noet foldmethod=indent :

24
CPM.cmake Normal file
View File

@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.38.7)
set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)
include(${CPM_DOWNLOAD_LOCATION})

25
LICENSE Normal file
View File

@ -0,0 +1,25 @@
The .cmake files in this directory are intended to be included in other CMake build scripts.
They are free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

59
README.md Normal file
View File

@ -0,0 +1,59 @@
# CmakeTools
[![License](https://img.shields.io/badge/License-Unlicense-lightgrey.svg)](https://unlicense.org/)
[![CMake](https://img.shields.io/badge/CMake-3.26.0-blue.svg)](https://cmake.org/)
## Overview
This repository contains CMake scripts I use in my projects to
manage build options, preferences, properties, and utilities for a CMake-based project.
The main scripts included are:
- `BuildOptions.cmake`
- `BuildPreferences.cmake`
- `Util.cmake`
Additional third-party scripts included are:
- [![GitHub](https://img.shields.io/badge/GitHub-CPM.cmake-yellow.svg)](https://github.com/cpm-cmake/CPM.cmake) ![MIT](https://img.shields.io/badge/License-MIT-red.svg)
## Getting Started
### Prerequisites
- CMake 3.26.0 or above. Might work with lesser verisons, but not tested.
### Setup
1. Create a project repository and a directory to contain these scripts. (e.g `CMake`)
2. ```sh
$ git submodule add ${REPO_URL} CMake # You can use any directory name you wish
```
### Usage
1. Create your `CMakeLists.txt`
2. Add this at the top:
```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.26)
include(CMake/Util)
git_setup_submodules()
include(CMake/BuildPreferences)
iunclude(Cmake/BuildOptions)
prevent_in_source_build()
disable_deprecated_features()
## or
# include(CMake/DefaultConfig)
project(MyProject)
```
### License
The .cmake scripts in this repository are disstributed under the Unlicense - see the [LICENSE](LICENSE) file for details.
The included CPM.cmake module is © Lars Melchior and contributors, and is distributed under the MIT License - see the [LICENSE](https://github.com/cpm-cmake/CPM.cmake/blob/33bdbae902df5365ad545a7d082949883bd8d99d/LICENSE) file for details.

37
Util.cmake Normal file
View File

@ -0,0 +1,37 @@
macro(ASSERT condition message)
if(NOT ${condition})
message(FATAL_ERROR ${message})
endif()
endmacro()
macro(git_setup_submodules)
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
option(GIT_SUBMODULE "Check submodules during build" ON)
if(GIT_SUBMODULE)
message(STATUS "Git submodule update")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
endif()
endif()
else()
message(FATAL_ERROR "Git not found or .git directory not found")
endif()
endmacro()
macro(prevent_in_source_build)
# Prevent in-source builds
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Source and build directories cannot be the same.")
endif()
endmacro()
macro(disable_deprecated_features)
# Use new timestamp behavior when extracting files archives
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
endmacro()