Prepare parts of the build system
extracted and slightly modified from Buddy-FW, still doesn't workpull/1/head
parent
d3500a7e16
commit
c85d86f340
|
|
@ -0,0 +1,126 @@
|
|||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: WebKit
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# If a statement is wrapped to more than one line, than dangle the closing
|
||||
# parenthesis on it's own line.
|
||||
dangle_parens = True
|
||||
dangle_align = 'child'
|
||||
|
||||
# If true, the parsers may infer whether or not an argument list is sortable
|
||||
# (without annotation).
|
||||
autosort = True
|
||||
|
||||
# How wide to allow formatted cmake files
|
||||
line_width = 100
|
||||
|
||||
additional_commands = {
|
||||
"target_sources": {
|
||||
"kwargs": {
|
||||
"PUBLIC": "*",
|
||||
"PRIVATE": "*",
|
||||
"INTERFACE": "*",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
.vs
|
||||
/build*
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
.dependencies
|
||||
.DS_Store
|
||||
/CMakeLists.txt.user
|
||||
.ccls-cache
|
||||
.idea
|
||||
compile_commands.json
|
||||
/.vscode/*.peripherals.state.json
|
||||
/.vscode/*.registers.state.json
|
||||
Makefile
|
||||
/doc/html/
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/dragomirecky/cmake-format-pre-commit-hook
|
||||
rev: 'v0.6.0'
|
||||
hooks:
|
||||
- id: cmake-format # cmake formatter
|
||||
files: (CMakeLists.*|.*\.cmake|.*\.cmake.in)
|
||||
- repo: https://github.com/pre-commit/mirrors-yapf
|
||||
rev: 'v0.27.0'
|
||||
hooks:
|
||||
- id: yapf # python formatter
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: clang-format
|
||||
name: clang-format
|
||||
description: This hook automatically checks and reformats changed files using clang-format formatter.
|
||||
entry: './.dependencies/clang-format-9.0.0-noext/clang-format'
|
||||
language: script
|
||||
files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$
|
||||
args: ['-i', '-style=file']
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: 'v2.4.0'
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
exclude: |
|
||||
(?x)(
|
||||
^tests/unit/lang/translator/(keys|cs|es|fr|de|pl|it)\.txt$|
|
||||
^lib/inih/|
|
||||
^lib/Marlin/|
|
||||
^lib/Prusa-Error-Codes/|
|
||||
^lib/TMCStepper/|
|
||||
^lib/Middlewares/Third_Party/LwIP/|
|
||||
^lib/jsmn/|
|
||||
^lib/Catch2/
|
||||
)
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
include(cmake/Utilities.cmake)
|
||||
include(cmake/GetGitRevisionDescription.cmake)
|
||||
include(cmake/ProjectVersion.cmake)
|
||||
|
||||
project(
|
||||
MMU
|
||||
LANGUAGES C CXX ASM
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
#
|
||||
# If we are not crosscompiling, include `utils` with host tools.
|
||||
#
|
||||
add_subdirectory(utils)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Command Line Options
|
||||
#
|
||||
# You should specify those options when invoking CMake. Example:
|
||||
# ~~~
|
||||
# cmake .. <other options> -DPRINTER=MMU
|
||||
# ~~~
|
||||
|
||||
set(PRINTER_VALID_OPTS "MMU")
|
||||
|
||||
set(PRINTER
|
||||
"MMU"
|
||||
CACHE
|
||||
STRING
|
||||
"Select the MMU unit for which you want to compile the project (valid values are ${PRINTER_VALID_OPTS})."
|
||||
)
|
||||
set(PROJECT_VERSION_SUFFIX
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Full version suffix to be shown on the info screen in settings (e.g. full_version=4.0.3-BETA+1035.PR111.B4, suffix=-BETA+1035.PR111.B4). Defaults to '+<commit sha>.<dirty?>.<debug?>' if set to '<auto>'."
|
||||
)
|
||||
set(PROJECT_VERSION_SUFFIX_SHORT
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Short version suffix to be shown on splash screen. Defaults to '+<BUILD_NUMBER>' if set to '<auto>'."
|
||||
)
|
||||
set(BUILD_NUMBER
|
||||
""
|
||||
CACHE STRING "Build number of the firmware. Resolved automatically if not specified."
|
||||
)
|
||||
set(CUSTOM_COMPILE_OPTIONS
|
||||
""
|
||||
CACHE STRING "Allows adding custom C/C++ flags"
|
||||
)
|
||||
|
||||
# Validate options
|
||||
foreach(OPTION "PRINTER")
|
||||
if(NOT ${OPTION} IN_LIST ${OPTION}_VALID_OPTS)
|
||||
message(FATAL_ERROR "Invalid ${OPTION} ${${OPTION}}: Valid values are ${${OPTION}_VALID_OPTS}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Resolve BUILD_NUMBER and PROJECT_VERSION_* variables
|
||||
resolve_version_variables()
|
||||
|
||||
# Check GCC Version
|
||||
get_recommended_gcc_version(RECOMMENDED_TOOLCHAIN_VERSION)
|
||||
if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL
|
||||
${RECOMMENDED_TOOLCHAIN_VERSION}
|
||||
)
|
||||
message(WARNING "Recommended AVR toolchain is ${RECOMMENDED_TOOLCHAIN_VERSION}"
|
||||
", but you have ${CMAKE_CXX_COMPILER_VERSION}"
|
||||
)
|
||||
|
||||
elseif(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
message(
|
||||
WARNING
|
||||
"Recommended compiler for host tools and unittests is GCC, you have ${CMAKE_CXX_COMPILER_ID}."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Inform user about the resolved settings
|
||||
message(STATUS "Project version: ${PROJECT_VERSION}")
|
||||
message(STATUS "Project version with full suffix: ${PROJECT_VERSION_FULL}")
|
||||
message(
|
||||
STATUS "Project version with short suffix: ${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX_SHORT}"
|
||||
)
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
|
||||
message(STATUS "Printer: ${PRINTER}")
|
||||
|
||||
# eclipse sets those variables, so lets just use them so we don't get a warning about unused
|
||||
# variables
|
||||
set(unused "${CMAKE_VERBOSE_MAKEFILE} ${CMAKE_RULE_MESSAGES}")
|
||||
|
||||
# append custom C/C++ flags
|
||||
if(CUSTOM_COMPILE_OPTIONS)
|
||||
string(REPLACE " " ";" CUSTOM_COMPILE_OPTIONS "${CUSTOM_COMPILE_OPTIONS}")
|
||||
add_compile_options(${CUSTOM_COMPILE_OPTIONS})
|
||||
endif()
|
||||
|
||||
#
|
||||
# MMUHeaders
|
||||
#
|
||||
|
||||
# add_library(MMUHeaders INTERFACE) target_include_directories( MMUHeaders INTERFACE include
|
||||
# include/stm32f4_hal include/usb_host include/usb_device include/marlin include/freertos )
|
||||
|
||||
# target_link_libraries(A3idesHeaders INTERFACE STM32F4::HAL FreeRTOS::FreeRTOS)
|
||||
|
||||
# target_compile_definitions( A3idesHeaders INTERFACE PRINTER_TYPE=PRINTER_PRUSA_${PRINTER} )
|
||||
|
||||
#
|
||||
# Global Compiler & Linker Configuration
|
||||
#
|
||||
|
||||
# include symbols
|
||||
add_compile_options(-g)
|
||||
|
||||
# optimizations
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_compile_options(-Og)
|
||||
else()
|
||||
add_compile_options(-Os)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
# mcu related settings set(MCU_FLAGS -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16)
|
||||
# add_compile_options(${MCU_FLAGS}) add_link_options(${MCU_FLAGS})
|
||||
|
||||
# split and gc sections
|
||||
add_compile_options(-ffunction-sections -fdata-sections)
|
||||
add_link_options(-Wl,--gc-sections)
|
||||
|
||||
# disable exceptions and related metadata
|
||||
add_compile_options(-fno-exceptions -fno-unwind-tables)
|
||||
add_link_options(-Wl,--defsym,__exidx_start=0,--defsym,__exidx_end=0)
|
||||
endif()
|
||||
|
||||
# enable all warnings (well, not all, but some)
|
||||
add_compile_options(-Wall -Wsign-compare)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-register> $<$<COMPILE_LANGUAGE:CXX>:-std=c++14>)
|
||||
|
||||
# support _DEBUG macro (some code uses to recognize debug builds)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_compile_definitions(_DEBUG)
|
||||
endif()
|
||||
|
||||
# if(CMAKE_CROSSCOMPILING) # configure linker script set(LINKER_SCRIPT
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/src/STM32F407VG_FLASH.ld")
|
||||
# add_link_options("-Wl,-T,${LINKER_SCRIPT}") endif()
|
||||
|
||||
#
|
||||
# Import definitions of all libraries
|
||||
#
|
||||
|
||||
# add_subdirectory(lib)
|
||||
|
||||
#
|
||||
# MMU firmware
|
||||
#
|
||||
|
||||
add_executable(firmware)
|
||||
|
||||
set_target_properties(firmware PROPERTIES CXX_STANDARD 14)
|
||||
|
||||
# generate firmware.bin file
|
||||
objcopy(firmware "binary" ".bin")
|
||||
|
||||
# generate linker map file
|
||||
target_link_options(firmware PUBLIC -Wl,-Map=firmware.map)
|
||||
|
||||
# inform about the firmware's size in terminal
|
||||
report_size(firmware)
|
||||
|
||||
# add_link_dependency(firmware "${LINKER_SCRIPT}")
|
||||
|
||||
target_include_directories(firmware PRIVATE include src)
|
||||
|
||||
target_compile_options(firmware PRIVATE -Wdouble-promotion)
|
||||
|
||||
# target_link_libraries( firmware PRIVATE A3idesHeaders )
|
||||
|
||||
target_sources(firmware PRIVATE src/main.cpp)
|
||||
|
||||
set_property(
|
||||
SOURCE src/version.c
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
FW_BUILD_NUMBER=${BUILD_NUMBER}
|
||||
FW_VERSION_FULL=${PROJECT_VERSION_FULL}
|
||||
FW_VERSION=${PROJECT_VERSION}
|
||||
FW_VERSION_SUFFIX=${PROJECT_VERSION_SUFFIX}
|
||||
FW_VERSION_SUFFIX_SHORT=${PROJECT_VERSION_SUFFIX_SHORT}
|
||||
)
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
get_filename_component(PROJECT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||
include("${PROJECT_CMAKE_DIR}/Utilities.cmake")
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
||||
|
||||
#
|
||||
# Utilities
|
||||
|
||||
if(MINGW
|
||||
OR CYGWIN
|
||||
OR WIN32
|
||||
)
|
||||
set(UTIL_SEARCH_CMD where)
|
||||
set(EXECUTABLE_SUFFIX ".exe")
|
||||
elseif(UNIX OR APPLE)
|
||||
set(UTIL_SEARCH_CMD which)
|
||||
set(EXECUTABLE_SUFFIX "")
|
||||
endif()
|
||||
|
||||
set(TOOLCHAIN_PREFIX arm-none-eabi-)
|
||||
|
||||
#
|
||||
# Looking up the toolchain
|
||||
#
|
||||
|
||||
if(ARM_TOOLCHAIN_DIR)
|
||||
# using toolchain set by gcc-arm-none-eabi.cmake (locked version)
|
||||
set(BINUTILS_PATH "${ARM_TOOLCHAIN_DIR}/bin")
|
||||
else()
|
||||
# search for ANY arm-none-eabi-gcc toolchain
|
||||
execute_process(
|
||||
COMMAND ${UTIL_SEARCH_CMD} ${TOOLCHAIN_PREFIX}gcc
|
||||
OUTPUT_VARIABLE ARM_NONE_EABI_GCC_PATH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE FIND_RESULT
|
||||
)
|
||||
# found?
|
||||
if(NOT "${FIND_RESULT}" STREQUAL "0")
|
||||
message(FATAL_ERROR "arm-none-eabi-gcc not found")
|
||||
endif()
|
||||
get_filename_component(BINUTILS_PATH "${ARM_NONE_EABI_GCC_PATH}" DIRECTORY)
|
||||
get_filename_component(ARM_TOOLCHAIN_DIR ${BINUTILS_PATH} DIRECTORY)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Setup CMake
|
||||
#
|
||||
|
||||
# Without that flag CMake is not able to pass test compilation check
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(triple armv7m-none-eabi)
|
||||
set(CMAKE_C_COMPILER
|
||||
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}gcc${EXECUTABLE_SUFFIX}"
|
||||
CACHE FILEPATH "" FORCE
|
||||
)
|
||||
set(CMAKE_C_COMPILER_TARGET
|
||||
${triple}
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
set(CMAKE_ASM_COMPILER
|
||||
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}gcc${EXECUTABLE_SUFFIX}"
|
||||
CACHE FILEPATH "" FORCE
|
||||
)
|
||||
set(CMAKE_ASM_COMPILER_TARGET
|
||||
${triple}
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
set(CMAKE_CXX_COMPILER
|
||||
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}g++${EXECUTABLE_SUFFIX}"
|
||||
CACHE FILEPATH "" FORCE
|
||||
)
|
||||
set(CMAKE_CXX_COMPILER_TARGET
|
||||
${triple}
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT
|
||||
"--specs=nosys.specs"
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_ASM_COMPILE_OBJECT
|
||||
"<CMAKE_ASM_COMPILER> <DEFINES> <FLAGS> -o <OBJECT> -c <SOURCE>"
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_OBJCOPY
|
||||
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}objcopy${EXECUTABLE_SUFFIX}"
|
||||
CACHE INTERNAL "objcopy tool"
|
||||
)
|
||||
set(CMAKE_SIZE_UTIL
|
||||
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}size${EXECUTABLE_SUFFIX}"
|
||||
CACHE INTERNAL "size tool"
|
||||
)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH "${ARM_TOOLCHAIN_DIR}")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# getlocked version
|
||||
get_filename_component(PROJECT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||
get_filename_component(PROJECT_ROOT_DIR "${PROJECT_CMAKE_DIR}" DIRECTORY)
|
||||
include("${PROJECT_CMAKE_DIR}/Utilities.cmake")
|
||||
|
||||
get_recommended_gcc_version(RECOMMENDED_TOOLCHAIN_VERSION)
|
||||
set(RECOMMENDED_TOOLCHAIN_BINUTILS
|
||||
"${PROJECT_ROOT_DIR}/.dependencies/gcc-arm-none-eabi-${RECOMMENDED_TOOLCHAIN_VERSION}/bin"
|
||||
)
|
||||
|
||||
# check that the locked version of gcc-arm-none-eabi is present
|
||||
if(NOT EXISTS "${RECOMMENDED_TOOLCHAIN_BINUTILS}")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"arm-none-eabi-gcc (version ${RECOMMENDED_TOOLCHAIN_VERSION}) not found. Run the command below to download it.\n"
|
||||
"${PROJECT_ROOT_DIR}/utils/bootstrap.sh\n"
|
||||
)
|
||||
endif()
|
||||
|
||||
# include any-gcc-arm-none-eabi toolchain and pass in ARM_TOOLCHAIN_DIR
|
||||
get_filename_component(ARM_TOOLCHAIN_DIR "${RECOMMENDED_TOOLCHAIN_BINUTILS}" DIRECTORY)
|
||||
include("${PROJECT_ROOT_DIR}/cmake/AnyGccArmNoneEabi.cmake")
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
# * Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can trust the values of the
|
||||
# variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting the output so that it tests
|
||||
# false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree, and adjusting the output so
|
||||
# that it tests false if there was no exact matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. Uses the return code of
|
||||
# "git diff-index --quiet HEAD --". Does not regard untracked files.
|
||||
#
|
||||
# git_count_parent_commits(<var>)
|
||||
#
|
||||
# Returns number of commits preceeding current commit -1 if git rev-list --count HEAD failed or
|
||||
# "GIT-NOTFOUND" if git executable was not found or "HEAD-HASH-NOTFOUND" if head hash was not found.
|
||||
# I don't know if get_git_head_revision() must be called internally or not, as reason of calling it
|
||||
# is not clear for me also in git_local_changes().
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author: 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010. Distributed under the Boost Software License, Version
|
||||
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time, to find the path to this
|
||||
# module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
set(${_hashvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file(
|
||||
"${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" "${GIT_DATA}/grabRef.cmake" @ONLY
|
||||
)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar}
|
||||
"${HEAD_REF}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
set(${_hashvar}
|
||||
"${HEAD_HASH}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize if((${ARGN}" MATCHES "&&") OR (ARGN MATCHES "||") OR (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!") message(FATAL_ERROR "Looks like
|
||||
# someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") endif()
|
||||
|
||||
# message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe ${hash} ${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()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(res EQUAL 0)
|
||||
set(${_var}
|
||||
"CLEAN"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
else()
|
||||
set(${_var}
|
||||
"DIRTY"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(git_count_parent_commits _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-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(res EQUAL 0)
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
else()
|
||||
set(${_var}
|
||||
"-1"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author: 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010. Distributed under the Boost Software License, Version
|
||||
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# This file is responsible for setting the following variables:
|
||||
#
|
||||
# ~~~
|
||||
# BUILD_NUMBER (1035)
|
||||
# PROJECT_VERSION (4.0.3)
|
||||
# PROJECT_VERSION_FULL (4.0.3-BETA+1035.PR111.B4)
|
||||
# PROJECT_VERSION_SUFFIX (-BETA+1035.PR111.B4)
|
||||
# PROJECT_VERSION_SUFFIX_SHORT (+1035)
|
||||
#
|
||||
# The `PROJECT_VERSION` variable is set as soon as the file is included.
|
||||
# To set the rest, the function `resolve_version_variables` has to be called.
|
||||
#
|
||||
# ~~~
|
||||
|
||||
# PROJECT_VERSION
|
||||
file(READ "${CMAKE_SOURCE_DIR}/version.txt" content)
|
||||
string(REGEX MATCH "([0-9]+)\.([0-9]+)\.([0-9]+)" result "${content}")
|
||||
if(NOT result)
|
||||
message(FATAL_ERROR "Failed to read version info from ${version_file}")
|
||||
endif()
|
||||
set(PROJECT_VERSION ${CMAKE_MATCH_0})
|
||||
|
||||
function(resolve_version_variables)
|
||||
# BUILD_NUMBER
|
||||
if(NOT BUILD_NUMBER)
|
||||
git_count_parent_commits(BUILD_NUMBER)
|
||||
set(ERRORS "GIT-NOTFOUND" "HEAD-HASH-NOTFOUND")
|
||||
if(BUILD_NUMBER IN_LIST ERRORS)
|
||||
message(WARNING "Failed to resolve build number: ${BUILD_NUMBER}. Setting to zero.")
|
||||
set(BUILD_NUMBER "0")
|
||||
endif()
|
||||
set(BUILD_NUMBER
|
||||
${BUILD_NUMBER}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
||||
|
||||
# PROJECT_VERSION_SUFFIX
|
||||
if(PROJECT_VERSION_SUFFIX STREQUAL "<auto>")
|
||||
# TODO: set to +<sha>.dirty?.debug?
|
||||
set(PROJECT_VERSION_SUFFIX "+${BUILD_NUMBER}.LOCAL")
|
||||
set(PROJECT_VERSION_SUFFIX
|
||||
"+${BUILD_NUMBER}.LOCAL"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
||||
|
||||
# PROJECT_VERSION_SUFFIX_SHORT
|
||||
if(PROJECT_VERSION_SUFFIX_SHORT STREQUAL "<auto>")
|
||||
set(PROJECT_VERSION_SUFFIX_SHORT
|
||||
"+${BUILD_NUMBER}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
||||
|
||||
# PROJECT_VERSION_FULL
|
||||
set(PROJECT_VERSION_FULL
|
||||
"${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
get_filename_component(PROJECT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||
get_filename_component(PROJECT_ROOT_DIR "${PROJECT_CMAKE_DIR}" DIRECTORY)
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
if(NOT Python3_FOUND)
|
||||
message(FATAL_ERROR "Python3 not found.")
|
||||
endif()
|
||||
|
||||
function(get_recommended_gcc_version var)
|
||||
execute_process(
|
||||
COMMAND "${Python3_EXECUTABLE}" "${PROJECT_ROOT_DIR}/utils/bootstrap.py"
|
||||
"--print-dependency-version" "gcc-arm-none-eabi"
|
||||
OUTPUT_VARIABLE RECOMMENDED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RETVAL
|
||||
)
|
||||
|
||||
if(NOT "${RETVAL}" STREQUAL "0")
|
||||
message(FATAL_ERROR "Failed to obtain recommended gcc version from utils/bootstrap.py")
|
||||
endif()
|
||||
|
||||
set(${var}
|
||||
${RECOMMENDED_VERSION}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(get_dependency_directory dependency var)
|
||||
execute_process(
|
||||
COMMAND "${Python3_EXECUTABLE}" "${PROJECT_ROOT_DIR}/utils/bootstrap.py"
|
||||
"--print-dependency-directory" "${dependency}"
|
||||
OUTPUT_VARIABLE DEPENDENCY_DIRECTORY
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RETVAL
|
||||
)
|
||||
|
||||
if(NOT "${RETVAL}" STREQUAL "0")
|
||||
message(FATAL_ERROR "Failed to find directory with ${dependency}")
|
||||
endif()
|
||||
|
||||
set(${var}
|
||||
${DEPENDENCY_DIRECTORY}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(objcopy target format suffix)
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND "${CMAKE_OBJCOPY}" -O ${format} -S "$<TARGET_FILE:${target}>"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${target}${suffix}"
|
||||
COMMENT "Generating ${format} from ${target}..."
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(report_size target)
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND echo "" # visually separate the output
|
||||
COMMAND "${CMAKE_SIZE_UTIL}" -B "$<TARGET_FILE:${target}>"
|
||||
USES_TERMINAL
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(pack_firmware target fw_version build_number printer_type signing_key)
|
||||
set(bin_firmware_path "${CMAKE_CURRENT_BINARY_DIR}/${target}.bin")
|
||||
if(SIGNING_KEY)
|
||||
set(sign_opts "--key" "${signing_key}")
|
||||
else()
|
||||
set(sign_opts "--no-sign")
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND "${CMAKE_OBJCOPY}" -O binary -S "$<TARGET_FILE:${target}>" "${bin_firmware_path}"
|
||||
COMMAND echo "" # visually separate the output
|
||||
COMMAND
|
||||
"${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/utils/pack_fw.py" --version="${fw_version}"
|
||||
--printer-type "${printer_type}" --printer-version "1" ${sign_opts} "${bin_firmware_path}"
|
||||
--build-number "${build_number}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(create_dfu)
|
||||
set(options)
|
||||
set(one_value_args OUTPUT TARGET)
|
||||
set(multi_value_args INPUT)
|
||||
cmake_parse_arguments(CREATE_DFU "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
add_custom_command(
|
||||
TARGET "${CREATE_DFU_TARGET}" POST_BUILD
|
||||
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/utils/dfu.py" create ${CREATE_DFU_INPUT}
|
||||
"${CREATE_DFU_OUTPUT}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(add_link_dependency target file_path)
|
||||
get_target_property(link_deps ${target} LINK_DEPENDS)
|
||||
if(link_deps STREQUAL "link_deps-NOTFOUND")
|
||||
set(link_deps "")
|
||||
endif()
|
||||
list(APPEND link_deps "${file_path}")
|
||||
set_target_properties(${target} PROPERTIES LINK_DEPENDS "${link_deps}")
|
||||
endfunction()
|
||||
|
||||
function(rfc1123_datetime var)
|
||||
set(cmd
|
||||
"from email.utils import formatdate; print(formatdate(timeval=None, localtime=False, usegmt=True))"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND "${Python3_EXECUTABLE}" -c "${cmd}"
|
||||
OUTPUT_VARIABLE RFC1123_DATETIME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RETVAL
|
||||
)
|
||||
if(NOT "${RETVAL}" STREQUAL "0")
|
||||
message(FATAL_ERROR "Failed to obtain rfc1123 date time from Python")
|
||||
endif()
|
||||
set(${var}
|
||||
${RFC1123_DATETIME}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#include "version.h"
|
||||
#include "config.h"
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
const char project_version[] = STR(FW_VERSION);
|
||||
|
||||
const char project_version_full[] = STR(FW_VERSION_FULL);
|
||||
|
||||
const char project_version_suffix[] = STR(FW_VERSION_SUFFIX);
|
||||
|
||||
const char project_version_suffix_short[] = STR(FW_VERSION_SUFFIX_SHORT);
|
||||
|
||||
const int project_build_number = FW_BUILD_NUMBER;
|
||||
|
||||
#if (PRINTER_TYPE == PRINTER_PRUSA_MINI)
|
||||
const char project_firmware_name[] = "Buddy_MINI";
|
||||
#else
|
||||
#error "unknown printer type"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif //__cplusplus
|
||||
|
||||
/// Project's version (4.0.2)
|
||||
extern const char project_version[];
|
||||
|
||||
/// Full project's version (4.0.3-BETA+1035.PR111.B4)
|
||||
extern const char project_version_full[];
|
||||
|
||||
/// Project's version suffix (-BETA+1035.PR111.B4)
|
||||
extern const char project_version_suffix[];
|
||||
|
||||
/// Project's short version suffix (+1035)
|
||||
extern const char project_version_suffix_short[];
|
||||
|
||||
/// Project's build number (number of commits in a branch)
|
||||
extern const int project_build_number;
|
||||
|
||||
/// Firmware name
|
||||
extern const char project_firmware_name[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif //__cplusplus
|
||||
|
|
@ -0,0 +1 @@
|
|||
#
|
||||
|
|
@ -0,0 +1 @@
|
|||
#
|
||||
|
|
@ -0,0 +1 @@
|
|||
#
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Bootstrap Script
|
||||
#
|
||||
# This script
|
||||
# 1) records the recommended versions of dependencies, and
|
||||
# 2) when run, checks that all of them are present and downloads
|
||||
# them if they are not.
|
||||
#
|
||||
# pylint: disable=line-too-long
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import zipfile
|
||||
from argparse import ArgumentParser
|
||||
from pathlib import Path
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
project_root_dir = Path(__file__).resolve().parent.parent
|
||||
dependencies_dir = project_root_dir / '.dependencies'
|
||||
|
||||
# All dependencies of this project.
|
||||
#
|
||||
# yapf: disable
|
||||
dependencies = {
|
||||
'ninja': {
|
||||
'version': '1.9.0',
|
||||
'url': {
|
||||
'Linux': 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip',
|
||||
'Windows': 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-win.zip',
|
||||
'Darwin': 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-mac.zip',
|
||||
},
|
||||
},
|
||||
'cmake': {
|
||||
'version': '3.15.5',
|
||||
'url': {
|
||||
'Linux': 'https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.15.5-Linux-x86_64.tar.gz',
|
||||
'Windows': 'https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.15.5-win64-x64.zip',
|
||||
'Darwin': 'https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.15.5-Darwin-x86_64.tar.gz',
|
||||
},
|
||||
},
|
||||
'avr8-gnu-toolchain': {
|
||||
'version': '5.4.0',
|
||||
'url': {
|
||||
'Linux': 'https://xxxarmkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2',
|
||||
'Windows': 'https://xxxarmkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-win32.zip',
|
||||
'Darwin': 'https://xxxarmkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-mac.tar.bz2',
|
||||
}
|
||||
},
|
||||
'clang-format': {
|
||||
'version': '9.0.0-noext',
|
||||
'url': {
|
||||
'Linux': 'https://prusa-buddy-firmware-dependencies.s3.eu-central-1.amazonaws.com/clang-format-9.0.0-linux.zip',
|
||||
'Windows': 'https://prusa-buddy-firmware-dependencies.s3.eu-central-1.amazonaws.com/clang-format-9.0.0-noext-win.zip',
|
||||
'Darwin': 'https://prusa-buddy-firmware-dependencies.s3.eu-central-1.amazonaws.com/clang-format-9.0.0-darwin.zip',
|
||||
}
|
||||
},
|
||||
}
|
||||
pip_dependencies = ['ecdsa', 'polib']
|
||||
# yapf: enable
|
||||
|
||||
|
||||
def directory_for_dependency(dependency, version):
|
||||
return dependencies_dir / (dependency + '-' + version)
|
||||
|
||||
|
||||
def find_single_subdir(path: Path):
|
||||
members = list(path.iterdir())
|
||||
if path.is_dir() and len(members) > 1:
|
||||
return path
|
||||
elif path.is_dir() and len(members) == 1:
|
||||
return find_single_subdir(members[0]) if members[0].is_dir() else path
|
||||
else:
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
def download_and_unzip(url: str, directory: Path):
|
||||
"""Download a compressed file and extract it at `directory`."""
|
||||
extract_dir = directory.with_suffix('.temp')
|
||||
shutil.rmtree(directory, ignore_errors=True)
|
||||
shutil.rmtree(extract_dir, ignore_errors=True)
|
||||
|
||||
print('Downloading ' + directory.name)
|
||||
f, _ = urlretrieve(url, filename=None)
|
||||
print('Extracting ' + directory.name)
|
||||
if '.tar.bz2' in url or '.tar.gz' in url or '.tar.xz' in url:
|
||||
obj = tarfile.open(f)
|
||||
else:
|
||||
obj = zipfile.ZipFile(f, 'r')
|
||||
obj.extractall(path=str(extract_dir))
|
||||
|
||||
subdir = find_single_subdir(extract_dir)
|
||||
shutil.move(str(subdir), str(directory))
|
||||
shutil.rmtree(extract_dir, ignore_errors=True)
|
||||
|
||||
|
||||
def run(*cmd):
|
||||
process = subprocess.run([str(a) for a in cmd],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
encoding='utf-8')
|
||||
return process.stdout.strip()
|
||||
|
||||
|
||||
def fix_executable_permissions(dependency, installation_directory):
|
||||
to_fix = ('ninja', 'clang-format')
|
||||
if dependency not in to_fix:
|
||||
return
|
||||
for fpath in installation_directory.iterdir():
|
||||
if fpath.is_file and fpath.with_suffix('').name in to_fix:
|
||||
st = os.stat(fpath)
|
||||
os.chmod(fpath, st.st_mode | stat.S_IEXEC)
|
||||
|
||||
|
||||
def recommended_version_is_available(dependency):
|
||||
version = dependencies[dependency]['version']
|
||||
directory = directory_for_dependency(dependency, version)
|
||||
return directory.exists() and directory.is_dir()
|
||||
|
||||
|
||||
def get_installed_pip_packages():
|
||||
result = run(sys.executable, '-m', 'pip', 'list',
|
||||
'--disable-pip-version-check', '--format', 'json')
|
||||
data = json.loads(result)
|
||||
return [(pkg['name'].lower(), pkg['version']) for pkg in data]
|
||||
|
||||
|
||||
def install_dependency(dependency):
|
||||
specs = dependencies[dependency]
|
||||
installation_directory = directory_for_dependency(dependency,
|
||||
specs['version'])
|
||||
url = specs['url']
|
||||
if isinstance(url, dict):
|
||||
url = url[platform.system()]
|
||||
download_and_unzip(url=url, directory=installation_directory)
|
||||
fix_executable_permissions(dependency, installation_directory)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = ArgumentParser()
|
||||
# yapf: disable
|
||||
parser.add_argument(
|
||||
'--print-dependency-version', type=str,
|
||||
help='Prints recommended version of given dependency and exits.')
|
||||
parser.add_argument(
|
||||
'--print-dependency-directory', type=str,
|
||||
help='Prints installation directory of given dependency and exits.')
|
||||
args = parser.parse_args(sys.argv[1:])
|
||||
# yapf: enable
|
||||
|
||||
if args.print_dependency_version:
|
||||
try:
|
||||
version = dependencies[args.print_dependency_version]['version']
|
||||
print(version)
|
||||
return 0
|
||||
except KeyError:
|
||||
print('Unknown dependency "%s"' % args.print_dependency_version)
|
||||
return 1
|
||||
|
||||
if args.print_dependency_directory:
|
||||
try:
|
||||
dependency = args.print_dependency_directory
|
||||
version = dependencies[dependency]['version']
|
||||
install_dir = directory_for_dependency(dependency, version)
|
||||
print(install_dir)
|
||||
return 0
|
||||
except KeyError:
|
||||
print('Unknown dependency "%s"' % args.print_dependency_directory)
|
||||
return 1
|
||||
|
||||
# if no argument present, check and install dependencies
|
||||
for dependency in dependencies:
|
||||
if recommended_version_is_available(dependency):
|
||||
continue
|
||||
install_dependency(dependency)
|
||||
|
||||
# also, install pip packages
|
||||
installed_pip_packages = get_installed_pip_packages()
|
||||
for package in pip_dependencies:
|
||||
is_installed = any(installed[0] == package
|
||||
for installed in installed_pip_packages)
|
||||
if is_installed:
|
||||
continue
|
||||
print('Installing Python package %s' % package)
|
||||
run(sys.executable, '-m', 'pip', 'install', package,
|
||||
'--disable-pip-version-check')
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -0,0 +1,441 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from abc import ABC, abstractmethod, abstractproperty
|
||||
from copy import deepcopy
|
||||
from enum import Enum
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
try:
|
||||
from tqdm import tqdm
|
||||
except ModuleNotFoundError:
|
||||
|
||||
def tqdm(iterable, *args, **kwargs):
|
||||
return iterable
|
||||
|
||||
if os.isatty(sys.stdout.fileno()) and random.randint(0, 10) <= 1:
|
||||
print('TIP: run `pip install -m tqdm` to get a nice progress bar')
|
||||
|
||||
project_root = Path(__file__).resolve().parent.parent
|
||||
dependencies_dir = project_root / '.dependencies'
|
||||
|
||||
|
||||
def bootstrap(*args, interactive=False, check=False):
|
||||
"""Run the bootstrap script."""
|
||||
bootstrap_py = project_root / 'utils' / 'bootstrap.py'
|
||||
result = subprocess.run([sys.executable, str(bootstrap_py)] + list(args),
|
||||
check=False,
|
||||
encoding='utf-8',
|
||||
stdout=None if interactive else subprocess.PIPE,
|
||||
stderr=None if interactive else subprocess.PIPE)
|
||||
return result
|
||||
|
||||
|
||||
def project_version():
|
||||
"""Return current project version (e. g. "4.0.3")"""
|
||||
with open(project_root / 'version.txt', 'r') as f:
|
||||
return f.read().strip()
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def get_dependency(name):
|
||||
install_dir = Path(
|
||||
bootstrap('--print-dependency-directory', name,
|
||||
check=True).stdout.strip())
|
||||
suffix = '.exe' if platform.system() == 'Windows' else ''
|
||||
if name == 'ninja':
|
||||
return install_dir / ('ninja' + suffix)
|
||||
elif name == 'cmake':
|
||||
return install_dir / 'bin' / ('cmake' + suffix)
|
||||
else:
|
||||
return install_dir
|
||||
|
||||
|
||||
class Printer(Enum):
|
||||
"""Represents the -DPRINTER CMake option."""
|
||||
|
||||
MMU = 'MMU'
|
||||
|
||||
|
||||
#class Bootloader(Enum):
|
||||
# """Represents the -DBOOTLOADER CMake option."""
|
||||
#
|
||||
# NO = 'NO'
|
||||
# EMPTY = 'EMPTY'
|
||||
# YES = 'YES'
|
||||
#
|
||||
# @property
|
||||
# def file_component(self):
|
||||
# if self == Bootloader.NO:
|
||||
# return 'NOBOOT'
|
||||
# elif self == Bootloader.EMPTY:
|
||||
# return 'EMPTYBOOT'
|
||||
# elif self == Bootloader.YES:
|
||||
# return 'BOOT'
|
||||
# else:
|
||||
# raise NotImplementedError
|
||||
|
||||
|
||||
class BuildType(Enum):
|
||||
"""Represents the -DCONFIG CMake option."""
|
||||
|
||||
DEBUG = 'DEBUG'
|
||||
RELEASE = 'RELEASE'
|
||||
|
||||
|
||||
#class HostTool(Enum):
|
||||
# """Known host tools."""
|
||||
#
|
||||
# png2font = "png2font"
|
||||
# bin2cc = "bin2cc"
|
||||
# hex2dfu = "hex2dfu"
|
||||
# makefsdata = "makefsdata"
|
||||
|
||||
|
||||
class BuildConfiguration(ABC):
|
||||
@abstractmethod
|
||||
def get_cmake_cache_entries(self):
|
||||
"""Convert the build configuration to CMake cache entries."""
|
||||
|
||||
@abstractmethod
|
||||
def get_cmake_flags(self, build_dir: Path) -> List[str]:
|
||||
"""Return all CMake command-line flags required to build this configuration."""
|
||||
|
||||
@abstractproperty
|
||||
def name(self):
|
||||
"""Name of the configuration."""
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
|
||||
class FirmwareBuildConfiguration(BuildConfiguration):
|
||||
def __init__(self,
|
||||
printer: Printer,
|
||||
build_type: BuildType,
|
||||
toolchain: Path = None,
|
||||
generator: str = None,
|
||||
version_suffix: str = None,
|
||||
version_suffix_short: str = None,
|
||||
custom_entries: List[str] = None):
|
||||
self.printer = printer
|
||||
self.build_type = build_type
|
||||
self.toolchain = toolchain or FirmwareBuildConfiguration.default_toolchain(
|
||||
)
|
||||
self.generator = generator
|
||||
self.version_suffix = version_suffix
|
||||
self.version_suffix_short = version_suffix_short
|
||||
self.custom_entries = custom_entries or []
|
||||
|
||||
@staticmethod
|
||||
def default_toolchain() -> Path:
|
||||
return Path(
|
||||
__file__).resolve().parent.parent / 'cmake/GccArmNoneEabi.cmake'
|
||||
|
||||
def get_cmake_cache_entries(self):
|
||||
entries = []
|
||||
if self.generator.lower() == 'ninja':
|
||||
entries.append(('CMAKE_MAKE_PROGRAM', 'FILEPATH',
|
||||
str(get_dependency('ninja'))))
|
||||
entries.extend([
|
||||
('CMAKE_MAKE_PROGRAM', 'FILEPATH', str(get_dependency('ninja'))),
|
||||
('PRINTER', 'STRING', self.printer.value),
|
||||
('CMAKE_TOOLCHAIN_FILE', 'FILEPATH', str(self.toolchain)),
|
||||
('CMAKE_BUILD_TYPE', 'STRING', self.build_type.value.title()),
|
||||
('PROJECT_VERSION_SUFFIX', 'STRING', self.version_suffix or ''),
|
||||
('PROJECT_VERSION_SUFFIX_SHORT', 'STRING',
|
||||
self.version_suffix_short or ''),
|
||||
])
|
||||
entries.extend(self.custom_entries)
|
||||
return entries
|
||||
|
||||
def get_cmake_flags(self, build_dir: Path) -> List[str]:
|
||||
cache_entries = self.get_cmake_cache_entries()
|
||||
flags = ['-D{}:{}={}'.format(*entry) for entry in cache_entries]
|
||||
flags += ['-G', self.generator or 'Ninja']
|
||||
flags += ['-S', str(Path(__file__).resolve().parent.parent)]
|
||||
flags += ['-B', str(build_dir)]
|
||||
return flags
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
components = [
|
||||
self.printer.name,
|
||||
self.build_type.value,
|
||||
]
|
||||
return '_'.join(components)
|
||||
|
||||
|
||||
class BuildResult:
|
||||
"""Represents a result of an attempt to build the project."""
|
||||
|
||||
def __init__(self, config_returncode: int, build_returncode: Optional[int],
|
||||
stdout: Path, stderr: Path, products: List[Path]):
|
||||
self.config_returncode = config_returncode
|
||||
self.build_returncode = build_returncode
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.products = products
|
||||
|
||||
@property
|
||||
def configuration_failed(self):
|
||||
return self.config_returncode != 0
|
||||
|
||||
@property
|
||||
def build_failed(self):
|
||||
return self.build_returncode != 0 and self.build_returncode is not None
|
||||
|
||||
@property
|
||||
def is_failure(self):
|
||||
return self.configuration_failed or self.build_failed
|
||||
|
||||
def __str__(self):
|
||||
return '<BuildResult config={self.config_returncode} build={self.build_returncode}>'.format(
|
||||
self=self)
|
||||
|
||||
|
||||
def build(configuration: BuildConfiguration,
|
||||
build_dir: Path,
|
||||
configure_only=False,
|
||||
output_to_file=True) -> BuildResult:
|
||||
"""Build a project with a single configuration."""
|
||||
flags = configuration.get_cmake_flags(build_dir=build_dir)
|
||||
|
||||
# create the build directory
|
||||
build_dir.mkdir(parents=True, exist_ok=True)
|
||||
products = []
|
||||
|
||||
if output_to_file:
|
||||
# stdout and stderr are saved to a file in the build directory
|
||||
stdout_path = build_dir / 'stdout.txt'
|
||||
stderr_path = build_dir / 'stderr.txt'
|
||||
stdout = open(stdout_path, 'w')
|
||||
stderr = open(stderr_path, 'w')
|
||||
else:
|
||||
stdout_path, stderr_path = None, None
|
||||
stdout, stderr = None, None
|
||||
|
||||
# prepare the build
|
||||
config_process = subprocess.run([str(get_dependency('cmake'))] + flags,
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
check=False)
|
||||
if not configure_only and config_process.returncode == 0:
|
||||
cmd = [
|
||||
str(get_dependency('cmake')), '--build',
|
||||
str(build_dir), '--config',
|
||||
configuration.build_type.value.lower()
|
||||
]
|
||||
build_process = subprocess.run(cmd,
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
check=False)
|
||||
build_returncode = build_process.returncode
|
||||
products.extend(build_dir / fname for fname in [
|
||||
'firmware', 'firmware.bin', 'firmware.bbf', 'firmware.dfu',
|
||||
'firmware.map'
|
||||
] if (build_dir / fname).exists())
|
||||
else:
|
||||
build_returncode = None
|
||||
|
||||
if stdout:
|
||||
stdout.close()
|
||||
if stderr:
|
||||
stderr.close()
|
||||
|
||||
# collect the result and return
|
||||
return BuildResult(config_returncode=config_process.returncode,
|
||||
build_returncode=build_returncode,
|
||||
stdout=stdout_path,
|
||||
stderr=stderr_path,
|
||||
products=products)
|
||||
|
||||
|
||||
def store_products(products: List[Path], build_config: BuildConfiguration,
|
||||
products_dir: Path):
|
||||
"""Copy build products to a shared products directory."""
|
||||
products_dir.mkdir(parents=True, exist_ok=True)
|
||||
for product in products:
|
||||
is_firmware = isinstance(build_config, FirmwareBuildConfiguration)
|
||||
has_custom_suffix = is_firmware and (build_config.version_suffix !=
|
||||
'<auto>')
|
||||
if has_custom_suffix:
|
||||
version = project_version()
|
||||
name = build_config.name.lower(
|
||||
) + '_' + version + build_config.version_suffix
|
||||
else:
|
||||
name = build_config.name.lower()
|
||||
destination = products_dir / (name + product.suffix)
|
||||
shutil.copy(product, destination)
|
||||
|
||||
|
||||
def list_of(EnumType):
|
||||
"""Create an argument-parser for comma-separated list of values of some Enum subclass."""
|
||||
|
||||
def convert(val):
|
||||
if val == '':
|
||||
return []
|
||||
values = [p.lower() for p in val.split(',')]
|
||||
if 'all' in values:
|
||||
return list(EnumType)
|
||||
else:
|
||||
return [EnumType(v.upper()) for v in values]
|
||||
|
||||
convert.__name__ = EnumType.__name__
|
||||
return convert
|
||||
|
||||
|
||||
def cmake_cache_entry(arg):
|
||||
match = re.fullmatch(r'(.*):(.*)=(.*)', arg)
|
||||
if not match:
|
||||
raise ValueError('invalid cmake entry; must be <NAME>:<TYPE>=<VALUE>')
|
||||
return (match.group(1), match.group(2), match.group(3))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
# yapf: disable
|
||||
parser.add_argument(
|
||||
'--printer',
|
||||
type=list_of(Printer),
|
||||
default=list(Printer),
|
||||
help='Printer type (default: {default}).'.format(
|
||||
default=','.join(str(p.value.lower()) for p in Printer)))
|
||||
parser.add_argument(
|
||||
'--build-type',
|
||||
type=list_of(BuildType),
|
||||
default='release',
|
||||
help=('Build type (debug or release; default: release; '
|
||||
'default for --generate-cproject: debug,release).'))
|
||||
parser.add_argument(
|
||||
'--version-suffix',
|
||||
type=str,
|
||||
default='<auto>',
|
||||
help='Version suffix (e.g. -BETA+1035.PR111.B4)')
|
||||
parser.add_argument(
|
||||
'--version-suffix-short',
|
||||
type=str,
|
||||
default='<auto>',
|
||||
help='Version suffix (e.g. +1035)')
|
||||
parser.add_argument(
|
||||
'--final',
|
||||
action='store_true',
|
||||
help='Set\'s --version-suffix and --version-suffix-short to empty string.')
|
||||
parser.add_argument(
|
||||
'--build-dir',
|
||||
type=Path,
|
||||
help='Specify a custom build directory to be used.')
|
||||
parser.add_argument(
|
||||
'--products-dir',
|
||||
type=Path,
|
||||
help='Directory to store built firmware (default: <build-dir>/products).')
|
||||
parser.add_argument(
|
||||
'-G', '--generator',
|
||||
type=str,
|
||||
default='Ninja',
|
||||
help='Generator to be used by CMake (default=Ninja).')
|
||||
parser.add_argument(
|
||||
'--toolchain',
|
||||
type=Path,
|
||||
help='Path to a CMake toolchain file to be used.')
|
||||
parser.add_argument(
|
||||
'--host-tools',
|
||||
action='store_true',
|
||||
help=('Build host tools (png2font and others). '
|
||||
'Turned on by default with --generate-cproject only.')
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-build',
|
||||
action='store_true',
|
||||
help='Do not build, configure the build only.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-store-output',
|
||||
action='store_false',
|
||||
help='Do not write build output to files - print it to console instead.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-D', '--cmake-def',
|
||||
action='append', type=cmake_cache_entry,
|
||||
help='Custom CMake cache entries (e.g. -DCUSTOM_COMPILE_OPTIONS:STRING=-Werror)'
|
||||
)
|
||||
args = parser.parse_args(sys.argv[1:])
|
||||
# yapf: enable
|
||||
|
||||
build_dir_root = args.build_dir or Path(
|
||||
__file__).resolve().parent.parent / 'build'
|
||||
products_dir_root = args.products_dir or (build_dir_root / 'products')
|
||||
|
||||
if args.final:
|
||||
args.version_suffix = ''
|
||||
args.version_suffix_short = ''
|
||||
|
||||
# Check all dependencis are installed
|
||||
if bootstrap(interactive=True).returncode != 0:
|
||||
print('bootstrap.py failed.')
|
||||
sys.exit(1)
|
||||
|
||||
# prepare configurations
|
||||
configurations = [
|
||||
FirmwareBuildConfiguration(
|
||||
printer=printer,
|
||||
build_type=build_type,
|
||||
version_suffix=args.version_suffix,
|
||||
version_suffix_short=args.version_suffix_short,
|
||||
generator=args.generator,
|
||||
custom_entries=args.cmake_def) for printer in args.printer
|
||||
for build_type in args.build_type
|
||||
]
|
||||
|
||||
# build everything
|
||||
configurations_iter = tqdm(configurations)
|
||||
results: Dict[BuildConfiguration, BuildResult] = dict()
|
||||
for configuration in configurations_iter:
|
||||
build_dir = build_dir_root / configuration.name.lower()
|
||||
description = 'Building ' + configuration.name.lower()
|
||||
if hasattr(configurations_iter, 'set_description'):
|
||||
configurations_iter.set_description(description)
|
||||
else:
|
||||
print(description)
|
||||
result = build(configuration,
|
||||
build_dir=build_dir,
|
||||
configure_only=args.no_build,
|
||||
output_to_file=args.no_store_output is not False)
|
||||
store_products(result.products, configuration, products_dir_root)
|
||||
results[configuration] = result
|
||||
|
||||
# print results
|
||||
print()
|
||||
print('Building finished: {} success, {} failure(s).'.format(
|
||||
sum(1 for result in results.values() if not result.is_failure),
|
||||
sum(1 for result in results.values() if result.is_failure)))
|
||||
failure = False
|
||||
max_configname_len = max(len(config.name) for config in results)
|
||||
for config, result in results.items():
|
||||
if result.configuration_failed:
|
||||
status = 'project configuration FAILED'
|
||||
failure = True
|
||||
elif result.build_failed:
|
||||
status = 'build FAILED'
|
||||
failure = True
|
||||
else:
|
||||
status = 'SUCCESS'
|
||||
|
||||
print(' {} {}'.format(
|
||||
config.name.lower().ljust(max_configname_len, ' '), status))
|
||||
if failure:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1 @@
|
|||
2.0.0
|
||||
Loading…
Reference in New Issue