Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine CMake version handling based on tags #4381

Merged
merged 16 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
submodules: true
fetch-depth: 0

- name: Checkout ${{ github.event.ref }}
uses: actions/checkout@v3
if: ${{ !github.event.pull_request }}
with:
ref: ${{ github.event.ref }}
submodules: true
fetch-depth: 0

- name: Cache Dependencies
uses: actions/cache@v3.0.11
Expand Down
80 changes: 73 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ include(cmake/ReproducibleBuild.cmake)
include(cmake/ProjectVersion.cmake)
resolve_version_variables()

OPTION(ENFORCE_VERSION_MATCH "Enforce checking that configuration.h matches any parsed git tags" OFF)
OPTION(NO_TAG_IS_FATAL "If tag parsing fails, issue a fatal error" OFF)

set(PROJECT_VERSION_SUFFIX
"<auto>"
CACHE
Expand Down Expand Up @@ -36,9 +39,60 @@ set(CUSTOM_COMPILE_OPTIONS
set(FN_PREFIX "FW${PROJECT_VERSION}+${PROJECT_VERSION_SUFFIX}")

# Inform user about the resolved settings
message(STATUS "Project version ...........: ${PROJECT_VERSION}")
message(STATUS "Project version suffix ....: ${PROJECT_VERSION_SUFFIX}")
message(STATUS "Project version description: ${PROJECT_VERSION_FULL}")
message(STATUS "Project version (Configuration.h): ${PROJECT_VERSION}")
message(STATUS "Project version suffix ..........: ${PROJECT_VERSION_SUFFIX}")
message(STATUS "Project version description......: ${PROJECT_VERSION_FULL}")

# testing
# SET(FW_COMMIT_DSC "v3.13.0-1234")

if(NOT "${PROJECT_VERSION_SUFFIX}" STREQUAL "UNKNOWN" AND NOT "${FW_COMMIT_DSC}" MATCHES ".+NOTFOUND.+") # else -> no commit hash is known... likely no git.
string(REGEX MATCH "v([0-9]+)\.([0-9]+)\.([0-9]+)-?(${DEV_TAG_REGEX})?([0-9]+)?-([0-9]+)" TAG_VERSION "${FW_COMMIT_DSC}")

if (CMAKE_MATCH_4) # Do we have a build type?
decode_flavor_code(PROJECT_VER_TAG_FLV "${CMAKE_MATCH_4}" "${CMAKE_MATCH_5}")
else()
# No dev status found, it must be a final tag.
decode_flavor_code(PROJECT_VER_TAG_FLV "RELEASED" "0")
endif()

if(ENFORCE_VERSION_MATCH)
if(NOT ${CMAKE_MATCH_1} STREQUAL ${PROJECT_VERSION_MAJOR})
message(FATAL_ERROR "Major version of current tag disagrees with Configuration.h ${CMAKE_MATCH_1}!=${PROJECT_VERSION_MAJOR}")
endif()

if(NOT ${CMAKE_MATCH_2} STREQUAL ${PROJECT_VERSION_MINOR})
message(FATAL_ERROR "Minor version of current tag disagrees with Configuration.h ${CMAKE_MATCH_2}!=${PROJECT_VERSION_MINOR}")
endif()

if(NOT ${CMAKE_MATCH_3} STREQUAL ${PROJECT_VERSION_REV})
message(FATAL_ERROR "Rev version of current tag disagrees with Configuration.h ${CMAKE_MATCH_3}!=${PROJECT_VERSION_REV}")
endif()

if(NOT ${PROJECT_VER_TAG_FLV} STREQUAL ${PROJECT_VERSION_TWEAK})
message(FATAL_ERROR "Dev status of current tag disagrees with Configuration.h ${PROJECT_VER_TAG_FLV}!=${PROJECT_VERSION_TWEAK}")
endif()
# Note - we don't check the commit counter, that'd be too much of a headache. Maybe it
# should be an error only on a tagged build?
MESSAGE(STATUS "Configuration.h and tag match: OK (${PROJECT_VERSION}/${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})")
else()
MESSAGE(STATUS "Configuration.h and tag (not enforced): (${PROJECT_VERSION}/${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})")
endif()

MESSAGE(STATUS "Commit Nr: Configuration.h: ${PROJECT_VERSION_COMMIT} Tag: ${CMAKE_MATCH_6}")
MESSAGE(STATUS "These tag values will override Configuration.h")
SET(PROJECT_VERSION ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})
SET(PROJECT_VERSION_COMMIT ${CMAKE_MATCH_6})
git_get_repository(PROJECT_REPOSITORY)
else(GIT_FOUND)
if (NO_TAG_IS_FATAL)
MESSAGE(FATAL_ERROR "Git was not found or an error occurred parsing the tag. This is a fatal error according to the settings.")
else()
MESSAGE(STATUS "Git was not found or an error occurred parsing the tag. Falling back to Configuration.h values (${PROJECT_VERSION}).")
endif()
set(FW_COMMIT_HASH "0") # Clear it, the code expects a binary...
set(PROJECT_VERSION_TIMESTAMP "0")
endif()

# Language configuration
set(MAIN_LANGUAGES
Expand All @@ -58,7 +112,7 @@ set(COMMUNITY_LANGUAGES
set(SELECTED_LANGUAGES ${MAIN_LANGUAGES} ${COMMUNITY_LANGUAGES})

get_dependency_directory(prusa3dboards PRUSA_BOARDS_DIR)
project(Prusa-Firmware)
project(Prusa-Firmware VERSION ${PROJECT_VERSION})
add_subdirectory(lib)

# Get LANG_MAX_SIZE from sources
Expand Down Expand Up @@ -309,12 +363,24 @@ function(add_base_binary variant_name)
target_link_options(
${variant_name} PUBLIC -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${variant_name}.map
)

decode_tweak_version(PROJECT_VERSION_FLV PROJECT_VERSION_FLV_VER)
target_compile_definitions(
${variant_name}
PRIVATE CMAKE_CONTROL FW_REPOSITORY="${PROJECT_REPOSITORY}"
FW_VERSION_FULL="${PROJECT_VERSION_FULL}" FW_COMMIT_HASH=0x${FW_COMMIT_HASH}
FW_COMMIT_HASH=0x${FW_COMMIT_HASH}
FW_MAJOR=${PROJECT_VERSION_MAJOR}
FW_MINOR=${PROJECT_VERSION_MINOR}
FW_REVISION=${PROJECT_VERSION_REV}
FW_COMMITNR=${PROJECT_VERSION_COMMIT}
)
if(NOT PROJECT_VERSION_FLV STREQUAL "RELEASED")
target_compile_definitions(
${variant_name}
PRIVATE
FW_FLAVERSION=${PROJECT_VERSION_FLV_VER}
FW_FLAVOR=${PROJECT_VERSION_FLV}
)
endif()
endfunction()

function(fw_add_variant variant_name)
Expand Down Expand Up @@ -500,7 +566,7 @@ if(CMAKE_CROSSCOMPILING)
set(DIR_NAME ${THIS_VAR})
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME}/CMakeLists.txt
"project(${DIR_NAME})\nfw_add_variant(${THIS_VAR})"
"project(${DIR_NAME} VERSION ${PROJECT_VERSION})\nfw_add_variant(${THIS_VAR})"
)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
endforeach(THIS_VAR IN LISTS FW_VARIANTS)
Expand Down
20 changes: 17 additions & 3 deletions Firmware/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,37 @@

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define _CONCAT(x,y) x##y
#define CONCAT(x,y) _CONCAT(x,y)

#include <avr/pgmspace.h>
extern const uint16_t _nPrinterType;
extern const char _sPrinterName[] PROGMEM;
extern const uint16_t _nPrinterMmuType;
extern const char _sPrinterMmuName[] PROGMEM;

// Firmware version
// Firmware version.
// NOTE: These are ONLY used if you are not building via cmake and/or not in a git repository.
// Otherwise the repository information takes precedence.
#ifndef CMAKE_CONTROL
#define FW_MAJOR 3
#define FW_MINOR 13
#define FW_REVISION 1
#define FW_FLAVOR RC //uncomment if DEBUG, DEVEL, ALPHA, BETA or RC
#define FW_REVISION 0
#warning "** Not sure why I had to touch this, but it seems like v3.13.1 is not in the linear history of this branch yet?"
#define FW_COMMITNR 6853
#define FW_FLAVOR RC //uncomment if DEV, ALPHA, BETA or RC
#define FW_FLAVERSION 1 //uncomment if FW_FLAVOR is defined and versioning is needed. Limited to max 8.
#endif

#ifndef FW_FLAVOR
#define FW_TWEAK (FIRMWARE_REVISION_RELEASED)
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION)
#define FW_VERSION_FULL STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_COMMITNR)
#else
// Construct the TWEAK value as it is expected from the enum.
#define FW_TWEAK (CONCAT(FIRMWARE_REVISION_,FW_FLAVOR) + FW_FLAVERSION)
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION)
#define FW_VERSION_FULL STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION) "-" STR(FW_COMMITNR)
#endif

