diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100644 index 0000000..90d21f6 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,11 @@ +#!/bin/bash + +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +set -eo pipefail + +# Configure and run the tests +cmake -B tests/.build-githook -S tests --log-level=NOTICE diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..f8a9e89 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,38 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +name: Release +permissions: + contents: write + +on: + release: + types: [published] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Configure & run examples + run: cmake -B build + + - name: Package source code + run: cmake --build build --target package + + - name: Add packaged source code to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: build/ic_cmake.zip + tag: ${{ github.ref }} + + - name: Add fetch_test_cmake.cmake to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: fetch_ic_cmake.cmake + tag: ${{ github.ref }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..9db3c86 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +name: Test + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Configure & run tests + run: cmake -B tests/build -S tests --log-level=NOTICE diff --git a/CMakeLists.txt b/CMakeLists.txt index 6818cfb..6a4691f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,4 @@ -cmake_minimum_required(VERSION 3.20.0) - -include(intercreate.cmake) - -project(project_name) - -intercreate_project( - CLIENT_NAME "client name!" - HW_VERSION FF1 - GIT_TAG 0.1.0 - GIT_HASH abcdef - BUILD_DATE 2020-20-10 - BUILD_TYPE debug - ARTIFACT_PREFIX prefix - RELEASE_DEPENDS zephyr -) \ No newline at end of file +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..43090e6 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Intercreate CMake + +# Tests + +``` +cmake -B tests/build -S tests --log-level=NOTICE +``` + +# Contributions + +* Fork this repository: https://github.com/intercreate/ic-cmake/fork +* Clone your fork: `git clone git@github.com:/ic-cmake.git` + * then change directory to your cloned fork: `cd ic-cmake` +* Enable the githook: `git config core.hooksPath .githooks` diff --git a/fetch_ic.cmake b/fetch_ic.cmake new file mode 100644 index 0000000..e46d867 --- /dev/null +++ b/fetch_ic.cmake @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +include_guard(GLOBAL) + +include(FetchContent) + +FetchContent_Declare(ic_cmake + URL https://github.com/intercreate/test-cmake/releases/latest/download/ic.zip + DOWNLOAD_EXTRACT_TIMESTAMP true +) +FetchContent_MakeAvailable(ic_cmake) + +include(${CMAKE_BINARY_DIR}/_deps/ic_cmake-src/ic.cmake) diff --git a/ic.cmake b/ic.cmake new file mode 100644 index 0000000..2e58479 --- /dev/null +++ b/ic.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/src/ic_project.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/src/ic_utils.cmake) diff --git a/intercreate.cmake b/intercreate.cmake deleted file mode 100644 index 071dfdf..0000000 --- a/intercreate.cmake +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2023 Intercreate, Inc. - -# Sets the following CMake variables -# FW_VERSION -# GIT_TAG -# GIT_TAG_REV (this is the -1, -2, -3, that counts commits after tag) -# GIT_HASH -# BUILD_DATE (YYYYMMDD) - -# And adds the following compile definitions -# FW_VERSION -# GIT_TAG -# GIT_TAG_REV (this is the -1, -2, -3, that counts commits after tag) -# GIT_HASH -# BUILD_DATE (YYYYMMDD) - -# Set firmware version -execute_process( - COMMAND git describe --dirty=+ --always --abbrev=7 - OUTPUT_VARIABLE FW_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) -add_compile_definitions(FW_VERSION="${FW_VERSION}") -message(STATUS "Firmware version is ${FW_VERSION}") - -# Get the GIT tag and tag revision from the FW_VERSION -string(REPLACE "-" ";" _FW_VERSION_LIST ${FW_VERSION}) -list(GET _FW_VERSION_LIST 0 GIT_TAG) -list(LENGTH _FW_VERSION_LIST _LEN) -if (_LEN EQUAL 3) - list(GET _FW_VERSION_LIST 1 GIT_TAG_REV) - set(GIT_TAG_REV "-${GIT_TAG_REV}") -else() - set(GIT_TAG_REV "") -endif() - -# Set short git commit hash -execute_process( - COMMAND git describe --dirty=+ --always --abbrev=7 --exclude * - OUTPUT_VARIABLE GIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -add_compile_definitions( - GIT_TAG="${GIT_TAG}" - GIT_TAG_REV="${GIT_TAG_REV}" - GIT_HASH="${GIT_HASH}" -) -message(STATUS "GIT tag is ${GIT_TAG}") -message(STATUS "GIT tag revision is ${GIT_TAG_REV}") -message(STATUS "Short git hash is ${GIT_HASH}") - -# Set build date -string(TIMESTAMP BUILD_DATE "%Y%m%d") -add_compile_definitions(BUILD_DATE="${BUILD_DATE}") -message(STATUS "Today is ${BUILD_DATE}") - - -macro(_set_default_arg) - if(NOT DEFINED "_${ARGV1}") - set("_${ARGV1}" "${ARGV2}") - endif() -endmacro() - -# Create well-named build output files, folder, and archives -function(intercreate_project) - set(_REQUIRED_KEYWORD_ARGS - CLIENT_NAME - HW_VERSION - ) - set(_OPTIONAL_KEYWORD_ARGS - PROJECT_NAME - GIT_TAG_REV - BUILD_TYPE - ARTIFACT_PREFIX - DEPENDS_TARGET - EXTRA_FILES - ) - list(APPEND _KEYWORD_ARGS - ${_REQUIRED_KEYWORD_ARGS} - ${_OPTIONAL_KEYWORD_ARGS} - ) - cmake_parse_arguments("" "" "${_KEYWORD_ARGS}" "" ${ARGN}) - - _set_default_arg(_PROJECT_NAME ${CMAKE_PROJECT_NAME}) - _set_default_arg(_GIT_TAG_REV "") - _set_default_arg(_BUILD_TYPE ${CMAKE_BUILD_TYPE}) - _set_default_arg(_ARTIFACT_PREFIX "") - _set_default_arg(_DEPENDS_TARGET ${CMAKE_PROJECT_NAME}) - _set_default_arg(_EXTRA_FILES "") - - foreach(KEY ${_REQUIRED_KEYWORD_ARGS}) - if(NOT DEFINED "_${KEY}") - message(FATAL_ERROR "Missing keyword argument ${KEY} in call to ${CMAKE_CURRENT_FUNCTION}()") - endif() - endforeach() - - set(_cmd "COMMAND ${CMAKE_COMMAND} -E") - - add_custom_target(intercreate_names ALL - _cmd remove_directory intercreate_output - _cmd make_directory intercreate_output - - ) - - -endfunction() \ No newline at end of file diff --git a/src/ic_project.cmake b/src/ic_project.cmake new file mode 100644 index 0000000..3dad932 --- /dev/null +++ b/src/ic_project.cmake @@ -0,0 +1,242 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/ic_utils.cmake) + +#[[ +Create the project(), set() CMake variables, and add_compile_definitions() with project metadata. + + : output variable list (see ic_project_out) +CLIENT_NAME : the client name for the project +PROJECT_NAME : the name of the project; calls project() +BOARD_NAME : the name of the board (hardware revision) +[BOARD_REV ] : the board revision +[BUILD_TYPE ] : a build type modifier, e.g. release, debug, factory, etc. + will default to ${CMAKE_BUILD_TYPE} but it does not set CMAKE_BUILD_TYPE + +Usage: + ic_project_out(ic_out) # using the default names + ic_project( + # output variables + ${ic_out} + + # keyword arguments + CLIENT_NAME "Flumbr" + PROJECT_NAME "Dipple Snurp 3" + BOARD_NAME FF3 + BUILD_TYPE debug + ) +]]# +function(ic_project + # output variables + out_client_name + out_project_name + out_board_name + out_board_rev # depends on BOARD_REV + out_fw_version + out_build_type # depends on BUILD_TYPE + out_git_dirty + out_git_tag + out_git_tag_rev # maybe "" + out_git_hash + out_git_user_name + out_git_user_email + out_build_date + out_build_time + out_c_compiler_id + out_c_compiler + out_c_compiler_version + out_host_system_name + out_host_system_version + out_config_string +) + set(required_keyword_args + CLIENT_NAME + PROJECT_NAME + BOARD_NAME + ) + set(optional_keyword_args + BOARD_REV + BUILD_TYPE + ) + list(APPEND keyword_args + ${required_keyword_args} + ${optional_keyword_args} + ) + cmake_parse_arguments(PARSE_ARGV 20 "" "" "${keyword_args}" "") + + if(_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unparsed arguments: ${_UNPARSED_ARGUMENTS}") + endif() + + set_default("_BUILD_TYPE" "${CMAKE_BUILD_TYPE}") + + foreach(KEY ${required_keyword_args}) + if(NOT DEFINED "_${KEY}") + message( + FATAL_ERROR + "Missing keyword argument ${KEY} in call to \ + ${CMAKE_CURRENT_FUNCTION}()" + ) + endif() + endforeach() + + set_definition("${out_client_name}" ${_CLIENT_NAME} PARENT_SCOPE) + + project(${_PROJECT_NAME}) + if(NOT ${_PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + message(FATAL_ERROR "${_PROJECT_NAME} != ${CMAKE_PROJECT_NAME}") + endif() + set_definition("${out_project_name}" ${CMAKE_PROJECT_NAME} PARENT_SCOPE) + + set_definition("${out_board_name}" "${_BOARD_NAME}" PARENT_SCOPE) + if_set_definition("${out_board_rev}" "${_BOARD_REV}" PARENT_SCOPE) + + # Warn about git tag + execute_process( + COMMAND git describe + RESULT_VARIABLE res + ERROR_QUIET + OUTPUT_QUIET + ) + if(res AND NOT res EQUAL 0) + message( + WARNING + "The ${git_tag} should be set by git tag but there is no tag" + ) + set(has_git_tag 0) + else() + set(has_git_tag 1) + endif() + + # Set firmware version + execute_process( + COMMAND git describe --dirty=+ --always --abbrev=7 + OUTPUT_VARIABLE git_tag + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set_definition("${out_fw_version}" ${git_tag} PARENT_SCOPE) + + if_set_definition("${out_build_type}" "${_BUILD_TYPE}" PARENT_SCOPE) + + # Set git dirty commit + string(FIND ${git_tag} + res) + if(res EQUAL -1) + set_definition("${out_git_dirty}" 0 PARENT_SCOPE) + else() + set_definition("${out_git_dirty}" 1 PARENT_SCOPE) + endif() + + if(${has_git_tag}) + # Set the git tag + string(REPLACE "-" ";" fw_version_list ${git_tag}) + list(GET fw_version_list 0 git_label) + set_definition("${out_git_tag}" ${git_label} PARENT_SCOPE) + + # Set the git tag revision + list(LENGTH fw_version_list len) + if (len EQUAL 3) + list(GET fw_version_list 1 git_tag_rev) + set_definition("${out_git_tag_rev}" ${git_tag_rev} PARENT_SCOPE) + else() + set_definition("${out_git_tag_rev}" "" PARENT_SCOPE) + endif() + else() + set_definition("${out_git_tag}" "" PARENT_SCOPE) + set_definition("${out_git_tag_rev}" "" PARENT_SCOPE) + endif() + + # Set short git commit hash + execute_process( + COMMAND git describe --dirty=+ --always --abbrev=7 --exclude * + OUTPUT_VARIABLE git_hash + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set_definition("${out_git_hash}" ${git_hash} PARENT_SCOPE) + + string(TIMESTAMP build_date "%Y%m%d") + set_definition("${out_build_date}" ${build_date} PARENT_SCOPE) + string(TIMESTAMP timestamp) + set_definition("${out_build_time}" ${timestamp} PARENT_SCOPE) + + # Set user info + execute_process( + COMMAND git config user.name + OUTPUT_VARIABLE user_name + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set_definition("${out_git_user_name}" ${user_name} PARENT_SCOPE) + execute_process( + COMMAND git config user.email + OUTPUT_VARIABLE user_email + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set_definition("${out_git_user_email}" ${user_email} PARENT_SCOPE) + + # Set build environment info + set_definition("${out_c_compiler_id}" ${CMAKE_C_COMPILER_ID} PARENT_SCOPE) + set_definition("${out_c_compiler}" ${CMAKE_C_COMPILER} PARENT_SCOPE) + set_definition("${out_c_compiler_version}" ${CMAKE_C_COMPILER_VERSION} PARENT_SCOPE) + set_definition("${out_host_system_name}" ${CMAKE_HOST_SYSTEM} PARENT_SCOPE) + set_definition("${out_host_system_version}" ${CMAKE_HOST_SYSTEM_VERSION} PARENT_SCOPE) + + if(NOT "" STREQUAL "${_BOARD_REV}") + set(board_rev_string @${_BOARD_REV}) + endif() + + if(NOT "" STREQUAL "${_BUILD_TYPE}") + set(build_type_string _${_BUILD_TYPE}) + endif() + + # Set the config string for use in naming files, docs, etc. + set( + config_string + ${_CLIENT_NAME}_${CMAKE_PROJECT_NAME}_${_BOARD_NAME}${board_rev_string}_${git_tag}_${build_date}${build_type_string} + ) + string(REPLACE " " "_" config_string ${config_string}) + set_definition("${out_config_string}" ${config_string} PARENT_SCOPE) + +endfunction() + +#[[ +Set the variable `out_variable_name` to the default ic_project() output variable names list. + + : the name of the CMake variable in which to store the default list + +Usage: + ic_project_out(ic_project_out_vars) + ic_project(${ic_project_out_vars} + CLIENT_NAME my_client + PROJECT_NAME my_project + BOARD_NAME my_board + ) +#]] +function(ic_project_out out_variable_name) + set(_IC_OUT_VARIABLES + IC_CLIENT_NAME + IC_PROJECT_NAME + IC_BOARD_NAME + IC_BOARD_REV + IC_FW_VERSION + IC_BUILD_TYPE + IC_GIT_DIRTY + IC_GIT_TAG + IC_GIT_TAG_REV + IC_GIT_HASH + IC_GIT_USER_NAME + IC_GIT_USER_EMAIL + IC_BUILD_DATE + IC_BUILD_TIME + IC_C_COMPILER_ID + IC_C_COMPILER + IC_C_COMPILER_VERSION + IC_HOST_SYSTEM_NAME + IC_HOST_SYSTEM_VERSION + IC_CONFIG_STRING + ) + set(${out_variable_name} ${_IC_OUT_VARIABLES} PARENT_SCOPE) +endfunction() diff --git a/src/ic_utils.cmake b/src/ic_utils.cmake new file mode 100644 index 0000000..b4257bb --- /dev/null +++ b/src/ic_utils.cmake @@ -0,0 +1,60 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +include_guard(GLOBAL) + +#[[ +set() name to value only if name is not defined. + +Use to set default arguments within a function. + + : CMake variable name to set + : the value for the CMake variable +#]] +macro(set_default name value) + if(NOT DEFINED ${name}) + set(${name} ${value}) + endif() +endmacro() + +#[[ +set() the CMake variable and add_compile_definition() + + : CMake variable and compile definition name to set + : the value to set name to +[PARENT_SCOPE] : call set() with PARENT_SCOPE +#]] +macro(set_definition name value) + if(NOT ${ARGC} EQUAL 2 AND NOT ${ARGC} EQUAL 3) + message( + FATAL_ERROR + "Invalid arguments to set_definition( [PARENT_SCOPE]): (${name} ${value} ${ARGN})" + ) + elseif(${ARGC} EQUAL 3 AND NOT ${ARG2} EQUAL PARENT_SCOPE) + message( + FATAL_ERROR + "Invalid arguments to set_definition( [PARENT_SCOPE]): (${name} ${value} ${ARGN})" + ) + elseif(DEFINED name) + message(FATAL_ERROR "${name} is already defined!") + endif() + + set(${name} ${value} ${ARGN}) + add_compile_definitions(${name}=${value}) + message(STATUS "${name} = ${value}") +endmacro() + +#[[ +set_definition() only if value is defined as something other than "" + + : CMake variable and compile definition name to set + : the value to set name to +[PARENT_SCOPE] : call set() with PARENT_SCOPE +#]] +macro(if_set_definition name value) + if(NOT "" STREQUAL "${value}") + set_definition(${name} ${value} ${ARGN}) + endif() +endmacro() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..46a7b51 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +cmake_minimum_required(VERSION 3.20.0) +project(test_ic_project) + +include(${CMAKE_SOURCE_DIR}/../ic.cmake) + +include(fetch_test_cmake.cmake) + +test_cmake_begin() + +include(test_ic_project.cmake) + +test_cmake_end() diff --git a/tests/fetch_test_cmake.cmake b/tests/fetch_test_cmake.cmake new file mode 100644 index 0000000..0adc991 --- /dev/null +++ b/tests/fetch_test_cmake.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +include(FetchContent) + +FetchContent_Declare(test_cmake + URL https://github.com/intercreate/test-cmake/releases/latest/download/test_cmake.zip + DOWNLOAD_EXTRACT_TIMESTAMP true +) +FetchContent_MakeAvailable(test_cmake) + +include(${CMAKE_BINARY_DIR}/_deps/test_cmake-src/test_cmake.cmake) diff --git a/tests/test_ic_project.cmake b/tests/test_ic_project.cmake new file mode 100644 index 0000000..e949826 --- /dev/null +++ b/tests/test_ic_project.cmake @@ -0,0 +1,69 @@ +# Copyright (c) 2023 Intercreate, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: J.P. Hutchins + +test_cmake_group_begin("ic_project() with required args") + +# test ic_project() with only required args +ic_project_out(ic_out) +ic_project( + # output variables + ${ic_out} + + # keyword arguments + CLIENT_NAME "Flumbr" + PROJECT_NAME "Dipple Snurp 3" + BOARD_NAME FF3 +) + +# assert the ones that should not be defined +assert(NOT DEFINED IC_BOARD_REV) +assert(NOT DEFINED IC_BUILD_TYPE) + +# filter out stuff that wouldn't be defined +list(FILTER ic_out EXCLUDE REGEX "IC_GIT_TAG_REV|IC_BOARD_REV|IC_BUILD_TYPE") + +foreach(ic_out_var ${ic_out}) + assert(DEFINED "${ic_out_var}") +endforeach() + +assert(Flumbr STREQUAL ${IC_CLIENT_NAME}) +assert("Dipple Snurp 3" STREQUAL ${IC_PROJECT_NAME}) +assert(FF3 STREQUAL ${IC_BOARD_NAME}) +assert(${IC_CONFIG_STRING} MATCHES Flumbr_Dipple_Snurp_3_FF3_.+_[0-9]+) + +test_cmake_group_end() + +test_cmake_group_begin("ic_project() with optional args") + +# test ic_project() with all args +ic_project_out(ic_out) +ic_project( + # output variables + ${ic_out} + + # keyword arguments + CLIENT_NAME "Flampr" + PROJECT_NAME "flying-vanilla-bean" + BOARD_NAME "toffee" + BOARD_REV "NFF2" + BUILD_TYPE proto +) + +# filter out GIT_TAG_REV - so we don't have to check here +list(FILTER ic_out EXCLUDE REGEX "IC_GIT_TAG_REV") + +foreach(ic_out_var ${ic_out}) + assert(DEFINED "${ic_out_var}") +endforeach() + +assert(Flampr STREQUAL ${IC_CLIENT_NAME}) +assert(flying-vanilla-bean STREQUAL ${IC_PROJECT_NAME}) +assert(toffee STREQUAL ${IC_BOARD_NAME}) +assert(NFF2 STREQUAL ${IC_BOARD_REV}) +assert(proto STREQUAL ${IC_BUILD_TYPE}) +assert(Flampr STREQUAL ${IC_CLIENT_NAME}) +assert(${IC_CONFIG_STRING} MATCHES Flampr_flying-vanilla-bean_toffee@NFF2_.+_[0-9]+_proto) + +test_cmake_group_end()