diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f20309e19..54679be438 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,15 @@ cmake_minimum_required(VERSION 3.17) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +set(MAIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(MAIN_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib") +set(MAIN_UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/utils") +set(MAIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/main") +set(SVD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dev/svd") +set(DOWNLOADS_DIR "${MAIN_DIR}/downloads") +set(TOOLS_DIR "${MAIN_DIR}/tools") + set(TOOLCHAIN_OPTIONS none arm-none-eabi) set(TOOLCHAIN "arm-none-eabi" CACHE STRING "Toolchain to use. Available: ${TOOLCHAIN_OPTIONS}") set_property(CACHE TOOLCHAIN PROPERTY STRINGS ${TOOLCHAIN_OPTIONS}) @@ -14,6 +24,7 @@ if(TOOLCHAIN STREQUAL none) add_subdirectory(src/test) else() set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}.cmake") + include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}-checks.cmake") endif() if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") @@ -37,13 +48,6 @@ if (NOT RUBY_EXECUTABLE) endif() -set(MAIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}") -set(MAIN_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib") -set(MAIN_UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/utils") -set(MAIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/main") -set(SVD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dev/svd") - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC GIT_SHA1) diff --git a/cmake/arm-none-eabi-checks.cmake b/cmake/arm-none-eabi-checks.cmake new file mode 100644 index 0000000000..2faf08bc00 --- /dev/null +++ b/cmake/arm-none-eabi-checks.cmake @@ -0,0 +1,110 @@ +include(gcc) +set(arm_none_eabi_triplet "arm-none-eabi") + +# Keep version in sync with the distribution files below +set(arm_none_eabi_gcc_version "9.2.1") +set(arm_none_eabi_base_url "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/gcc-arm-none-eabi-9-2019-q4-major") +# suffix and sha1 +set(arm_none_eabi_win32 "win32.zip" 60f364ecf2e8717a58d352db95b388eee508b727) +set(arm_none_eabi_linux_amd64 "x86_64-linux.tar.bz2" 3829ff61b2601c6cf061a5a275c2538a96a8d521) +set(arm_none_eabi_linux_aarch64 "aarch64-linux.tar.bz2" fdb6fe7058927ad897f63d2d245f825a9587a1c5) +set(arm_none_eabi_gcc_macos "mac.tar.bz2" 26fe33e0c25d9a2947c0373ea48c00ef46eacd58) + +function(arm_none_eabi_gcc_distname var) + string(REPLACE "/" ";" url_parts ${arm_none_eabi_base_url}) + list(LENGTH url_parts n) + math(EXPR last "${n} - 1") + list(GET url_parts ${last} basename) + set(${var} ${basename} PARENT_SCOPE) +endfunction() + +function(host_uname_machine var) + # We need to call uname -m manually, since at the point + # this file is included CMAKE_HOST_SYSTEM_PROCESSOR is + # empty because we haven't called project() yet. + execute_process(COMMAND uname -m + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE machine) + + set(${var} ${machine} PARENT_SCOPE) +endfunction() + +function(arm_none_eabi_gcc_install) + set(dist "") + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(dist ${arm_none_eabi_win32}) + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + host_uname_machine(machine) + if(machine STREQUAL "x86_64") + set(dist ${arm_none_eabi_linux_amd64}) + elseif(machine STREQUAL "aarch64") + set(dist ${arm_none_eabi_linux_aarch64}) + else() + message("-- no precompiled ${arm_none_eabi_triplet} toolchain for machine ${machine}") + endif() + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(dist ${arm_none_eabi_gcc_macos}) + endif() + + if(dist STREQUAL "") + message(FATAL_ERROR "could not install ${arm_none_eabi_triplet}-gcc automatically") + endif() + list(GET dist 0 dist_suffix) + list(GET dist 1 dist_sha1) + set(dist_url "${arm_none_eabi_base_url}-${dist_suffix}") + string(REPLACE "/" ";" url_parts ${dist_url}) + list(LENGTH url_parts n) + math(EXPR last "${n} - 1") + list(GET url_parts ${last} basename) + set(output "${DOWNLOADS_DIR}/${basename}") + message("-- downloading ${arm_none_eabi_triplet}-gcc ${arm_none_eabi_gcc_version} from ${dist_url}") + file(DOWNLOAD ${dist_url} ${output} + INACTIVITY_TIMEOUT 30 + STATUS status + SHOW_PROGRESS + EXPECTED_HASH SHA1=${dist_sha1} + TLS_VERIFY ON + ) + list(GET status 0 status_code) + if(NOT status_code EQUAL 0) + list(GET status 1 status_message) + message(FATAL_ERROR "error downloading ${basename}: ${status_message}") + endif() + message("-- extracting ${basename}") + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TOOLS_DIR}) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${output} + RESULT_VARIABLE status + WORKING_DIRECTORY ${TOOLS_DIR} + ) + if(NOT status EQUAL 0) + message(FATAL_ERROR "error extracting ${basename}: ${status}") + endif() +endfunction() + +function(arm_none_eabi_gcc_add_path) + arm_none_eabi_gcc_distname(dist_name) + set(gcc_path "${TOOLS_DIR}/${dist_name}/bin") + set(ENV{PATH} "$ENV{PATH}:${gcc_path}") +endfunction() + +function(arm_none_eabi_gcc_check) + gcc_get_version(version + TRIPLET ${arm_none_eabi_triplet} + PROGRAM_NAME prog + PROGRAM_PATH prog_path + ) + if(NOT version) + message("-- could not find ${prog}") + arm_none_eabi_gcc_install() + return() + endif() + message("-- found ${prog} ${version} at ${prog_path}") + if(NOT arm_none_eabi_gcc_version STREQUAL version) + message("-- expecting ${prog} version ${arm_none_eabi_gcc_version}, but got version ${version} instead") + arm_none_eabi_gcc_install() + return() + endif() +endfunction() + +arm_none_eabi_gcc_add_path() +arm_none_eabi_gcc_check() \ No newline at end of file diff --git a/cmake/arm-none-eabi.cmake b/cmake/arm-none-eabi.cmake index e86cb6a507..eb7ddebabf 100644 --- a/cmake/arm-none-eabi.cmake +++ b/cmake/arm-none-eabi.cmake @@ -6,35 +6,16 @@ if(WIN32) endif() set(TARGET_TRIPLET "arm-none-eabi") -set(gcc "${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}") - -find_program(GCC "${gcc}") -if (NOT GCC) - message(FATAL_ERROR "Could not find ${gcc}") -endif() - -set(ARM_NONE_EABI_GCC_VERSION 9.2.1) - -execute_process(COMMAND "${GCC}" -dumpversion - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE GCC_VERSION) - -if (NOT ${ARM_NONE_EABI_GCC_VERSION} STREQUAL ${GCC_VERSION}) - # TODO: Show how to override on cmdline or install builtin compiler - message(FATAL_ERROR "Expecting gcc version ${ARM_NONE_EABI_GCC_VERSION}, but found ${GCC_VERSION}") -endif() - -get_filename_component(TOOLCHAIN_BIN_DIR "${GCC}" DIRECTORY) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -set(CMAKE_ASM_COMPILER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "asm compiler") -set(CMAKE_C_COMPILER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c compiler") -set(CMAKE_CXX_COMPILER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-g++${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++ compiler") -set(CMAKE_OBJCOPY "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objcopy${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objcopy tool") -set(CMAKE_OBJDUMP "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objdump${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objdump tool") -set(CMAKE_SIZE "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-size${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "size tool") -set(CMAKE_DEBUGGER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gdb${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "debugger") -set(CMAKE_CPPFILT "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-c++filt${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++filt") +set(CMAKE_ASM_COMPILER "${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "asm compiler") +set(CMAKE_C_COMPILER "${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c compiler") +set(CMAKE_CXX_COMPILER "${TARGET_TRIPLET}-g++${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++ compiler") +set(CMAKE_OBJCOPY "${TARGET_TRIPLET}-objcopy${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objcopy tool") +set(CMAKE_OBJDUMP "${TARGET_TRIPLET}-objdump${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objdump tool") +set(CMAKE_SIZE "${TARGET_TRIPLET}-size${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "size tool") +set(CMAKE_DEBUGGER "${TARGET_TRIPLET}-gdb${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "debugger") +set(CMAKE_CPPFILT "${TARGET_TRIPLET}-c++filt${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++filt") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/gcc.cmake b/cmake/gcc.cmake new file mode 100644 index 0000000000..cfe2ddf3db --- /dev/null +++ b/cmake/gcc.cmake @@ -0,0 +1,34 @@ +function(gcc_get_version var) + cmake_parse_arguments(args + "" + "TRIPLET;PROGRAM_NAME;PROGRAM_PATH" + "" + ${ARGN} + ) + set(prog "gcc") + if(args_TRIPLET) + set(prog "${args_TRIPLET}-${prog}") + endif() + if(args_PROGRAM_NAME) + set(${args_PROGRAM_NAME} ${prog} PARENT_SCOPE) + endif() + + find_program(gcc ${prog}) + if (NOT gcc) + set(${var} OFF PARENT_SCOPE) + endif() + + if(args_PROGRAM_PATH) + set(${args_PROGRAM_PATH} ${gcc} PARENT_SCOPE) + endif() + + execute_process(COMMAND "${gcc}" -dumpversion + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE version) + + if("" STREQUAL version) + set(${var} OFF PARENT_SCOPE) + else() + set(${var} ${version} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/settings.cmake b/cmake/settings.cmake index d3e3db8f3a..17d48168b4 100644 --- a/cmake/settings.cmake +++ b/cmake/settings.cmake @@ -18,7 +18,7 @@ function(enable_settings exe name) add_custom_command( OUTPUT ${dir}/${SETTINGS_GENERATED_H} ${dir}/${SETTINGS_GENERATED_C} COMMAND - ${CMAKE_COMMAND} -E env CFLAGS="${cflags}" TARGET=${name} + ${CMAKE_COMMAND} -E env CFLAGS="${cflags}" TARGET=${name} PATH=$ENV{PATH} ${RUBY_EXECUTABLE} ${SETTINGS_GENERATOR} ${MAIN_DIR} ${SETTINGS_FILE} -o "${dir}" DEPENDS ${SETTINGS_GENERATOR} ${SETTINGS_FILE} ) diff --git a/cmake/stm32.cmake b/cmake/stm32.cmake index 23fb723333..f028a3fdc2 100644 --- a/cmake/stm32.cmake +++ b/cmake/stm32.cmake @@ -192,13 +192,15 @@ endfunction() function(add_hex_target name exe hex) add_custom_target(${name} ALL + cmake -E env PATH=$ENV{PATH} ${CMAKE_OBJCOPY} -Oihex $ ${hex} BYPRODUCTS ${hex} ) endfunction() function(add_bin_target name exe bin) - add_custom_target(${name} ALL + add_custom_target(${name} + cmake -E env PATH=$ENV{PATH} ${CMAKE_OBJCOPY} -Obinary $ ${bin} BYPRODUCTS ${bin} )