patrislav1 / cubemx.cmake Goto Github PK
View Code? Open in Web Editor NEWScript collection to build CubeMX projects with CMake and debug them with VSCode
License: The Unlicense
Script collection to build CubeMX projects with CMake and debug them with VSCode
License: The Unlicense
Please include a .gitattributes
configuration in the main directory and ensure all files use native line endings in the repository:
* text=auto
*.cmake text
*.in text
*.md text
*.py text
Please convert line endings in the repository accordingly. TIA.
When the RCC.HSI_VALUE
is not set (e.g. with the NUCLEO-H723ZG) then configuring the project fails:
cmake_minimum_required(VERSION 3.16)
# Possible values: openocd, pyocd, stlink. stlink is default
# set(CMX_DEBUGGER "openocd")
# set(OPENOCD_CFG "${CMAKE_CURRENT_SOURCE_DIR}/openocd.cfg")
include(cubemx.cmake/cubemx.cmake)
project(evaltest)
file(
GLOB_RECURSE APP_SRC_FILES "app/*.c"
)
add_executable(evaltest ${APP_SRC_FILES})
cubemx_target(
TARGET evaltest
IOC "${CMAKE_CURRENT_LIST_DIR}/evaltest.ioc"
# STARTUP "custom_startup.s" # optional custom startup
# LDSCRIPT "custom_ldscript.ld" # optional custom ldscript
)
target_compile_options(evaltest PRIVATE -Og -Wall -g -gdwarf-2)
# Depending on the project setup, sometimes one of these symbols must be omitted. (Cannot be reliably derived from the .ioc file)
target_compile_definitions(evaltest PRIVATE USE_FULL_LL_DRIVER USE_HAL_DRIVER)
$ cmake ..
-- Found Python3: /usr/bin/python3.8 (found version "3.8.10") found components: Interpreter
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - failed
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Traceback (most recent call last):
File "/home/user/work/evaltest/cubemx.cmake/cubemx-cmake.py", line 87, in <module>
f"HSI_VALUE={iocConf['RCC.HSI_VALUE']}",
KeyError: 'RCC.HSI_VALUE'
CMake Error at cubemx.cmake/cubemx.cmake:28 (message):
cubemx-cmake.py failed - aborting
Call Stack (most recent call first):
cubemx.cmake/cubemx.cmake:98 (cmx_get)
CMakeLists.txt:16 (cubemx_target)
-- Configuring incomplete, errors occurred!
See also "/home/user/work/evaltest/build/CMakeFiles/CMakeOutput.log".
See also "/home/user/work/evaltest/build/CMakeFiles/CMakeError.log".
It seems like the parser doesn't care about middlewares(freertos, usb_device, etc.). As this project is a "minimal" ioc parser, is it OK to take care of these additional components?
Or alternatively, can we add a .cproject
parser, and directly extract sources/include paths from CubeIDE project file?
Given the following rough project setup:
include(cubemx.cmake/cubemx.cmake)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
project(firmware LANGUAGES C CXX ASM)
add_executable(firmware app_version.c)
cubemx_target(
TARGET firmware
IOC "${CMAKE_CURRENT_LIST_DIR}/app_stub/app_stub.ioc"
FLASH_TARGET_NAME flash_app
IMG_ADDR 0x08008000
)
target_compile_options(firmware PRIVATE -Og -Wall -g -gdwarf-2)
target_compile_definitions(firmware PRIVATE USE_FULL_LL_DRIVER USE_HAL_DRIVER)
target_include_directories(firmware PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/app"
"${CMAKE_CURRENT_LIST_DIR}/common"
)
file(GLOB_RECURSE FIRMWARE_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/app/*.c"
"${CMAKE_CURRENT_LIST_DIR}/app/*.cpp"
"${CMAKE_CURRENT_LIST_DIR}/common/*.c"
"${CMAKE_CURRENT_LIST_DIR}/common/*.cpp"
)
target_sources(firmware PRIVATE ${FIRMWARE_SOURCES})
add_executable(bootloader boot_version.c)
cubemx_target(
TARGET bootloader
IOC "${CMAKE_CURRENT_LIST_DIR}/boot_stub/boot_stub.ioc"
FLASH_TARGET_NAME flash_boot
IMG_ADDR 0x08000000
)
target_compile_options(bootloader PRIVATE -Og -Wall -g -gdwarf-2)
target_compile_definitions(bootloader PRIVATE USE_FULL_LL_DRIVER USE_HAL_DRIVER)
target_include_directories(bootloader PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/boot"
"${CMAKE_CURRENT_LIST_DIR}/common"
)
file(GLOB_RECURSE BOOTLOADER_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/boot/*.c"
"${CMAKE_CURRENT_LIST_DIR}/boot/*.cpp"
"${CMAKE_CURRENT_LIST_DIR}/common/*.c"
"${CMAKE_CURRENT_LIST_DIR}/common/*.cpp"
)
target_sources(bootloader PRIVATE ${BOOTLOADER_SOURCES})
add_custom_command(
OUTPUT app_version.c _ # "_" is dummy output, so this command runs on every build
COMMAND ${CMAKE_COMMAND}
-D INPUT_FILE=${CMAKE_CURRENT_SOURCE_DIR}/app/version.c.in
-D OUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/app_version.c
-P ${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen_version.cmake
)
add_custom_command(
OUTPUT boot_version.c _ # "_" is dummy output, so this command runs on every build
COMMAND ${CMAKE_COMMAND}
-D INPUT_FILE=${CMAKE_CURRENT_SOURCE_DIR}/boot/version.c.in
-D OUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/boot_version.c
-P ${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen_version.cmake
)
Result looks like this:
$ cmake .. && make
Using startup file: /home/user/project/app_stub/startup_stm32l476xx.s;/home/user/project/boot_stub/startup_stm32l476xx.s
Using linkerscript: /home/user/project/app_stub/STM32L476RGTx_FLASH.ld;/home/user/project/boot_stub/STM32L476RGTx_FLASH.ld
Using startup file: /home/user/project/app_stub/startup_stm32l476xx.s;/home/user/project/boot_stub/startup_stm32l476xx.s
Using linkerscript: /home/user/project/app_stub/STM32L476RGTx_FLASH.ld;/home/user/project/boot_stub/STM32L476RGTx_FLASH.ld
CMake Error at cubemx.cmake/stlink/flash-target.cmake:4 (add_custom_target):
add_custom_target cannot create target "reset" because another target with
the same name already exists. The existing target is a custom target
created in source directory "/home/user/project". See
documentation for policy CMP0002 for more details.
Call Stack (most recent call first):
cubemx.cmake/cubemx.cmake:147 (include)
CMakeLists.txt:42 (cubemx_target)
CMake Error at cubemx.cmake/stlink/flash-target.cmake:12 (add_custom_target):
add_custom_target cannot create target "erase" because another target with
the same name already exists. The existing target is a custom target
created in source directory "/home/user/project". See
documentation for policy CMP0002 for more details.
Call Stack (most recent call first):
cubemx.cmake/cubemx.cmake:147 (include)
CMakeLists.txt:42 (cubemx_target)
I have generated a CubeMX project, called demo-mx
, and the startup file is correctly present at the root directory. In my case, using an STM32F401RE, the startup file is startup_stm32f401xe.s
. But, when trying to build with CMake this error is thrown:
[cmake] CMake Error at cubemx.cmake/cubemx.cmake:85 (message):
[cmake] CubeMX startup file not found!
I followed all the steps under "How to use section", and below are attached the source tree and the content of the CMakeLists.txt
file
cmake_minimum_required(VERSION 3.16)
# Possible values: openocd, pyocd, stlink, blackmagic. stlink is default
set(CMX_DEBUGGER "stlink")
# set(OPENOCD_CFG "${CMAKE_CURRENT_SOURCE_DIR}/openocd.cfg")
include(cubemx.cmake/cubemx.cmake)
# cross compilation
set(TOOLCHAIN_PATH "C:\\ST\\STM32CubeCLT\\GNU-tools-for-STM32\\bin\\")
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PATH}arm-none-eabi-gcc)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
project(demo-mx)
add_executable(demo-mx Core/Src/*.c)
cubemx_target(
TARGET demo-mx
IOC "${CMAKE_CURRENT_LIST_DIR}/demo-mx.ioc"
)
target_compile_options(demo-mx PRIVATE -Og -Wpedantic -Wall -g -gdwarf-2)
# Depending on the project setup, sometimes one of these symbols must be omitted. (Cannot be reliably determined from the .ioc file)
target_compile_definitions(demo-mx PRIVATE USE_FULL_LL_DRIVER USE_HAL_DRIVER)
GNU ARM Toolchain 11.2 on Windows, bin directory in PATH, normal example template.
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" -Sc:/git/testprojekt -Bc:/git/testprojekt/build -G Ninja
[main] Configuring folder: testprojekt
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -Sc:/git/testprojekt -Bc:/git/testprojekt/build -G Ninja
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The ASM compiler identification is unknown
[cmake] -- Didn't find assembler
[cmake] CMake Error at cubemx.cmake/cubemx.cmake:16 (enable_language):
[cmake] No CMAKE_ASM_COMPILER could be found.
[cmake]
[cmake] -- Warning: Did not find file Compiler/-ASM
[cmake] Tell CMake where to find the compiler by setting either the environment
[cmake] variable "ASM" or the CMake cache entry CMAKE_ASM_COMPILER to the full path
[cmake] to the compiler, or to the compiler name if it is in the PATH.
[cmake] Call Stack (most recent call first):
[cmake] CMakeLists.txt:12 (include)
[cmake]
[cmake]
[cmake] -- Configuring incomplete, errors occurred!
[cmake] See also "C:/git/testprojekt/build/CMakeFiles/CMakeOutput.log".
[cmake] See also "C:/git/testprojekt/build/CMakeFiles/CMakeError.log".
Toolchain located in "C:\Program Files (x86)\Arm GNU Toolchain arm-none-eabi\11.2 2022.02\bin"
I have a project that is structured in this way:
project/
├── target-1/
│ ├── ...
│ └── target-1.ioc
├── target-2/
│ ├── ...
│ └── target-2.ioc
├── ...
└── CMakeLists.txt
Where the CMakeLists.txt
file contains something like this:
include(cubemx.cmake/cubemx.cmake)
project(project)
add_executable(target-1)
cubemx_target(
TARGET target-1
CUBEMX_SOURCE_DIR target-1
FLASH_TARGET_NAME target-1-flash
IOC "${CMAKE_CURRENT_LIST_DIR}/target-1/target-1.ioc"
)
...
add_executable(target-2)
cubemx_target(
TARGET target-2
CUBEMX_SOURCE_DIR target-2
FLASH_TARGET_NAME target-2-flash
IOC "${CMAKE_CURRENT_LIST_DIR}/target-2/target-2.ioc"
)
...
The problem with this configuration is that the .vscode/launch.json
is (kinda) broken because it contains the configuration for only one of the targets.
The problem is that vscode-debug.cmake
for every configured target, it replaces the entire contents of that file, overwriting any previously saved configuration.
What it should do instead is to overwrite only the entries of the "configurations"
JSON array object that have the same name of the selected targets.
This is obviously much more difficult to implement, given that (IIRC) there is no JSON support to CMake and that it's not a trivial operation. One of the edge cases I can think of is removing a target, that would leave the configuration for that target untouched, which means that the user would have to delete it manually.
There is also the fact that this type of project structure can probably be changed for a better one or that I've missed something that could make this work without any changes.
When the main CMakeLists.txt
references a CubeMX project file that does not exist, the Python script throws stacktraces about the file not existing, instead of some plain small error line that CMake could pick up and prematurely abort configuration.
Steps to reproduce:
CMakeLists-example.txt
to CMakeLists.txt
mkdir build
cd build
cmake ..
Expected behaviour:
Clear indication that cmake
aborts after the first signs the project file does not exist.
Actual Result:
Loads of python backtraces and cmake
continuing along …
user@host:~/cubemx.cmake (master[origin])$ cp CMakeLists-example.txt CMakeLists.txt
user@host:~/cubemx.cmake (master[origin])$ mkdir build
user@host:~/cubemx.cmake/build (master[origin])$ cd build/
user@host:~/cubemx.cmake/build (master[origin])$ cmake ..
-- Found Python3: /usr/bin/python3.8 (found version "3.8.5") found components: Interpreter
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
Traceback (most recent call last):
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 60, in <module>
iocConf = loadIOC(args.iocFile)
File "/home/user/cubemx.cmake/cmake/cubemx-cmake.py", line 9, in loadIOC
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/user/cubemx.cmake/cubemx_project.ioc'
CMake Error at CMakeLists.txt:11 (project):
project PROJECT called with incorrect number of arguments
CMake Error at CMakeLists.txt:14 (cubemx_target):
cubemx_target Function invoked with incorrect arguments for function named:
cubemx_target
CMake Error at CMakeLists.txt:15 (target_compile_options):
Cannot specify compile options for target "PRIVATE" which is not built by
this project.
-- Configuring incomplete, errors occurred!
See also "/home/user/cubemx.cmake/build/CMakeFiles/CMakeOutput.log".
Hello, I successfully compiled a HelloWorld project out of CubeMX with cmake after using your scripts with a recent sample Nucleo board Nucleo-U575ZI.
Therefore I had to adapt the cubemx-cmake.py in terms of coreTable and fpuTable. In my opinion the compiler options are already visible in the settings of CubeMX -> C/C++ Build -> MCU GCC Compiler -> All options
Would it be feasible to read out that information from the project instead of manual creating this tables? I also noticed the compiler / linker switches were not put 1:1 to the cmake files, so my result elf-binary is slightly different.
This idea (and also my low Python skills) snarled me up sending you a table change commit.
What do you think? Or do I miss something?
Best Regards.
There are several places that do
file(GLOB_RECURSIVE VARNAME ${DIR} ${FILENAME})
This is broken, as it finds ${FILENAME}
in any subdirectory of the current ${CMAKE_CURRENT_LIST_DIR}
. Symptoms of the bug include linker errors claiming multiple definitions of memory sections and complaints about missing parameter prefixes:
$ cmake .. && make
Using startup file: /home/user/project/app_stub/startup_stm32l476xx.s;/home/user/project/boot_stub/startup_stm32l476xx.s
Using linkerscript: /home/user/project/app_stub/STM32L476RGTx_FLASH.ld;/home/user/project/boot_stub/STM32L476RGTx_FLASH.ld
Using startup file: /home/user/project/app_stub/startup_stm32l476xx.s;/home/user/project/boot_stub/startup_stm32l476xx.s
Using linkerscript: /home/user/project/app_stub/STM32L476RGTx_FLASH.ld;/home/user/project/boot_stub/STM32L476RGTx_FLASH.ld
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/project/build
Scanning dependencies of target bootloader
[ 1%] Linking C executable bootloader.elf
/opt/gcc-arm-none-eabi-10.3-2022.01/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/bootloader.dir/boot_stub/startup_stm32l476xx.s.obj:(.isr_vector+0x0): multiple definition of `g_pfnVectors'; CMakeFiles/bootloader.dir/app_stub/startup_stm32l476xx.s.obj:(.isr_vector+0x0): first defined here
/opt/gcc-arm-none-eabi-10.3-2022.01/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/bootloader.dir/boot_stub/startup_stm32l476xx.s.obj: in function `Default_Handler':
/home/user/project/boot_stub/startup_stm32l476xx.s:119: multiple definition of `Default_Handler'; CMakeFiles/bootloader.dir/app_stub/startup_stm32l476xx.s.obj:/home/user/project/app_stub/startup_stm32l476xx.s:120: first defined here
Correct would be:
file(GLOB_RECURSIVE VARNAME "${DIR}/${FILENAME}")
PR incoming, just looking through the code if I missed any.
From 8dd123df128127e76b15b37570ad2d0e74771fba Mon Sep 17 00:00:00 2001
From: Benny Baumann <[email protected]>
Date: Tue, 29 Mar 2022 09:56:50 +0200
Subject: [PATCH 1/2] Fix globbing for the startup file
---
cubemx.cmake | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cubemx.cmake b/cubemx.cmake
index 8c9c8a47..30eb16ed 100644
--- a/cubemx.cmake
+++ b/cubemx.cmake
@@ -51,11 +51,11 @@ function(add_startup)
if("${CMX_STARTUP}" STREQUAL "")
# Check if the "Makefile" startupfile is in the source tree
cmx_get(startupfile_makefile CMX_STARTUPFILE)
- file(GLOB_RECURSE CMX_STARTUP ${CMX_CUBEMX_CORE_DIR} ${CMX_STARTUPFILE})
+ file(GLOB_RECURSE CMX_STARTUP "${CMX_CUBEMX_CORE_DIR}/${CMX_STARTUPFILE}")
if("${CMX_STARTUP}" STREQUAL "")
# If not, look for the "STM32CubeIDE" startupfile
cmx_get(startupfile_stm32cubeide CMX_STARTUPFILE)
- file(GLOB_RECURSE CMX_STARTUP ${CMX_CUBEMX_CORE_DIR} ${CMX_STARTUPFILE})
+ file(GLOB_RECURSE CMX_STARTUP "${CMX_CUBEMX_CORE_DIR}/${CMX_STARTUPFILE}")
if("${CMX_STARTUP}" STREQUAL "")
message(FATAL_ERROR "CubeMX startup file not found!")
endif()
--
2.25.1
From d171b0442d722dc66988b7ba2d1a8080b1b44771 Mon Sep 17 00:00:00 2001
From: Benny Baumann <[email protected]>
Date: Tue, 29 Mar 2022 10:16:29 +0200
Subject: [PATCH 2/2] Fix globbing for the linker script
---
cubemx.cmake | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/cubemx.cmake b/cubemx.cmake
index 30eb16ed..15f70a87 100644
--- a/cubemx.cmake
+++ b/cubemx.cmake
@@ -73,16 +73,17 @@ function(add_ldscript)
if("${CMX_LDSCRIPT}" STREQUAL "")
# Check if the "Makefile" linkerscript is in the source tree
set(LINKERSCRIPT "${CMX_MCUNAME}_FLASH.ld")
- file(GLOB_RECURSE CMX_LDSCRIPT ${CMX_CUBEMX_CORE_DIR} ${LINKERSCRIPT})
+ file(GLOB_RECURSE CMX_LDSCRIPT "${CMX_CUBEMX_CORE_DIR}/${LINKERSCRIPT}")
if("${CMX_LDSCRIPT}" STREQUAL "")
# If not, look for the "STM32CubeIDE" linkerscript
string(REPLACE "x" "X" LINKERSCRIPT ${LINKERSCRIPT})
- file(GLOB_RECURSE CMX_LDSCRIPT ${CMX_CUBEMX_CORE_DIR} ${LINKERSCRIPT})
+ file(GLOB_RECURSE CMX_LDSCRIPT "${CMX_CUBEMX_CORE_DIR}/${LINKERSCRIPT}")
if("${CMX_LDSCRIPT}" STREQUAL "")
message(FATAL_ERROR "CubeMX linkerscript not found!")
endif()
endif()
endif()
+
message("Using linkerscript: ${CMX_LDSCRIPT}")
set(CMX_LDSCRIPT ${CMX_LDSCRIPT} PARENT_SCOPE)
endfunction()
--
2.25.1
When building multi-part binary bundles it's necessary to inflate the generated .bin
file for some targets (e.g. when creating a bootloader). Currently there's no direct option to pass additional arguments for the mcu_elf2bin
such that additional arguments like --pad-to 0x8008000 --gap-fill 0xff
can be passed.
Also it'd be nice to have the various target files available as TARGET_PROPERTIES
so they can be referenced in generator expressions for dependent targets:
add_custom_command(
OUTPUT bundle.bin
COMMAND
cat
"$<TARGET_PROPERTY:bootloader,TARGET_FILE_BIN>"
"$<TARGET_PROPERTY:firmware,TARGET_FILE_BIN>"
> "${CMAKE_CURRENT_BINARY_DIR}/bundle.bin"
DEPENDS bootloader firmware
COMMENT "Generating firmware bundle"
)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.