// The full version string and repository source are set via cmake
Expand Down
6 changes: 4 additions & 2 deletions Firmware/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ const uint16_t FW_VERSION_NR[4] PROGMEM = {
FW_MAJOR,
FW_MINOR,
FW_REVISION,
(uint16_t)(FW_COMMIT_HASH) // explicitly truncate the hash to fit
FW_TWEAK,
};

const uint32_t FW_VERSION_HASH PROGMEM = FW_COMMIT_HASH;

const char* FW_VERSION_STR_P()
{
return FW_VERSION_STR;
Expand Down Expand Up @@ -147,7 +149,7 @@ inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n)
return -1;
if (pgm_read_byte(p1) > pgm_read_byte(p2))
return 1;
}
}
}
return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions Firmware/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
extern const uint16_t FW_VERSION_NR[4];
extern const char* FW_VERSION_STR_P();

extern const uint32_t FW_VERSION_HASH PROGMEM;
static inline uint32_t FW_VERSION_HASH_P() { return (uint32_t)pgm_read_dword(&FW_VERSION_HASH); }

// Definition of a firmware flavor numerical values.
// To keep it short as possible
// DEVs/ALPHAs/BETAs limited to max 8 flavor versions
Expand Down
68 changes: 65 additions & 3 deletions cmake/GetGitRevisionDescription.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,21 @@ function(git_describe_working_tree _var)
PARENT_SCOPE)
return()
endif()

