/ cmake / git_version.cmake
git_version.cmake
  1  # Inspired by https://www.mattkeeter.com/blog/2018-01-06-versioning/
  2  
  3  #
  4  # Include version.h in your code to use the auto-generated variables
  5  # Make sure to update version.h if you ever add new ones!
  6  #
  7  
  8  set(GIT_CMD git)
  9  set(GIT_ARGS_SHA describe --match ForceNone --abbrev=8 --always)
 10  execute_process(COMMAND ${GIT_CMD} ${GIT_ARGS_SHA}
 11                  OUTPUT_VARIABLE GIT_SHA
 12                  OUTPUT_STRIP_TRAILING_WHITESPACE)
 13  
 14  # Figure out if there are uncommitted/unstaged changes to git repo
 15  # See https://stackoverflow.com/a/2659808 for more info
 16  execute_process(COMMAND ${GIT_CMD} diff-index --quiet HEAD -- RESULT_VARIABLE IS_DIRTY)
 17  if(IS_DIRTY)
 18  set(DIRTY_STR "1")
 19  else()
 20  set(DIRTY_STR "0")
 21  endif()
 22  
 23  # if VERSION_STR wasn't passed as an argument, get it from git
 24  if(NOT VERSION_STR)
 25      set(GIT_ARGS_TAG describe --always --dirty --abbrev=8)
 26  
 27      execute_process(COMMAND ${GIT_CMD} ${GIT_ARGS_TAG}
 28                      OUTPUT_VARIABLE VERSION_STR
 29                      OUTPUT_STRIP_TRAILING_WHITESPACE)
 30  endif()
 31  
 32  # Convert GIT_SHA from hex to decimal
 33  math(EXPR GIT_SHA_DEC "0x${GIT_SHA}" OUTPUT_FORMAT DECIMAL)
 34  
 35  set(NOTE_FW_STR "\n#ifdef HAS_NOTECARD\nconst char *NOTE_FW_STR = \"firmware::info:{")
 36  set(NOTE_FW_STR "${NOTE_FW_STR}\\\"product\\\":\\\"Sunflower\\\",")
 37  set(NOTE_FW_STR "${NOTE_FW_STR}\\\"firmware\\\":\\\"${VERSION_STR}\\\",")
 38  
 39  # Default to eng build unless RELEASE=1 is passed in
 40  if(RELEASE STREQUAL "1")
 41  set(ENG_STR "0")
 42  else ()
 43  set(ENG_STR "1")
 44  endif()
 45  
 46  if (VERSION_STR MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)$")
 47      # Extract version info from git tag
 48      # Expects format vx.y.z with optional extra stuff in the end
 49      set(MAJ_STR "${CMAKE_MATCH_1}")
 50      set(MIN_STR "${CMAKE_MATCH_2}")
 51      set(REV_STR "${CMAKE_MATCH_3}")
 52  
 53      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_major\\\":${CMAKE_MATCH_1},")
 54      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_minor\\\":${CMAKE_MATCH_2},")
 55      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_patch\\\":${CMAKE_MATCH_3},")
 56  
 57      set(MCUBOOT_VERSION_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}+${GIT_SHA_DEC}")
 58  
 59      # Don't allow invalid version strings when doing releases
 60      # ENG- releases can have whatever
 61      if(CMAKE_MATCH_4 AND RELEASE STREQUAL "1")
 62          message(ERROR "Release versions MUST follow format: vx.x.x")
 63      endif()
 64  
 65  else()
 66      message(WARNING "invalid version string!")
 67  
 68      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_major\\\":0,")
 69      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_minor\\\":0,")
 70      set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_patch\\\":0,")
 71  
 72      set(MAJ_STR "0xFF")
 73      set(MIN_STR "0xFF")
 74      set(REV_STR "0xFF")
 75      set(MCUBOOT_VERSION_STR "0.0.0+${GIT_SHA_DEC}")
 76  endif()
 77  
 78  # Safety checks
 79  if(DIRTY_STR STREQUAL "1" AND RELEASE STREQUAL 1)
 80  message( SEND_ERROR "Cannot have a release build with a dirty git repo!" )
 81  endif()
 82  
 83  # Last item doesn't have a comma!!!
 84  set(NOTE_FW_STR "${NOTE_FW_STR}\\\"ver_build\\\":${GIT_SHA_DEC}")
 85  set(NOTE_FW_STR "${NOTE_FW_STR}}\";\n#endif\n")
 86  
 87  #
 88  # These arguments are passed as command line defines -DXYZ by caller
 89  #
 90  if(APP STREQUAL "bootloader")
 91      set(IS_BOOTLOADER_STR "1")
 92  else()
 93      set(IS_BOOTLOADER_STR "0")
 94  endif()
 95  
 96  if(SIGN_IMAGES STREQUAL 1)
 97      set(SIGN_IMAGES_STR "1")
 98  else()
 99      set(SIGN_IMAGES_STR "0")
