@@ -155,6 +155,11 @@ def options(opt):
155
155
action = 'store_true' ,
156
156
default = False ,
157
157
help = 'Add debug symbolds to build.' )
158
+
159
+ g .add_option ('--vs-launch' ,
160
+ action = 'store_true' ,
161
+ default = False ,
162
+ help = 'Generate launch.json template for Visual Studio Code.' )
158
163
159
164
g .add_option ('--disable-watchdog' ,
160
165
action = 'store_true' ,
@@ -502,6 +507,7 @@ def configure(cfg):
502
507
503
508
cfg .env .BOARD = cfg .options .board
504
509
cfg .env .DEBUG = cfg .options .debug
510
+ cfg .env .VS_LAUNCH = cfg .options .vs_launch
505
511
cfg .env .DEBUG_SYMBOLS = cfg .options .debug_symbols
506
512
cfg .env .COVERAGE = cfg .options .coverage
507
513
cfg .env .FORCE32BIT = cfg .options .force_32bit
@@ -607,6 +613,13 @@ def configure(cfg):
607
613
else :
608
614
cfg .end_msg ('disabled' , color = 'YELLOW' )
609
615
616
+ if cfg .env .DEBUG :
617
+ cfg .start_msg ('VS Code launch' )
618
+ if cfg .env .VS_LAUNCH :
619
+ cfg .end_msg ('enabled' )
620
+ else :
621
+ cfg .end_msg ('disabled' , color = 'YELLOW' )
622
+
610
623
cfg .start_msg ('Coverage build' )
611
624
if cfg .env .COVERAGE :
612
625
cfg .end_msg ('enabled' )
@@ -652,6 +665,9 @@ def configure(cfg):
652
665
cfg .remove_target_list ()
653
666
_collect_autoconfig_files (cfg )
654
667
668
+ if cfg .env .VS_LAUNCH :
669
+ _create_vscode_launch_json (cfg )
670
+
655
671
def collect_dirs_to_recurse (bld , globs , ** kw ):
656
672
dirs = []
657
673
globs = Utils .to_list (globs )
@@ -875,6 +891,132 @@ def _load_pre_build(bld):
875
891
if getattr (brd , 'pre_build' , None ):
876
892
brd .pre_build (bld )
877
893
894
+ def _create_vscode_launch_json (cfg ):
895
+ launch_json_path = os .path .join (cfg .srcnode .abspath (), '.vscode' , 'launch.json' )
896
+ if os .path .exists (launch_json_path ):
897
+ default_template = {
898
+ "version" : "0.2.0" ,
899
+ "configurations" : []
900
+ }
901
+ try :
902
+ with open (launch_json_path , 'r' ) as f :
903
+ content = f .read ().strip ()
904
+ if content :
905
+ launch_json = json .loads (content )
906
+ else :
907
+ launch_json = default_template
908
+ if "configurations" not in launch_json :
909
+ launch_json ["configurations" ] = [] #initialize configurations
910
+ if type (launch_json ["configurations" ]) is not list :
911
+ launch_json ["configurations" ] = [] #overwrite invalid configurations
912
+ except json .JSONDecodeError :
913
+ print (f"\033 [91mError: Invalid JSON in { launch_json_path } . Creating a new launch.json file.\033 [0m" )
914
+ launch_json = default_template
915
+ else :
916
+ launch_json = default_template
917
+
918
+ configurations = [
919
+ {'name' : 'ArduCopter' , 'target' : 'arducopter' },
920
+ {'name' : 'ArduPlane' , 'target' : 'arduplane' },
921
+ {'name' : 'ArduCopter-Heli' , 'target' : 'arducopter-heli' },
922
+ {'name' : 'ArduRover' , 'target' : 'ardurover' },
923
+ {'name' : 'ArduSub' , 'target' : 'ardusub' },
924
+ {'name' : 'AP_Periph' , 'target' : 'AP_Periph' },
925
+ {'name' : 'AP_Blimp' , 'target' : 'blimp' },
926
+ {'name' : 'AntennaTracker' , 'target' : 'antennatracker' },
927
+ {'name' : 'AP_Bootloader' , 'target' : 'ap_bootloader' },
928
+ ] #pending to add more targets
929
+
930
+ for configuration in configurations :
931
+ if cfg .options .board == 'sitl' :
932
+ if configuration ['name' ] == 'AP_Bootloader' :
933
+ continue
934
+ launch_configuration = {
935
+ "name" : configuration ['name' ],
936
+ "type" : "cppdbg" ,
937
+ "request" : "launch" ,
938
+ "program" : "${workspaceFolder}/build/sitl/bin/" + configuration ['target' ],
939
+ "args" : [
940
+ "-S" ,
941
+ "--model" ,
942
+ "+" ,
943
+ "--speedup" ,
944
+ "1" ,
945
+ "--slave" ,
946
+ "0" ,
947
+ "--sim-address=127.0.0.1" ,
948
+ "-I0"
949
+ ],
950
+ "stopAtEntry" : False ,
951
+ "cwd" : "${workspaceFolder}" ,
952
+ "environment" : [],
953
+ "externalConsole" : False ,
954
+ "MIMode" : "lldb" ,
955
+ "setupCommands" : [
956
+ {
957
+ "description" : "Enable pretty-printing for gdb" ,
958
+ "text" : "-enable-pretty-printing" ,
959
+ "ignoreFailures" : False
960
+ }
961
+ ],
962
+ }
963
+ else :
964
+ if configuration ['name' ] == 'AP_Bootloader' :
965
+ executable_path = "${workspaceFolder}/build/" + cfg .options .board + "/bootloader/AP_Bootloader"
966
+ else :
967
+ executable_path = "${workspaceFolder}/build/" + cfg .options .board + "/bin/" + configuration ['target' ]
968
+ launch_configuration = {
969
+ "name" : configuration ['name' ],
970
+ "cwd" : "${workspaceFolder}" ,
971
+ "executable" : executable_path ,
972
+ "liveWatch" : {
973
+ "enabled" : True ,
974
+ "samplesPerSecond" : 4
975
+ },
976
+ "request" : "launch" ,
977
+ "type" : "cortex-debug" ,
978
+ "servertype" : "openocd" ,
979
+ "configFiles" : [
980
+ "${workspaceFolder}/build/" + cfg .options .board + "/openocd.cfg" ,
981
+ ]
982
+ }
983
+
984
+ configuration_overwrited = False
985
+ for index , current_configuration in enumerate (launch_json ["configurations" ]):
986
+ if current_configuration .get ('name' ) == launch_configuration ['name' ]:
987
+ launch_json ["configurations" ][index ] = launch_configuration
988
+ configuration_overwrited = True
989
+ break
990
+ if not configuration_overwrited :
991
+ launch_json ["configurations" ].append (launch_configuration )
992
+
993
+ with open (launch_json_path , 'w' ) as f :
994
+ json .dump (launch_json , f , indent = 4 )
995
+
996
+ #create openocd.cfg file
997
+ if cfg .options .board != 'sitl' :
998
+ openocd_cfg_path = os .path .join (cfg .srcnode .abspath (), 'build' , cfg .options .board , 'openocd.cfg' )
999
+ mcu_type = cfg .env .get_flat ('APJ_BOARD_TYPE' )
1000
+ openocd_target = ''
1001
+ if mcu_type .startswith ("STM32H7" ):
1002
+ openocd_target = 'stm32h7x.cfg'
1003
+ elif mcu_type .startswith ("STM32F7" ):
1004
+ openocd_target = 'stm32f7x.cfg'
1005
+ elif mcu_type .startswith ("STM32F4" ):
1006
+ openocd_target = 'stm32f4x.cfg'
1007
+ elif mcu_type .startswith ("STM32F3" ):
1008
+ openocd_target = 'stm32f3x.cfg'
1009
+ elif mcu_type .startswith ("STM32L4" ):
1010
+ openocd_target = 'stm32l4x.cfg'
1011
+ elif mcu_type .startswith ("STM32G4" ):
1012
+ openocd_target = 'stm32g4x.cfg'
1013
+
1014
+ with open (openocd_cfg_path , 'w+' ) as f :
1015
+ f .write ("source [find interface/stlink-v2.cfg]\n " )
1016
+ f .write (f"source [find target/{ openocd_target } ]\n " )
1017
+ f .write ("init\n " )
1018
+ f .write ("$_TARGETNAME configure -rtos auto\n " )
1019
+
878
1020
def build (bld ):
879
1021
config_hash = Utils .h_file (bld .bldnode .make_node ('ap_config.h' ).abspath ())
880
1022
bld .env .CCDEPS = config_hash
0 commit comments