git_head_commit_number(COMMIT_COUNT) #Bake the commit count into the full DSC
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
COMMAND "${GIT_EXECUTABLE}" describe --abbrev=0 --dirty=-D --broken=-B ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()

if( "${out}" MATCHES "-D\$")
STRING(REPLACE "-D" "-${COMMIT_COUNT}-D" out "${out}")
else()
set(out "${out}-${COMMIT_COUNT}")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
Expand Down Expand Up @@ -358,3 +362,61 @@ function(git_head_commit_data _var _format)
${out}
PARENT_SCOPE)
endfunction()

function(git_head_commit_number _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-list --count HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()

set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()

function(git_get_repository _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"Unknown"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" ls-remote --get-url
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
message("remote URL is ${out}")
string(REGEX MATCH "([A-z0-9-]+)/Prusa-Firmware.?g?i?t?" out "${out}")
if("${CMAKE_MATCH_COUNT}" EQUAL 1)
message("Found repository name ${CMAKE_MATCH_1}")
set(${_var}
"${CMAKE_MATCH_1}"
PARENT_SCOPE)
else()
message("Failed to get repository information")
set(${_var}
#"${out}" #outputs the github repo user name
"Unknown" #All other repos shown as unknown
PARENT_SCOPE)
endif()
endfunction()
58 changes: 56 additions & 2 deletions cmake/ProjectVersion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,50 @@
# ~~~
#]]

# NOTE: these are ordered according to the enum in Util.h. DO NOT ALTER!
# // Definition of a firmware flavor numerical values.
# // To keep it short as possible
# // DEVs/ALPHAs/BETAs limited to max 8 flavor versions
# // RCs limited to 32 flavor versions
# // Final Release always 64 as highest
# enum FirmwareRevisionFlavorType : uint16_t {
# FIRMWARE_REVISION_RELEASED = 0x0040,
# FIRMWARE_REVISION_DEV = 0x0000,
# FIRMWARE_REVISION_ALPHA = 0x008,
# FIRMWARE_REVISION_BETA = 0x0010,
# FIRMWARE_REVISION_RC = 0x0020
# };

# Note - the Xes are padding because there is an extended allowance of RC numbers.
SET(DEV_TAGS "DEV" "ALPHA" "BETA" "RC" "X" "X" "X" "X" "RELEASED")
STRING(REPLACE ";" "\|" DEV_TAG_REGEX "${DEV_TAGS}")
function(decode_flavor_code _output _label _ver)
LIST(FIND DEV_TAGS "${_label}" _code_index)
MESSAGE(DEBUG "Tweak math: (8*0${_code_index})+${_ver}")
MATH(EXPR _decoded "(8*0${_code_index})+${_ver}")
set(${_output}
"${_decoded}"
PARENT_SCOPE)
endfunction()

function(decode_tweak_version _str _ver)
MATH(EXPR _string_id "(${PROJECT_VERSION_TWEAK})/8")
MATH(EXPR _version "${PROJECT_VERSION_TWEAK}-(8*${_string_id})")
set(${_ver} "${_version}" PARENT_SCOPE)
LIST(GET DEV_TAGS ${_string_id} _string_val)
set(${_str} "${_string_val}" PARENT_SCOPE)
endfunction()


file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/Firmware/Configuration.h CFG_VER_DATA
REGEX "#define FW_[A-Z]+ ([0-9]+)"
REGEX "#define FW_[A-Z]+ (${DEV_TAG_REGEX}|[0-9]+)"
)
list(GET CFG_VER_DATA 0 PROJECT_VERSION_MAJOR)
list(GET CFG_VER_DATA 1 PROJECT_VERSION_MINOR)
list(GET CFG_VER_DATA 2 PROJECT_VERSION_REV)
list(GET CFG_VER_DATA 3 PROJECT_VERSION_COMMIT)
list(GET CFG_VER_DATA 4 PROJECT_VERSION_FLV)
list(GET CFG_VER_DATA 5 PROJECT_VERSION_FLV_VER)

string(REGEX MATCH "FW_MAJOR ([0-9]+)" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(PROJECT_VERSION_MAJOR "${CMAKE_MATCH_1}")
Expand All @@ -31,7 +69,23 @@ set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_1})
string(REGEX MATCH "FW_REVISION +([0-9]+)" PROJECT_VERSION_REV "${PROJECT_VERSION_REV}")
set(PROJECT_VERSION_REV ${CMAKE_MATCH_1})