100  endif()
101  
102  if(ENCRYPT_IMAGES STREQUAL 1)
103      set(ENCRYPT_IMAGES_STR "1")
104  else()
105      set(ENCRYPT_IMAGES_STR "0")
106  endif()
107  
108  string(LENGTH ${VERSION_STR} VERSION_STR_LEN)
109  
110  string(CONCAT VERSION
111      "#include <stdbool.h>\n"
112      "#include <stdint.h>\n"
113      "#include \"version.h\"\n"
114      "\n"
115      "__attribute__ ((section(\".note.sofar.version\")))\n"
116      "const versionNote_t versionNote = {\n"
117      "  .note = {\n"
118      "    .namesz=sizeof(((versionNote_t *)0)->name),\n"
119      "    .descsz=sizeof(versionInfo_t),\n"
120      "    .type=0x10, // Arbitrarily large value so binutis won't get confused\n"
121      "  },\n"
122      "  .name=\"VERSION\",\n"
123      "  .info = {\n"
124      "    .magic = VERSION_MAGIC,\n"
125      "    .gitSHA = 0x${GIT_SHA},\n"
126      "    .maj = ${MAJ_STR},\n"
127      "    .min = ${MIN_STR},\n"
128      "    .rev = ${REV_STR},\n"
129      "    .hwVersion = ${HW_VERSION},\n"
130      "    .flags = (\n"
131      "      (${ENG_STR} << VER_ENG_FLAG_OFFSET) |\n"
132      "      (${DIRTY_STR} << VER_DIRTY_FLAG_OFFSET) |\n"
133      "      (${IS_BOOTLOADER_STR} << VER_IS_BOOTLOADER_OFFSET) |\n"
134      "      (${SIGN_IMAGES_STR} << VER_SIGNATURE_SUPPORT_OFFSET) |\n"
135      "      (${ENCRYPT_IMAGES_STR} << VER_ENCRYPTION_SUPPORT_OFFSET)\n"
136      "     ),\n"
137      "    .versionStrLen = ${VERSION_STR_LEN},\n"
138      "    .versionStr = \"${VERSION_STR}\",\n"
139      "  },\n"
140      "};\n"
141      "${NOTE_FW_STR}\n"
142      )
143  
144  
145  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/version.c)
146      file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.c VERSION_)
147  else()
148      set(VERSION_ "")
149  endif()
150  
151  if (NOT "${VERSION}" STREQUAL "${VERSION_}")
152      file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/version.c "${VERSION}")
153  endif()
154  
155  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/version_string)
156      file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version_string MCUBOOT_VERSION_STR_)
157  else()
158      set(MCUBOOT_VERSION_STR_ "")
159  endif()
160  
161  if (NOT "${MCUBOOT_VERSION_STR}" STREQUAL "${MCUBOOT_VERSION_STR_}")
162      file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/version_string "${MCUBOOT_VERSION_STR}")
163  endif()
164  
165  message(STATUS "git version: ${VERSION_STR}")