Simpler build, less dependencies (#827)
* Simpler build, less dependencies * Follow ugly python linter * Introduce Brewfile & Update Readme * Make dist.sh target-specific * Tidy up make output * Get rid of cat and truncate (I still love cats tho) * Suppress dd output * Long live the cat
This commit is contained in:
		
							parent
							
								
									cc044c5033
								
							
						
					
					
						commit
						4303945748
					
				
							
								
								
									
										98
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										98
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -67,66 +67,19 @@ jobs: | |||||||
|           fi |           fi | ||||||
|            |            | ||||||
|           echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV |           echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV | ||||||
|  |           echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV | ||||||
|           echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}" |           echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}" | ||||||
|           echo "::set-output name=suffix::${SUFFIX}" |           echo "::set-output name=suffix::${SUFFIX}" | ||||||
|           echo "::set-output name=short-hash::${SHA}" |           echo "::set-output name=short-hash::${SHA}" | ||||||
|           echo "::set-output name=default-target::${DEFAULT_TARGET}" |           echo "::set-output name=default-target::${DEFAULT_TARGET}" | ||||||
| 
 | 
 | ||||||
|       - name: 'Build bootloader in docker' |       - name: 'Build the firmware in docker' | ||||||
|         uses: ./.github/actions/docker |         uses: ./.github/actions/docker | ||||||
|         with: |         with: | ||||||
|           run: | |           run: | | ||||||
|             for TARGET in ${TARGETS} |             for TARGET in ${TARGETS} | ||||||
|             do |             do | ||||||
|               make -j$(nproc) -C bootloader TARGET=${TARGET} |               make TARGET=${TARGET} | ||||||
|             done |  | ||||||
| 
 |  | ||||||
|       - name: 'Build firmware in docker' |  | ||||||
|         uses: ./.github/actions/docker |  | ||||||
|         with: |  | ||||||
|           run: | |  | ||||||
|             for TARGET in ${TARGETS} |  | ||||||
|             do |  | ||||||
|               make -j$(nproc) -C firmware TARGET=${TARGET} |  | ||||||
|             done |  | ||||||
| 
 |  | ||||||
|       - name: 'Generate full hex file' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         uses: ./.github/actions/docker |  | ||||||
|         with: |  | ||||||
|           run: | |  | ||||||
|             for TARGET in ${TARGETS} |  | ||||||
|             do |  | ||||||
|               srec_cat \ |  | ||||||
|                 bootloader/.obj/${TARGET}/bootloader.hex -Intel \ |  | ||||||
|                 firmware/.obj/${TARGET}/firmware.hex -Intel \ |  | ||||||
|                 -o firmware/.obj/${TARGET}/full.hex -Intel |  | ||||||
|             done |  | ||||||
| 
 |  | ||||||
|       - name: 'Generate full dfu file' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         uses: ./.github/actions/docker |  | ||||||
|         with: |  | ||||||
|           run: | |  | ||||||
|             for TARGET in ${TARGETS} |  | ||||||
|             do |  | ||||||
|               hex2dfu \ |  | ||||||
|                 -i firmware/.obj/${TARGET}/full.hex \ |  | ||||||
|                 -o artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.dfu \ |  | ||||||
|                 -l "Flipper Zero $(echo $TARGET | tr a-z A-Z)" |  | ||||||
|             done |  | ||||||
| 
 |  | ||||||
|       - name: 'Generate full json file' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         uses: ./.github/actions/docker |  | ||||||
|         with: |  | ||||||
|           run: | |  | ||||||
|             for TARGET in ${TARGETS} |  | ||||||
|             do |  | ||||||
|               jq -s '.[0] * .[1]' \ |  | ||||||
|                 bootloader/.obj/${TARGET}/bootloader.json \ |  | ||||||
|                 firmware/.obj/${TARGET}/firmware.json  \ |  | ||||||
|                 > artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.json |  | ||||||
|             done |             done | ||||||
| 
 | 
 | ||||||