set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_REV}")
string(REGEX MATCH "FW_COMMITNR +([0-9]+)" PROJECT_VERSION_COMMIT "${PROJECT_VERSION_COMMIT}")
set(PROJECT_VERSION_COMMIT ${CMAKE_MATCH_1})

string(REGEX MATCH "^#define FW_FLAVOR +(${DEV_TAG_REGEX})" PROJECT_VERSION_FLV "${PROJECT_VERSION_FLV}")
IF(PROJECT_VERSION_FLV)
message(STATUS "Found a defined FW_FLAVOR")
set(PROJECT_VERSION_FLV ${CMAKE_MATCH_1})
string(REGEX MATCH "FW_FLAVERSION +([0-9]+)" PROJECT_VERSION_FLV_VER "${PROJECT_VERSION_FLV_VER}")
set(PROJECT_VERSION_FLV_VER ${CMAKE_MATCH_1})

decode_flavor_code(PROJECT_VERSION_TWEAK "${PROJECT_VERSION_FLV}" "${PROJECT_VERSION_FLV_VER}")
ELSE()
decode_flavor_code(PROJECT_VERSION_TWEAK "RELEASED" "0")
ENDIF()


set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_REV}.${PROJECT_VERSION_TWEAK}")

function(resolve_version_variables)
if(FW_COMMIT_DSC)
Expand Down
Loading