WIP/proof-of-concept
This commit is contained in:
parent
8e72470afc
commit
f03e3c40ee
|
|
@ -2,7 +2,8 @@
|
||||||
/.settings
|
/.settings
|
||||||
/.project
|
/.project
|
||||||
/.cproject
|
/.cproject
|
||||||
/.vscode
|
|
||||||
|
/build/
|
||||||
|
|
||||||
# Temporary configuration
|
# Temporary configuration
|
||||||
/Firmware/Configuration_prusa.h
|
/Firmware/Configuration_prusa.h
|
||||||
|
|
@ -23,3 +24,4 @@ __pycache__
|
||||||
# Generated files
|
# Generated files
|
||||||
/build-env/
|
/build-env/
|
||||||
/Firmware/Doc/
|
/Firmware/Doc/
|
||||||
|
compile_commands.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Local_gcc-avr-none-eabi",
|
||||||
|
"toolchainFile": "${workspaceFolder}/cmake/LocalAvrGcc.cmake",
|
||||||
|
"cmakeSettings": {
|
||||||
|
"CMAKE_MAKE_PROGRAM": "${workspaceFolder}/.dependencies/ninja-1.9.0/ninja"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
buildType:
|
||||||
|
default: debug
|
||||||
|
choices:
|
||||||
|
debug:
|
||||||
|
short: Debug
|
||||||
|
long: Emit debug information
|
||||||
|
buildType: Debug
|
||||||
|
release:
|
||||||
|
short: Release
|
||||||
|
long: Optimize generated code
|
||||||
|
buildType: Release
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json",
|
||||||
|
"cmake.cmakePath": "${workspaceFolder}/.dependencies/cmake-3.22.5/bin/cmake",
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
"files.associations": {
|
||||||
|
"xlocale": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
209
CMakeLists.txt
209
CMakeLists.txt
|
|
@ -1,7 +1,212 @@
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
include(cmake/Utilities.cmake)
|
||||||
|
|
||||||
set (CMAKE_CXX_STANDARD 11)
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
project(Prusa-Firmware)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
# append custom C/C++ flags
|
||||||
|
if(CUSTOM_COMPILE_OPTIONS)
|
||||||
|
string(REPLACE " " ";" CUSTOM_COMPILE_OPTIONS "${CUSTOM_COMPILE_OPTIONS}")
|
||||||
|
add_compile_options(${CUSTOM_COMPILE_OPTIONS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Global Compiler & Linker Configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
# include symbols
|
||||||
|
add_compile_options(-g)
|
||||||
|
|
||||||
|
# optimizations
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
add_compile_options(-Og)
|
||||||
|
else()
|
||||||
|
add_compile_options(-Os)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# mcu related settings
|
||||||
|
set(MCU_FLAGS -mmcu=atmega2560 -DF_CPU=16000000L)
|
||||||
|
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_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
|
||||||
|
add_link_options(-Wl,--defsym,__exidx_start=0,--defsym,__exidx_end=0)
|
||||||
|
else()
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
add_compile_options(-O0)
|
||||||
|
else()
|
||||||
|
add_compile_options(-O2)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# enable all warnings (well, not all, but some)
|
||||||
|
add_compile_options(-Wall -Wsign-compare)
|
||||||
|
add_compile_options($<$<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()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Firmware - get file lists.
|
||||||
|
#
|
||||||
|
file(GLOB FW_SOURCES RELATIVE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/Firmware/*.c*)
|
||||||
|
file(GLOB FW_HEADERS RELATIVE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/Firmware/*.h*)
|
||||||
|
file(GLOB AVR_SOURCES RELATIVE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/cores/prusa_einsy_rambo/*.c*)
|
||||||
|
|
||||||
|
# Setup language resources:
|
||||||
|
file(GLOB LANG_VARIANTS RELATIVE ${PROJECT_SOURCE_DIR}/lang/po ${PROJECT_SOURCE_DIR}/lang/po/Firmware_??.po)
|
||||||
|
string(REPLACE "Firmware_" "" LANG_VARIANTS "${LANG_VARIANTS}")
|
||||||
|
string(REPLACE ".po" "" LANG_VARIANTS "${LANG_VARIANTS}")
|
||||||
|
message("Languages found: ${LANG_VARIANTS}")
|
||||||
|
|
||||||
|
add_library(avr_core STATIC ${AVR_SOURCES})
|
||||||
|
target_include_directories(avr_core PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/cores/prusa_einsy_rambo/
|
||||||
|
${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/variants/prusa_einsy_rambo/
|
||||||
|
)
|
||||||
|
target_compile_options(avr_core PUBLIC -mmcu=atmega2560)
|
||||||
|
|
||||||
|
function(fw_add_variant variant_name)
|
||||||
|
|
||||||
|
add_executable(${variant_name} ${FW_SOURCES} ${FW_HEADERS})
|
||||||
|
|
||||||
|
set_target_properties(${variant_name} PROPERTIES CXX_STANDARD 14)
|
||||||
|
|
||||||
|
|
||||||
|
# # configure linker script
|
||||||
|
set(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/ldscripts/avr6.xn)
|
||||||
|
target_link_options(${variant_name} PUBLIC -Wl,-T,${LINKER_SCRIPT})
|
||||||
|
add_link_dependency(${variant_name} ${LINKER_SCRIPT})
|
||||||
|
|
||||||
|
|
||||||
|
# limit the text section to 248K (256K - 8k reserved for the bootloader)
|
||||||
|
target_link_options(${variant_name} PUBLIC -Wl,--defsym=__TEXT_REGION_LENGTH__=248K)
|
||||||
|
|
||||||
|
# generate firmware.bin file
|
||||||
|
objcopy(${variant_name} "ihex" ".hex")
|
||||||
|
|
||||||
|
# produce ASM listing. Note we also specify the .map as a byproduct so it gets cleaned
|
||||||
|
# because link_options doesn't have a "generated outputs" feature.
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${variant_name} POST_BUILD COMMAND ${CMAKE_OBJDUMP} -CSd ${variant_name} > ${variant_name}.asm
|
||||||
|
BYPRODUCTS ${variant_name}.asm ${variant_name}.map
|
||||||
|
)
|
||||||
|
|
||||||
|
# inform about the firmware's size in terminal
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${variant_name} POST_BUILD COMMAND ${CMAKE_SIZE_UTIL} -C --mcu=atmega2560 ${variant_name}
|
||||||
|
)
|
||||||
|
report_size(${variant_name})
|
||||||
|
|
||||||
|
# generate linker map file
|
||||||
|
target_link_options(${variant_name} PUBLIC -Wl,-Map=${variant_name}.map)
|
||||||
|
|
||||||
|
|
||||||
|
target_include_directories(${variant_name} PRIVATE Firmware
|
||||||
|
${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/cores/prusa_einsy_rambo/
|
||||||
|
${PROJECT_SOURCE_DIR}/.dependencies/1.8.19-1.0.5-1-linux-64/portable/packages/PrusaResearch/hardware/avr/1.0.5-1/variants/prusa_einsy_rambo/
|
||||||
|
${PROJECT_SOURCE_DIR}/cmake/helpers/ # Add our magic config helper :)
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(${variant_name} PRIVATE) # turn this on for lolz -Wdouble-promotion)
|
||||||
|
string(REPLACE "-" "_" DEFINE_NAME "${variant_name}")
|
||||||
|
target_compile_definitions(${variant_name} PRIVATE H${DEFINE_NAME} ARDUINO=10600 __AVR_ATmega2560__)
|
||||||
|
target_link_libraries(${variant_name} avr_core)
|
||||||
|
|
||||||
|
#Construct language map
|
||||||
|
set(LANG_MAP ${CMAKE_CURRENT_BINARY_DIR}/lang/${variant_name}_lang.map)
|
||||||
|
set(LANG_FWBIN ${CMAKE_BINARY_DIR}/${variant_name}.bin)
|
||||||
|
set(LANG_FINAL_BIN ${CMAKE_CURRENT_BINARY_DIR}/lang/${variant_name}_lang.bin)
|
||||||
|
set(LANG_FINAL_HEX ${CMAKE_CURRENT_BINARY_DIR}/lang/${variant_name}_lang.hex)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${LANG_FWBIN}
|
||||||
|
COMMAND "${CMAKE_OBJCOPY}" -I ihex -O binary ${CMAKE_BINARY_DIR}/${variant_name}.hex ${LANG_FWBIN}
|
||||||
|
DEPENDS ${variant_name}
|
||||||
|
)
|
||||||
|
add_custom_command(OUTPUT ${LANG_MAP}
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lang/lang-map.py "${CMAKE_BINARY_DIR}/${variant_name}" "${LANG_FWBIN}" > "${LANG_MAP}"
|
||||||
|
DEPENDS ${LANG_FWBIN}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LANG_BINS "")
|
||||||
|
foreach (LANG IN LISTS LANG_VARIANTS)
|
||||||
|
set(LANG_BIN ${CMAKE_CURRENT_BINARY_DIR}/lang/${variant_name}_${LANG}.bin)
|
||||||
|
|
||||||
|
set(PO_FILE "${CMAKE_CURRENT_SOURCE_DIR}/lang/po/Firmware_${LANG}.po")
|
||||||
|
add_custom_command(OUTPUT ${LANG_BIN}
|
||||||
|
# COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lang/lang-check.py --no-warning --map "${LANG_MAP}" "${PO_FILE}"
|
||||||
|
# COMMAND ${CMAKE_COMMAND} -E echo "Building lang_${LANG}.bin"
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lang/lang-build.py ${LANG_MAP} ${PO_FILE} ${LANG_BIN}
|
||||||
|
DEPENDS ${LANG_MAP}
|
||||||
|
COMMENT "Generating ${variant_name}_${LANG}.bin from .po"
|
||||||
|
)
|
||||||
|
LIST(APPEND LANG_BINS ${LANG_BIN})
|
||||||
|
endforeach()
|
||||||
|
add_custom_command( OUTPUT ${LANG_FINAL_BIN}
|
||||||
|
# TODO - needs differentiation for platforms, e.g. copy /b on Win
|
||||||
|
COMMAND cat ${LANG_BINS} > ${LANG_FINAL_BIN}
|
||||||
|
DEPENDS ${LANG_BINS}
|
||||||
|
COMMENT "Merging language binaries"
|
||||||
|
)
|
||||||
|
add_custom_command( OUTPUT ${LANG_FINAL_HEX}
|
||||||
|
# TODO - needs differentiation for platforms, e.g. copy /b on Win
|
||||||
|
COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${LANG_FINAL_BIN} ${LANG_FINAL_HEX}
|
||||||
|
DEPENDS ${LANG_FINAL_BIN}
|
||||||
|
COMMENT "Generating Hex for language data"
|
||||||
|
)
|
||||||
|
set(LANG_HEX ${CMAKE_BINARY_DIR}/${variant_name}-lang.hex)
|
||||||
|
add_custom_target(${variant_name}-languages
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${variant_name}.hex ${LANG_HEX}
|
||||||
|
COMMAND cat ${LANG_FINAL_HEX} >> ${LANG_HEX}
|
||||||
|
COMMENT "Generating final ${variant_name}-lang.hex"
|
||||||
|
BYPRODUCTS ${LANG_HEX}
|
||||||
|
DEPENDS ${LANG_FINAL_HEX}
|
||||||
|
)
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
|
||||||
|
add_custom_target(All_Firmware)
|
||||||
|
|
||||||
|
file(GLOB FW_VARIANTS RELATIVE ${PROJECT_SOURCE_DIR}/Firmware/variants ${PROJECT_SOURCE_DIR}/Firmware/variants/*.h)
|
||||||
|
foreach(THIS_VAR IN LISTS FW_VARIANTS)
|
||||||
|
string(REPLACE ".h" "" TRIMMED_NAME "${THIS_VAR}")
|
||||||
|
message("Variant added: ${TRIMMED_NAME}")
|
||||||
|
fw_add_variant(${TRIMMED_NAME})
|
||||||
|
add_dependencies(All_Firmware ${TRIMMED_NAME})
|
||||||
|
|
||||||
|
endforeach(THIS_VAR IN LISTS FW_VARIANTS)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
|
# do not build the firmware by default (tests are the focus if not crosscompiling)
|
||||||
project(cmake_test)
|
project(cmake_test)
|
||||||
|
|
||||||
# Prepare "Catch" library for other executables
|
# Prepare "Catch" library for other executables
|
||||||
|
|
@ -22,3 +227,5 @@ set(TEST_SOURCES
|
||||||
add_executable(tests ${TEST_SOURCES})
|
add_executable(tests ${TEST_SOURCES})
|
||||||
target_include_directories(tests PRIVATE Tests)
|
target_include_directories(tests PRIVATE Tests)
|
||||||
target_link_libraries(tests Catch)
|
target_link_libraries(tests Catch)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
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 avr)
|
||||||
|
set(CMAKE_CROSSCOMPILING 1)
|
||||||
|
|
||||||
|
set(AVR_TOOLCHAIN_DIR "${PROJECT_CMAKE_DIR}/../.dependencies/1.8.19-1.0.5-1-linux-64/hardware/tools/avr/")
|
||||||
|
message( "tc dir is ${AVR_TOOLCHAIN_DIR}")
|
||||||
|
#
|
||||||
|
# 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 avr-)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Looking up the toolchain
|
||||||
|
#
|
||||||
|
|
||||||
|
if(AVR_TOOLCHAIN_DIR)
|
||||||
|
# using toolchain set by AvrGcc.cmake (locked version)
|
||||||
|
set(BINUTILS_PATH "${AVR_TOOLCHAIN_DIR}/bin")
|
||||||
|
else()
|
||||||
|
# search for ANY avr-gcc toolchain
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${UTIL_SEARCH_CMD} ${TOOLCHAIN_PREFIX}gcc
|
||||||
|
OUTPUT_VARIABLE AVR_GCC_PATH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
RESULT_VARIABLE FIND_RESULT
|
||||||
|
)
|
||||||
|
# found?
|
||||||
|
if(NOT "${FIND_RESULT}" STREQUAL "0")
|
||||||
|
message(FATAL_ERROR "avr-gcc not found")
|
||||||
|
endif()
|
||||||
|
get_filename_component(BINUTILS_PATH "${AVR_GCC_PATH}" DIRECTORY)
|
||||||
|
get_filename_component(AVR_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(CMAKE_C_COMPILER
|
||||||
|
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}gcc${EXECUTABLE_SUFFIX}"
|
||||||
|
CACHE FILEPATH "" FORCE
|
||||||
|
)
|
||||||
|
set(CMAKE_ASM_COMPILER
|
||||||
|
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}gcc${EXECUTABLE_SUFFIX}"
|
||||||
|
CACHE FILEPATH "" FORCE
|
||||||
|
)
|
||||||
|
set(CMAKE_CXX_COMPILER
|
||||||
|
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}g++${EXECUTABLE_SUFFIX}"
|
||||||
|
CACHE FILEPATH "" FORCE
|
||||||
|
)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_INIT
|
||||||
|
""
|
||||||
|
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_OBJDUMP
|
||||||
|
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}objdump${EXECUTABLE_SUFFIX}"
|
||||||
|
CACHE INTERNAL "objdump tool"
|
||||||
|
)
|
||||||
|
set(CMAKE_SIZE_UTIL
|
||||||
|
"${BINUTILS_PATH}/${TOOLCHAIN_PREFIX}size${EXECUTABLE_SUFFIX}"
|
||||||
|
CACHE INTERNAL "size tool"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_FIND_ROOT_PATH "${AVR_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,64 @@
|
||||||
|
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-avr"
|
||||||
|
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}..."
|
||||||
|
BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/${target}${suffix}"
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifdef H1_75mm_MK25_RAMBo10a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK25_RAMBo13a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK25S_RAMBo10a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK25S_RAMBo13a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK2_RAMBo10a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK2_RAMBo13a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK3_EINSy10a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK3-EINSy10a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
#ifdef H1_75mm_MK3S_EINSy10a_E3Dv6full
|
||||||
|
#include "variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h"
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
#!/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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'gcc-avr': {
|
||||||
|
# dummy placeholder (currently downloading cmake just for the sake of a valid url/zip archive)
|
||||||
|
# ... we truly need the binaries! :)
|
||||||
|
'version': '0.0.0',
|
||||||
|
'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',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pip_dependencies = []
|
||||||
|
# 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())
|
||||||
Loading…
Reference in New Issue