|       - name: 'Move upload files' |       - name: 'Move upload files' | ||||||
| @ -136,50 +89,7 @@ jobs: | |||||||
|           run: | |           run: | | ||||||
|             for TARGET in ${TARGETS} |             for TARGET in ${TARGETS} | ||||||
|             do |             do | ||||||
|               mv bootloader/.obj/${TARGET}/bootloader.dfu \ |               mv dist/${TARGET}/* artifacts/ | ||||||
|                 artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.dfu |  | ||||||
|               mv bootloader/.obj/${TARGET}/bootloader.bin \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.bin |  | ||||||
|               mv bootloader/.obj/${TARGET}/bootloader.elf \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.elf |  | ||||||
|               mv bootloader/.obj/${TARGET}/bootloader.json \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.json |  | ||||||
|               mv firmware/.obj/${TARGET}/firmware.dfu \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.dfu |  | ||||||
|               mv firmware/.obj/${TARGET}/firmware.bin \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.bin |  | ||||||
|               mv firmware/.obj/${TARGET}/firmware.elf \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.elf |  | ||||||
|               mv firmware/.obj/${TARGET}/firmware.json \ |  | ||||||
|                 artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.json |  | ||||||
|             done |  | ||||||
| 
 |  | ||||||
|       - name: 'Full flash asssembly: bootloader as base' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         run: | |  | ||||||
|           for TARGET in ${TARGETS} |  | ||||||
|           do |  | ||||||
|             cp \ |  | ||||||
|               artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.bin \ |  | ||||||
|               artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin |  | ||||||
|           done |  | ||||||
| 
 |  | ||||||
|       - name: 'Full flash asssembly: bootloader padding' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         run: | |  | ||||||
|           for TARGET in ${TARGETS} |  | ||||||
|           do |  | ||||||
|             truncate -s 32768 artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin |  | ||||||
|           done |  | ||||||
| 
 |  | ||||||
|       - name: 'Full flash asssembly: append firmware' |  | ||||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} |  | ||||||
|         run: | |  | ||||||
|           for TARGET in ${TARGETS} |  | ||||||
|           do |  | ||||||
|             cat \ |  | ||||||
|               artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.bin \ |  | ||||||
|               >> artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin |  | ||||||
|             done |             done | ||||||
| 
 | 
 | ||||||
|       - name: 'Bundle core2 firmware' |       - name: 'Bundle core2 firmware' | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -24,6 +24,7 @@ __pycache__/ | |||||||
| bindings/ | bindings/ | ||||||
| .DS_Store | .DS_Store | ||||||
| .mxproject | .mxproject | ||||||
|  | Brewfile.lock.json | ||||||
| 
 | 
 | ||||||
| # Visual Studio Code | # Visual Studio Code | ||||||
| .vscode/ | .vscode/ | ||||||
| @ -31,3 +32,6 @@ bindings/ | |||||||
| # legendary cmake's | # legendary cmake's | ||||||
| build | build | ||||||
| CMakeLists.txt | CMakeLists.txt | ||||||
|  | 
 | ||||||
|  | # bundle output | ||||||
|  | dist | ||||||
							
								
								
									
										6
									
								
								Brewfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Brewfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | cask "gcc-arm-embedded" | ||||||
|  | brew "protobuf" | ||||||
|  | brew "heatshrink" | ||||||
|  | brew "open-ocd" | ||||||
|  | brew "clang-format" | ||||||
|  | brew "dfu-util" | ||||||
							
								
								
									
										38
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								Makefile
									
									
									
									
									
								
							| @ -10,65 +10,69 @@ else ifeq ($(OS), Darwin) | |||||||
| NPROCS := $(shell sysctl -n hw.ncpu) | NPROCS := $(shell sysctl -n hw.ncpu) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | include	$(PROJECT_ROOT)/make/defaults.mk | ||||||
|  | 
 | ||||||
| .PHONY: all | .PHONY: all | ||||||
| all: bootloader_all firmware_all | all: bootloader_all firmware_all | ||||||
|  | 	@$(PROJECT_ROOT)/scripts/dist.sh | ||||||
| 
 | 
 | ||||||
| .PHONY: whole | .PHONY: whole | ||||||
| whole: flash_radio bootloader_flash firmware_flash | whole: flash_radio bootloader_flash firmware_flash | ||||||
| 
 | 
 | ||||||
| .PHONY: clean | .PHONY: clean | ||||||
| clean: bootloader_clean firmware_clean | clean: bootloader_clean firmware_clean | ||||||
|  | 	@rm -rf $(PROJECT_ROOT)/dist/$(TARGET) | ||||||
| 
 | 
 | ||||||
| .PHONY: flash | .PHONY: flash | ||||||
| flash: bootloader_flash firmware_flash | flash: bootloader_flash firmware_flash | ||||||
| 
 | 
 | ||||||
| .PHONY: debug | .PHONY: debug | ||||||
| debug: | debug: | ||||||
| 	$(MAKE) -C firmware -j$(NPROCS) debug | 	@$(MAKE) -C firmware -j$(NPROCS) debug | ||||||
| 
 | 
 | ||||||
| .PHONY: blackmagic | .PHONY: blackmagic | ||||||
| blackmagic: | blackmagic: | ||||||
| 	$(MAKE) -C firmware -j$(NPROCS) blackmagic | 	@$(MAKE) -C firmware -j$(NPROCS) blackmagic | ||||||
| 
 | 
 | ||||||
| .PHONY: wipe | .PHONY: wipe | ||||||
| wipe: | wipe: | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py wipe | 	@$(PROJECT_ROOT)/scripts/flash.py wipe | ||||||
| 	$(PROJECT_ROOT)/scripts/ob.py set | 	@$(PROJECT_ROOT)/scripts/ob.py set | ||||||
| 
 | 
 | ||||||
| .PHONY: bootloader_all | .PHONY: bootloader_all | ||||||
| bootloader_all: | bootloader_all: | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) all | 	@$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) all | ||||||
| 
 | 
 | ||||||
| .PHONY: firmware_all | .PHONY: firmware_all | ||||||
| firmware_all: | firmware_all: | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) all | 	@$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) all | ||||||
| 
 | 
 | ||||||
| .PHONY: bootloader_clean | .PHONY: bootloader_clean | ||||||
| bootloader_clean: | bootloader_clean: | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) clean | 	@$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) clean | ||||||
| 
 | 
 | ||||||
| .PHONY: firmware_clean | .PHONY: firmware_clean | ||||||
| firmware_clean: | firmware_clean: | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) clean | 	@$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) clean | ||||||
| 
 | 
 | ||||||
| .PHONY: bootloader_flash | .PHONY: bootloader_flash | ||||||
| bootloader_flash: | bootloader_flash: | ||||||
| ifeq ($(FORCE), 1) | ifeq ($(FORCE), 1) | ||||||
| 	rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true | 	@rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true | ||||||
| endif | endif | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash | 	@$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash | ||||||
| 
 | 
 | ||||||
| .PHONY: firmware_flash | .PHONY: firmware_flash | ||||||
| firmware_flash: | firmware_flash: | ||||||
| ifeq ($(FORCE), 1) | ifeq ($(FORCE), 1) | ||||||
| 	rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true | 	@rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true | ||||||
| endif | endif | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash | 	@$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash | ||||||
| 
 | 
 | ||||||
| .PHONY: flash_radio | .PHONY: flash_radio | ||||||
| flash_radio: | flash_radio: | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py core2radio 0x080CA000 $(COPRO_DIR)/stm32wb5x_BLE_Stack_full_fw.bin | 	@$(PROJECT_ROOT)/scripts/flash.py core2radio 0x080CA000 $(COPRO_DIR)/stm32wb5x_BLE_Stack_full_fw.bin | ||||||
| 	$(PROJECT_ROOT)/scripts/ob.py set | 	@$(PROJECT_ROOT)/scripts/ob.py set | ||||||
| 
 | 
 | ||||||
| .PHONY: flash_radio_fus | .PHONY: flash_radio_fus | ||||||
| flash_radio_fus: | flash_radio_fus: | ||||||
| @ -83,9 +87,9 @@ flash_radio_fus: | |||||||
| 
 | 
 | ||||||
| .PHONY: flash_radio_fus_please_i_m_not_going_to_complain | .PHONY: flash_radio_fus_please_i_m_not_going_to_complain | ||||||
| flash_radio_fus_please_i_m_not_going_to_complain: | flash_radio_fus_please_i_m_not_going_to_complain: | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin | 	@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin | 	@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin | ||||||
| 	$(PROJECT_ROOT)/scripts/ob.py set | 	@$(PROJECT_ROOT)/scripts/ob.py set | ||||||
| 
 | 
 | ||||||
| FORMAT_SOURCES = $(shell find applications bootloader core -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") | FORMAT_SOURCES = $(shell find applications bootloader core -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										118
									
								
								ReadMe.md
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								ReadMe.md
									
									
									
									
									
								
							| @ -55,17 +55,12 @@ One liner: `./flash_core1_main.sh` | |||||||
| 
 | 
 | ||||||
| 3. Run `dfu-util -D full.dfu -a 0` | 3. Run `dfu-util -D full.dfu -a 0` | ||||||
| 
 | 
 | ||||||
| # Build from source | # Build with Docker | ||||||
| 
 | 
 | ||||||
| ## Prerequisites | ## Prerequisites | ||||||
| 
 | 
 | ||||||
| 1. Install [Docker Engine and Docker Compose](https://www.docker.com/get-started) | 1. Install [Docker Engine and Docker Compose](https://www.docker.com/get-started) | ||||||
| 2. Clone the repo: | 2. Prepare the container: | ||||||
|    ```sh |  | ||||||
|    git clone https://github.com/flipperdevices/flipperzero-firmware |  | ||||||
|    cd flipperzero-firmware |  | ||||||
|    ``` |  | ||||||
| 3. Prepare the container: |  | ||||||
|    ```sh |    ```sh | ||||||
|    docker-compose up -d |    docker-compose up -d | ||||||
|    ``` |    ``` | ||||||
| @ -73,62 +68,71 @@ One liner: `./flash_core1_main.sh` | |||||||
| ## Compile everything | ## Compile everything | ||||||
| 
 | 
 | ||||||
| ```sh | ```sh | ||||||
| docker-compose exec dev make -j$(nproc) | docker-compose exec dev make | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | Check `dist/` for build outputs. | ||||||
|  | 
 | ||||||
|  | Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. | ||||||
|  | 
 | ||||||
|  | # Build on Linux/macOS | ||||||
|  | 
 | ||||||
|  | ## macOS Prerequisites | ||||||
|  | 
 | ||||||
|  | Make sure you have [brew](https://brew.sh) and install all the dependencies: | ||||||
|  | ```sh | ||||||
|  | brew bundle --verbose | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Linux Prerequisites | ||||||
|  | 
 | ||||||
|  | ### gcc-arm-none-eabi | ||||||
|  | 
 | ||||||
|  | ```sh | ||||||
|  | toolchain="gcc-arm-none-eabi-10.3-2021.10" | ||||||
|  | toolchain_package="$toolchain-$(uname -m)-linux" | ||||||
|  | 
 | ||||||
|  | wget -P /opt "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/$toolchain_package.tar.bz2" | ||||||
|  | 
 | ||||||
|  | tar xjf /opt/$toolchain_package.tar.bz2 -C /opt | ||||||
|  | rm /opt/$toolchain_package.tar.bz2 | ||||||
|  | 
 | ||||||
|  | for file in /opt/$toolchain/bin/* ; do ln -s "${file}" "/usr/bin/$(basename ${file})" ; done | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Optional dependencies | ||||||
|  | 
 | ||||||
|  | - openocd (debugging/flashing over SWD) | ||||||
|  | - heatshrink (compiling image assets) | ||||||
|  | - clang-format (code formatting) | ||||||
|  | - dfu-util (flashing over USB DFU) | ||||||
|  | - protobuf (compiling proto sources) | ||||||
|  | 
 | ||||||
|  | For example, to install them on Debian, use: | ||||||
|  | ```sh | ||||||
|  | apt update | ||||||
|  | apt install openocd clang-format-13 dfu-util protobuf-compiler | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | heatshrink has to be compiled [from sources](https://github.com/atomicobject/heatshrink). | ||||||
|  | 
 | ||||||
|  | ## Compile everything | ||||||
|  | 
 | ||||||
|  | ```sh | ||||||
|  | make | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Check `dist/` for build outputs. | ||||||
|  | 
 | ||||||
|  | Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. | ||||||
|  | 
 | ||||||
| ## Flash everything | ## Flash everything | ||||||
| 
 | 
 | ||||||
|  | Connect your device via ST-Link and run: | ||||||
| ```sh | ```sh | ||||||
| docker-compose exec dev make -j$(nproc) whole | make whole | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Compile bootloader |  | ||||||
| 
 |  | ||||||
| ```sh |  | ||||||
| docker-compose exec dev make -j$(nproc) -C bootloader |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Bootloader compilation results: |  | ||||||
| * `bootloader/.obj/f7/bootloader.elf` |  | ||||||
| * `bootloader/.obj/f7/bootloader.hex` |  | ||||||
| * `bootloader/.obj/f7/bootloader.bin` |  | ||||||
| * **`bootloader/.obj/f7/bootloader.dfu`** - should be used to flash |  | ||||||
| 
 |  | ||||||
| ## Compile firmware |  | ||||||
| 
 |  | ||||||
| ```sh |  | ||||||
| docker-compose exec dev make -j$(nproc) -C firmware |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Firmware compilation results: |  | ||||||
| * `firmware/.obj/f7/firmware.elf` |  | ||||||
| * `firmware/.obj/f7/firmware.hex` |  | ||||||
| * `firmware/.obj/f7/firmware.bin` |  | ||||||
| * **`firmware/.obj/f7/firmware.dfu`** - should be used to flash |  | ||||||
| 
 |  | ||||||
| ## Concatenate bootloader and firmware |  | ||||||
| 
 |  | ||||||
| You might want to do this to distribute the firmware as a single file. |  | ||||||
| 
 |  | ||||||
| That's exactly how we generate our `full` builds. |  | ||||||
| 
 |  | ||||||
| 1. Concatenate HEX files: |  | ||||||
|    ```sh |  | ||||||
|    docker-compose exec dev srec_cat \ |  | ||||||
|     bootloader/.obj/f7/bootloader.hex -Intel \ |  | ||||||
|     firmware/.obj/f7/firmware.hex -Intel \ |  | ||||||
|     -o firmware/.obj/f7/full.hex -Intel |  | ||||||
|    ``` |  | ||||||
| 2. Convert HEX to DFU: |  | ||||||
|    ```sh |  | ||||||
|    docker-compose exec dev hex2dfu \ |  | ||||||
|     -i firmware/.obj/f7/full.hex \ |  | ||||||
|     -o firmware/.obj/f7/full.dfu \ |  | ||||||
|     -l "Flipper Zero F7" |  | ||||||
|    ``` |  | ||||||
| 
 |  | ||||||
| Finally, you will have **`firmware/.obj/f7/full.dfu`** file that can be distributed and flashed. |  | ||||||
| 
 |  | ||||||
| # Links | # Links | ||||||
| * Discord: [flipp.dev/discord](https://flipp.dev/discord) | * Discord: [flipp.dev/discord](https://flipp.dev/discord) | ||||||
| * Website: [flipperzero.one](https://flipperzero.one) | * Website: [flipperzero.one](https://flipperzero.one) | ||||||
| @ -198,4 +202,4 @@ Finally, you will have **`firmware/.obj/f7/full.dfu`** file that can be distribu | |||||||
|   * toolbox - toolbox of things that we are using but don't place in core |   * toolbox - toolbox of things that we are using but don't place in core | ||||||
|   * u8g2 - graphics library that we use to draw GUI |   * u8g2 - graphics library that we use to draw GUI | ||||||
| - make - make helpers | - make - make helpers | ||||||
| - scripts - supplimentary scripts | - scripts - supplementary scripts | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ ASM_SOURCES		+= $(wildcard src/*.s) | |||||||
| C_SOURCES		+= $(wildcard src/*.c) | C_SOURCES		+= $(wildcard src/*.c) | ||||||
| CPP_SOURCES		+= $(wildcard src/*.cpp) | CPP_SOURCES		+= $(wildcard src/*.cpp) | ||||||
| 
 | 
 | ||||||
| TARGET			?= f7 | include			$(PROJECT_ROOT)/make/defaults.mk | ||||||
| TARGET_DIR		= targets/$(TARGET) | TARGET_DIR		= targets/$(TARGET) | ||||||
| include			$(TARGET_DIR)/target.mk | include			$(TARGET_DIR)/target.mk | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,14 +8,12 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal | |||||||
|         clang-format-12 \ |         clang-format-12 \ | ||||||
|         dfu-util \ |         dfu-util \ | ||||||
|         openocd \ |         openocd \ | ||||||
|         srecord \ |  | ||||||
|         libncurses5 \ |         libncurses5 \ | ||||||
|         python-setuptools \ |         python-setuptools \ | ||||||
|         libpython2.7-dev \ |         libpython2.7-dev \ | ||||||
|         libxml2-dev \ |         libxml2-dev \ | ||||||
|         libxslt1-dev \ |         libxslt1-dev \ | ||||||
|         zlib1g-dev \ |         zlib1g-dev \ | ||||||
|         jq \ |  | ||||||
|         wget && \ |         wget && \ | ||||||
|     apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |     apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | ||||||
| 
 | 
 | ||||||
| @ -30,10 +28,6 @@ RUN wget --progress=dot:giga "https://developer.arm.com/-/media/Files/downloads/ | |||||||
| RUN wget --progress=dot:giga -O - https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2 && \ | RUN wget --progress=dot:giga -O - https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2 && \ | ||||||
|     pip install --no-cache-dir lxml==4.6.3 |     pip install --no-cache-dir lxml==4.6.3 | ||||||
| 
 | 
 | ||||||
| RUN git clone https://github.com/rusdacent/hex2dfu.git && \ |  | ||||||
|     cd hex2dfu && gcc hex2dfu.c ED25519/*.c -o hex2dfu && mv ./hex2dfu /usr/local/bin/hex2dfu  && \ |  | ||||||
|     hex2dfu -h |  | ||||||
| 
 |  | ||||||
| RUN git clone --depth 1 --branch v0.4.1 https://github.com/atomicobject/heatshrink.git && \ | RUN git clone --depth 1 --branch v0.4.1 https://github.com/atomicobject/heatshrink.git && \ | ||||||
|     cd heatshrink && make && mv ./heatshrink /usr/local/bin/heatshrink |     cd heatshrink && make && mv ./heatshrink /usr/local/bin/heatshrink | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ CFLAGS			+= -I$(PROJECT_ROOT) -Itargets/furi-hal-include | |||||||
| CFLAGS			+= -Werror -Wno-address-of-packed-member | CFLAGS			+= -Werror -Wno-address-of-packed-member | ||||||
| CPPFLAGS		+= -Werror | CPPFLAGS		+= -Werror | ||||||
| 
 | 
 | ||||||
| TARGET			?= f7 | include			$(PROJECT_ROOT)/make/defaults.mk | ||||||
| TARGET_DIR		= targets/$(TARGET) | TARGET_DIR		= targets/$(TARGET) | ||||||
| include			$(TARGET_DIR)/target.mk | include			$(TARGET_DIR)/target.mk | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								make/defaults.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								make/defaults.mk
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | TARGET	?= f7 | ||||||
|  | export TARGET | ||||||
| @ -2,7 +2,7 @@ GIT_COMMIT		:= $(shell git rev-parse --short HEAD || echo 'unknown') | |||||||
| GIT_BRANCH		:= $(shell echo $${WORKFLOW_BRANCH_OR_TAG-$$(git rev-parse --abbrev-ref HEAD || echo 'unknown')}) | GIT_BRANCH		:= $(shell echo $${WORKFLOW_BRANCH_OR_TAG-$$(git rev-parse --abbrev-ref HEAD || echo 'unknown')}) | ||||||
| GIT_BRANCH_NUM	:= $(shell git rev-list --count HEAD || echo 'nan') | GIT_BRANCH_NUM	:= $(shell git rev-list --count HEAD || echo 'nan') | ||||||
| BUILD_DATE		:= $(shell date '+%d-%m-%Y' || echo 'unknown') | BUILD_DATE		:= $(shell date '+%d-%m-%Y' || echo 'unknown') | ||||||
| VERSION			:= $(shell git describe --tags --abbrev=0 --exact-match || echo 'unknown') | VERSION			:= $(shell git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo 'unknown') | ||||||
| 
 | 
 | ||||||
| CFLAGS += \
 | CFLAGS += \
 | ||||||
| 	-DGIT_COMMIT=\"$(GIT_COMMIT)\" \
 | 	-DGIT_COMMIT=\"$(GIT_COMMIT)\" \
 | ||||||
|  | |||||||
| @ -33,6 +33,7 @@ CHECK_AND_REINIT_SUBMODULES_SHELL=\ | |||||||
| $(info $(shell $(CHECK_AND_REINIT_SUBMODULES_SHELL))) | $(info $(shell $(CHECK_AND_REINIT_SUBMODULES_SHELL))) | ||||||
| 
 | 
 | ||||||
| all: $(OBJ_DIR)/$(PROJECT).elf $(OBJ_DIR)/$(PROJECT).hex $(OBJ_DIR)/$(PROJECT).bin $(OBJ_DIR)/$(PROJECT).dfu $(OBJ_DIR)/$(PROJECT).json | all: $(OBJ_DIR)/$(PROJECT).elf $(OBJ_DIR)/$(PROJECT).hex $(OBJ_DIR)/$(PROJECT).bin $(OBJ_DIR)/$(PROJECT).dfu $(OBJ_DIR)/$(PROJECT).json | ||||||
|  | 	@: | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/$(PROJECT).elf: $(OBJECTS) | $(OBJ_DIR)/$(PROJECT).elf: $(OBJECTS) | ||||||
| 	@echo "\tLD\t" $@ | 	@echo "\tLD\t" $@ | ||||||
| @ -47,27 +48,28 @@ $(OBJ_DIR)/$(PROJECT).bin: $(OBJ_DIR)/$(PROJECT).elf | |||||||
| 	@echo "\tBIN\t" $@ | 	@echo "\tBIN\t" $@ | ||||||
| 	@$(BIN) $< $@ | 	@$(BIN) $< $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/$(PROJECT).dfu: $(OBJ_DIR)/$(PROJECT).hex | $(OBJ_DIR)/$(PROJECT).dfu: $(OBJ_DIR)/$(PROJECT).bin | ||||||
| 	@echo "\tDFU\t" $@ | 	@echo "\tDFU\t" $@ | ||||||
| 	@hex2dfu \
 | 	@../scripts/bin2dfu.py \
 | ||||||
| 		-i $(OBJ_DIR)/$(PROJECT).hex \
 | 		-i $(OBJ_DIR)/$(PROJECT).bin \
 | ||||||
| 		-o $(OBJ_DIR)/$(PROJECT).dfu \
 | 		-o $(OBJ_DIR)/$(PROJECT).dfu \
 | ||||||
|  | 		-a $(FLASH_ADDRESS) \
 | ||||||
| 		-l "Flipper Zero $(shell echo $(TARGET) | tr a-z A-Z)" > /dev/null | 		-l "Flipper Zero $(shell echo $(TARGET) | tr a-z A-Z)" > /dev/null | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/$(PROJECT).json: $(OBJ_DIR)/$(PROJECT).dfu | $(OBJ_DIR)/$(PROJECT).json: $(OBJ_DIR)/$(PROJECT).dfu | ||||||
| 	@echo "\tJSON\t" $@ | 	@echo "\tJSON\t" $@ | ||||||
| 	@python3 ../scripts/meta.py -p $(PROJECT) $(CFLAGS) > $(OBJ_DIR)/$(PROJECT).json | 	@../scripts/meta.py generate -p $(PROJECT) $(CFLAGS) > $(OBJ_DIR)/$(PROJECT).json | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS | $(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tCC\t" $< "->" $@ | 	@echo "\tCC\t" $(subst $(PROJECT_ROOT)/,,$(realpath $<)) "->" $@ | ||||||
| 	@$(CC) $(CFLAGS) -c $< -o $@ | 	@$(CC) $(CFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS | $(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tASM\t" $< "->" $@ | 	@echo "\tASM\t" $(subst $(PROJECT_ROOT)/,,$(realpath $<)) "->" $@ | ||||||
| 	@$(AS) $(CFLAGS) -c $< -o $@ | 	@$(AS) $(CFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS | $(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tCPP\t" $< "->" $@ | 	@echo "\tCPP\t" $(subst $(PROJECT_ROOT)/,,$(realpath $<)) "->" $@ | ||||||
| 	@$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ | 	@$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/flash: $(OBJ_DIR)/$(PROJECT).bin | $(OBJ_DIR)/flash: $(OBJ_DIR)/$(PROJECT).bin | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								scripts/bin2dfu.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										70
									
								
								scripts/bin2dfu.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import struct | ||||||
|  | from zlib import crc32 | ||||||
|  | 
 | ||||||
|  | from flipper.app import App | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Main(App): | ||||||
|  |     def init(self): | ||||||
|  |         self.parser.add_argument("-i", "--input", help=".bin input path", required=True) | ||||||
|  |         self.parser.add_argument( | ||||||
|  |             "-o", "--output", help=".dfu output path", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser.add_argument( | ||||||
|  |             "-a", | ||||||
|  |             "--address", | ||||||
|  |             help="Flash address", | ||||||
|  |             type=lambda x: int(x, 0), | ||||||
|  |             required=True, | ||||||
|  |         ) | ||||||
|  |         self.parser.add_argument( | ||||||
|  |             "-l", "--label", help="DFU Target label", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser.add_argument( | ||||||
|  |             "--vid", help="USB Vendor ID", default=0x0483, type=lambda x: int(x, 0) | ||||||
|  |         ) | ||||||
|  |         self.parser.add_argument( | ||||||
|  |             "--pid", help="USB Product ID", default=0xDF11, type=lambda x: int(x, 0) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         self.parser.set_defaults(func=self.convert) | ||||||
|  | 
 | ||||||
|  |     def convert(self): | ||||||
|  |         if not os.path.exists(self.args.input): | ||||||
|  |             self.logger.error(f'"{self.args.input}" does not exist') | ||||||
|  |             return 1 | ||||||
|  | 
 | ||||||
|  |         with open(self.args.input, mode="rb") as file: | ||||||
|  |             bin = file.read() | ||||||
|  | 
 | ||||||
|  |         data = struct.pack("<II", self.args.address, len(bin)) + bin | ||||||
|  | 
 | ||||||
|  |         # Target prefix | ||||||
|  |         szTargetName = self.args.label.encode("ascii") | ||||||
|  | 
 | ||||||
|  |         data = ( | ||||||
|  |             struct.pack("<6sBI255sII", b"Target", 0, 1, szTargetName, len(data), 1) | ||||||
|  |             + data | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         # Prefix | ||||||
|  |         data = struct.pack("<5sBIB", b"DfuSe", 0x01, len(data) + 11, 1) + data | ||||||
|  | 
 | ||||||
|  |         # Suffix | ||||||
|  |         data += struct.pack( | ||||||
|  |             "<HHHH3sB", 0xFFFF, self.args.pid, self.args.vid, 0x011A, b"UFD", 16 | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         dwCRC = ~crc32(data) & 0xFFFFFFFF | ||||||
|  | 
 | ||||||
|  |         data += struct.pack("<I", dwCRC) | ||||||
|  | 
 | ||||||
|  |         open(self.args.output, "wb").write(data) | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     Main()() | ||||||
							
								
								
									
										52
									
								
								scripts/dist.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										52
									
								
								scripts/dist.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | 
 | ||||||
|  | set -e | ||||||
|  | 
 | ||||||
|  | suffix="${DIST_SUFFIX:=local}" | ||||||
|  | 
 | ||||||
|  | rm -rf "dist/${TARGET}" | ||||||
|  | mkdir -p "dist/${TARGET}" | ||||||
|  | 
 | ||||||
|  | # copy build outputs | ||||||
|  | cp bootloader/.obj/${TARGET}/bootloader.elf \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.elf | ||||||
|  | cp bootloader/.obj/${TARGET}/bootloader.bin \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.bin | ||||||
|  | cp bootloader/.obj/${TARGET}/bootloader.dfu \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.dfu | ||||||
|  | cp bootloader/.obj/${TARGET}/bootloader.json \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.json | ||||||
|  | cp firmware/.obj/${TARGET}/firmware.elf \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.elf | ||||||
|  | cp firmware/.obj/${TARGET}/firmware.bin \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.bin | ||||||
|  | cp firmware/.obj/${TARGET}/firmware.dfu \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.dfu | ||||||
|  | cp firmware/.obj/${TARGET}/firmware.json \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.json | ||||||
|  | 
 | ||||||
|  | # generate full.bin | ||||||
|  | cp dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.bin \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.bin | ||||||
|  | dd if=/dev/null of=dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.bin bs=1 count=0 seek=32768 2> /dev/null | ||||||
|  | cat dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.bin \ | ||||||
|  |     >>dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.bin \ | ||||||
|  |     2> /dev/null | ||||||
|  | 
 | ||||||
|  | # generate full.dfu | ||||||
|  | ./scripts/bin2dfu.py \ | ||||||
|  |     -i dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.bin \ | ||||||
|  |     -o dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.dfu \ | ||||||
|  |     -a 0x08000000 \ | ||||||
|  |     -l "Flipper Zero $(echo ${TARGET} | tr a-z A-Z)" | ||||||
|  | 
 | ||||||
|  | # generate full.json | ||||||
|  | ./scripts/meta.py merge \ | ||||||
|  |     -i dist/${TARGET}/flipper-z-${TARGET}-bootloader-${suffix}.json \ | ||||||
|  |     dist/${TARGET}/flipper-z-${TARGET}-firmware-${suffix}.json \ | ||||||
|  |     >dist/${TARGET}/flipper-z-${TARGET}-full-${suffix}.json | ||||||
|  | 
 | ||||||
|  | echo "Firmware binaries can be found at:" | ||||||
|  | echo -e "\t$(pwd)/dist/${TARGET}" | ||||||
|  | echo "Use this file to flash your Flipper:" | ||||||
|  | echo -e "\tflipper-z-${TARGET}-full-${suffix}.dfu" | ||||||
| @ -15,7 +15,7 @@ class App: | |||||||
|         self.init() |         self.init() | ||||||
| 
 | 
 | ||||||
|     def __call__(self): |     def __call__(self): | ||||||
|         self.args = self.parser.parse_args() |         self.args, _ = self.parser.parse_known_args() | ||||||
|         if "func" not in self.args: |         if "func" not in self.args: | ||||||
|             self.parser.error("Choose something to do") |             self.parser.error("Choose something to do") | ||||||
|         # configure log output |         # configure log output | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								scripts/meta.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										53
									
								
								scripts/meta.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -1,31 +1,58 @@ | |||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| 
 | 
 | ||||||
| import argparse | from flipper.app import App | ||||||
| import json | import json | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Main: | class Main(App): | ||||||
|     def __init__(self): |     def init(self): | ||||||
|         # parse CFLAGS |         self.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
|         self.parser = argparse.ArgumentParser(allow_abbrev=False) |  | ||||||
|         self.parser.add_argument("-p", dest="project", required=True) |  | ||||||
|         self.parser.add_argument("-DBUILD_DATE", dest="build_date", required=True) |  | ||||||
|         self.parser.add_argument("-DGIT_COMMIT", dest="commit", required=True) |  | ||||||
|         self.parser.add_argument("-DGIT_BRANCH", dest="branch", required=True) |  | ||||||
|         self.parser.add_argument("-DTARGET", dest="target", type=int, required=True) |  | ||||||
| 
 | 
 | ||||||
|     def __call__(self): |         # generate | ||||||
|         self.args, _ = self.parser.parse_known_args() |         self.parser_generate = self.subparsers.add_parser( | ||||||
|  |             "generate", help="Generate JSON meta file" | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument("-p", dest="project", required=True) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "-DBUILD_DATE", dest="build_date", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument("-DGIT_COMMIT", dest="commit", required=True) | ||||||
|  |         self.parser_generate.add_argument("-DGIT_BRANCH", dest="branch", required=True) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "-DTARGET", dest="target", type=int, required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.set_defaults(func=self.generate) | ||||||
| 
 | 
 | ||||||
|  |         # merge | ||||||
|  |         self.parser_merge = self.subparsers.add_parser( | ||||||
|  |             "merge", help="Merge JSON meta files" | ||||||
|  |         ) | ||||||
|  |         self.parser_merge.add_argument( | ||||||
|  |             "-i", dest="input", action="append", nargs="+", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_merge.set_defaults(func=self.merge) | ||||||
|  | 
 | ||||||
|  |     def generate(self): | ||||||
|         meta = {} |         meta = {} | ||||||
|         for k, v in vars(self.args).items(): |         for k, v in vars(self.args).items(): | ||||||
|             if k == "project": |             if k == "project" or k == "func": | ||||||
|                 continue |                 continue | ||||||
|             if isinstance(v, str): |             if isinstance(v, str): | ||||||
|                 v = v.strip('"') |                 v = v.strip('"') | ||||||
|             meta[self.args.project + "_" + k] = v |             meta[self.args.project + "_" + k] = v | ||||||
| 
 | 
 | ||||||
|         print(json.dumps(meta, indent=4)) |         print(json.dumps(meta, indent=4)) | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  |     def merge(self): | ||||||
|  |         full = {} | ||||||
|  |         for path in self.args.input[0]: | ||||||
|  |             with open(path, mode="r") as file: | ||||||
|  |                 dict = json.loads(file.read()) | ||||||
|  |                 full |= dict | ||||||
|  | 
 | ||||||
|  |         print(json.dumps(full, indent=4)) | ||||||
|  |         return 0 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anna Prosvetova
						Anna Prosvetova