libxr 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env python
2
+
3
+ import os
4
+ import subprocess
5
+ import argparse
6
+
7
+ def run_command(command):
8
+ """Run a shell command and check the return value."""
9
+ result = subprocess.run(command, shell=True, capture_output=True, text=True)
10
+ if result.returncode == 0:
11
+ print(f"✅ Command executed successfully: {command}")
12
+ else:
13
+ print(f"❌ Command failed: {command}")
14
+ print(result.stderr)
15
+ exit(1)
16
+
17
+ def find_ioc_file(directory):
18
+ """Search for a .ioc file in the specified directory."""
19
+ for file in os.listdir(directory):
20
+ if file.endswith(".ioc"):
21
+ return os.path.join(directory, file)
22
+ return None
23
+
24
+ def initialize_git_repository(project_dir):
25
+ """Initialize a Git repository if not already present."""
26
+ git_dir = os.path.join(project_dir, ".git")
27
+ if not os.path.exists(git_dir):
28
+ print(f"❌ Directory {project_dir} is not a Git repository. Initializing Git...")
29
+ run_command(f"git init {project_dir}")
30
+
31
+ def create_gitignore_file(project_dir):
32
+ """Create a .gitignore file if it does not exist."""
33
+ gitignore_path = os.path.join(project_dir, ".gitignore")
34
+ if not os.path.exists(gitignore_path):
35
+ print(f"📝 Creating .gitignore file...")
36
+ with open(gitignore_path, "w") as gitignore_file:
37
+ gitignore_file.write("""build/**
38
+ .history/**
39
+ .cache/**
40
+ .config.json
41
+ """)
42
+
43
+ def add_git_submodule(project_dir):
44
+ """Add the LibXR submodule if not already present."""
45
+ libxr_path = os.path.join(project_dir, "Middlewares/Third_Party/LibXR")
46
+ if not os.path.exists(libxr_path):
47
+ print("❌ Middlewares/Third_Party/LibXR not found. Adding submodule...")
48
+ run_command(f"cd {project_dir} && git submodule add https://github.com/Jiu-Xiao/libxr.git ./Middlewares/Third_Party/LibXR")
49
+
50
+ def create_user_directory(project_dir):
51
+ """Ensure the User directory exists."""
52
+ user_path = os.path.join(project_dir, "User")
53
+ if not os.path.exists(user_path):
54
+ os.makedirs(user_path)
55
+ return user_path
56
+
57
+ def process_ioc_file(project_dir, json_output):
58
+ """Parse the .ioc file and generate JSON configuration."""
59
+ print("🔄 Parsing .ioc file...")
60
+ run_command(f"libxr_parse_ioc -d {project_dir} -o {json_output}")
61
+
62
+ def generate_cpp_code(json_output, cpp_output):
63
+ """Generate C++ code from JSON configuration."""
64
+ print("🔄 Generating C++ code...")
65
+ run_command(f"libxr_generate_code -i {json_output} -o {cpp_output}")
66
+
67
+ def modify_stm32_interrupts(project_dir):
68
+ """Modify STM32 interrupt handler files."""
69
+ print("🔄 Modifying STM32 interrupt files...")
70
+ run_command(f"libxr_generate_stm32_it {os.path.join(project_dir, 'Core/Src')}")
71
+
72
+ def generate_cmake_file(project_dir):
73
+ """Generate CMakeLists.txt for STM32 project."""
74
+ print("🔄 Generating CMakeLists.txt...")
75
+ run_command(f"libxr_generate_stm32_cmake {project_dir}")
76
+
77
+ def main():
78
+ parser = argparse.ArgumentParser(description="Automate STM32CubeMX project setup")
79
+ parser.add_argument("-d", "--directory", required=True, help="STM32CubeMX project directory")
80
+ parser.add_argument("-t", "--terminal", default="", help="Optional terminal device source")
81
+ args = parser.parse_args()
82
+
83
+ project_dir = args.directory.rstrip("/")
84
+ terminal_source = args.terminal
85
+
86
+ if not os.path.isdir(project_dir):
87
+ print(f"❌ Directory {project_dir} does not exist")
88
+ exit(1)
89
+
90
+ # Initialize Git repository and .gitignore
91
+ initialize_git_repository(project_dir)
92
+ create_gitignore_file(project_dir)
93
+
94
+ # Add Git submodule if necessary
95
+ add_git_submodule(project_dir)
96
+
97
+ # Find .ioc file
98
+ ioc_file = find_ioc_file(project_dir)
99
+ if not ioc_file:
100
+ print("❌ No .ioc file found")
101
+ exit(1)
102
+
103
+ print(f"📂 Found .ioc file: {ioc_file}")
104
+
105
+ # Create user directory
106
+ user_path = create_user_directory(project_dir)
107
+
108
+ # Define paths
109
+ json_output = os.path.join(project_dir, ".config.json")
110
+ cpp_output = os.path.join(user_path, "app_main.cpp")
111
+
112
+ # Process .ioc file
113
+ process_ioc_file(project_dir, json_output)
114
+
115
+ # Generate C++ code
116
+ generate_cpp_code(json_output, cpp_output)
117
+
118
+ # Modify STM32 interrupt handlers
119
+ modify_stm32_interrupts(project_dir)
120
+
121
+ # Generate CMakeLists.txt
122
+ generate_cmake_file(project_dir)
123
+
124
+ # Handle optional terminal source
125
+ if terminal_source:
126
+ print("🔄 Modifying terminal device source...")
127
+
128
+ print("✅ All tasks completed successfully!")
libxr/GeneratorCode.py ADDED
@@ -0,0 +1,454 @@
1
+ #!/usr/bin/env python
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ import sys
7
+
8
+ libxr_config = {
9
+ "terminal_source": "",
10
+ "software_timer": {"priority": 2, "stack_depth": 512},
11
+ "SPI": {},
12
+ "I2C": {},
13
+ "USART": {},
14
+ "USB": {},
15
+ "ADC": {},
16
+ "TIM": {},
17
+ "CAN": {},
18
+ "FDCAN": {},
19
+ }
20
+
21
+ def load_json(file_path):
22
+ """Load JSON configuration file."""
23
+ with open(file_path, "r", encoding="utf-8") as f:
24
+ return json.load(f)
25
+
26
+
27
+ def gpio_alias(port, gpio_data):
28
+ """Generate GPIO configuration code, supporting CubeMX macros and unaliased cases."""
29
+ label = gpio_data.get("Label") # Could be empty
30
+ is_exti = gpio_data.get("GPXTI", False) # Whether it's an EXTI interrupt pin
31
+
32
+ if label:
33
+ # **Alias exists** → Use CubeMX predefined macros
34
+ pin_define = f"{label}_Pin"
35
+ port_define = f"{label}_GPIO_Port"
36
+ irq_define = f"{label}_EXTI_IRQn" if is_exti else None
37
+ else:
38
+ # **No alias** → Directly use GPIOx, GPIO_PIN_x
39
+ parts = port.split("-")
40
+ port_define = f"GPIO{parts[0][1]}" # E.g., "PA4" → "GPIOA"
41
+ pin_define = f"GPIO_PIN_{parts[0][2:]}" # E.g., "PA4" → "GPIO_PIN_4"
42
+
43
+ # Calculate EXTI_IRQn
44
+ pin_num = int(parts[0][2:])
45
+ if is_exti:
46
+ if 5 <= pin_num <= 9:
47
+ irq_define = "EXTI9_5_IRQn"
48
+ elif 10 <= pin_num <= 15:
49
+ irq_define = "EXTI15_10_IRQn"
50
+ else:
51
+ irq_define = f"EXTI{pin_num}_IRQn"
52
+ else:
53
+ irq_define = None
54
+
55
+ # **Final formatted output**
56
+ if irq_define:
57
+ return f"{label or port}({port_define}, {pin_define}, {irq_define})"
58
+ return f"{label or port}({port_define}, {pin_define})"
59
+
60
+
61
+ def generate_dma_buffers(periph, instance, buffer_sizes):
62
+ """Generate DMA buffers for peripherals requiring DMA."""
63
+ if periph in ["SPI", "USART"]:
64
+ # Get USART configuration
65
+ tx_buffer_size = None
66
+ rx_buffer_size = None
67
+ if libxr_config.get(periph):
68
+ buffer_size = libxr_config[periph].get(instance, None)
69
+ else:
70
+ buffer_size = None
71
+
72
+ if buffer_size is None:
73
+ rx_buffer_size = buffer_sizes[periph]
74
+ tx_buffer_size = buffer_sizes[periph]
75
+ libxr_config[periph][instance] = {"tx_buffer_size": tx_buffer_size, "rx_buffer_size": rx_buffer_size}
76
+ else:
77
+ tx_buffer_size = buffer_size["tx_buffer_size"]
78
+ rx_buffer_size = buffer_size["rx_buffer_size"]
79
+
80
+ return f"static uint8_t {instance.lower()}_buff_tx[{tx_buffer_size}], {instance.lower()}_buff_rx[{rx_buffer_size}];\n"
81
+ if periph in ["I2C", "ADC"]:
82
+ # Get I2C configuration
83
+ if libxr_config.get(periph):
84
+ buffer_size = libxr_config[periph].get(instance, None)
85
+ else:
86
+ buffer_size = None
87
+
88
+ if buffer_size is None:
89
+ buffer_size = buffer_sizes[periph]
90
+ libxr_config[periph][instance] = {"buffer_size": buffer_size}
91
+ else:
92
+ buffer_size = buffer_size["buffer_size"]
93
+ return f"static uint8_t {instance.lower()}_buffer[{buffer_size}];\n"
94
+ return "" # Other peripherals don't need DMA
95
+
96
+
97
+ def generate_gpio_config(project_data):
98
+ """Generate GPIO configuration code."""
99
+ gpio_section = "\n // GPIO Configuration\n"
100
+ for port, config in project_data["GPIO"].items():
101
+ gpio_section += f" LibXR::STM32GPIO {gpio_alias(port, config)};\n"
102
+ return gpio_section
103
+
104
+
105
+ def generate_extern_config(project_data, buffer_sizes):
106
+ """Generate peripheral instantiation code and allocate DMA buffers if needed."""
107
+ dma_section = "\n// DMA Buffers\n"
108
+ externs = set()
109
+
110
+ for periph, instances in project_data["Peripherals"].items():
111
+ for instance, config in instances.items():
112
+ # Handle extern definitions
113
+ if periph == "USART" or periph == "UART":
114
+ externs.add(
115
+ f"extern UART_HandleTypeDef h{instance.lower().replace('usart', 'uart')};"
116
+ )
117
+ elif periph == "USB":
118
+ mode = config.get("Mode", "")
119
+ if "DEVICE" in instance.upper() or mode == "Device_Only":
120
+ externs.add("extern USBD_HandleTypeDef hUsbDeviceFS;")
121
+ elif "OTG_FS" in instance.upper():
122
+ externs.add("extern USBD_HandleTypeDef hUsbOtgFS;")
123
+ else:
124
+ externs.add(f"extern USBD_HandleTypeDef h{instance.lower()};")
125
+ else:
126
+ externs.add(f"extern {periph}_HandleTypeDef h{instance.lower()};")
127
+
128
+ # Generate DMA Buffers
129
+ if periph not in ["TIM", "USB", "CAN", "FDCAN"]:
130
+ dma_section += generate_dma_buffers(periph, instance, buffer_sizes)
131
+
132
+ return "\n".join(sorted(externs)) + "\n" + dma_section
133
+
134
+
135
+ def generate_peripherals_config(project_data):
136
+ """Generate peripheral instantiation code and assign DMA buffers."""
137
+ periph_section = "\n // Peripheral Configuration\n"
138
+ adc_channels = ""
139
+ pwm_section = ""
140
+
141
+ for periph, instances in project_data["Peripherals"].items():
142
+ for instance, config in instances.items():
143
+
144
+ # ADC
145
+ if periph == "ADC":
146
+ dma_enabled = (
147
+ config.get("DMA", "DISABLE") == "ENABLE"
148
+ ) # Default "DISABLE" if missing
149
+ conversion_key = "RegularConversions" if dma_enabled else "Channels"
150
+
151
+ # Ensure conversions are in list format
152
+ conversions = config.get(conversion_key, [])
153
+ if isinstance(conversions, str):
154
+ conversions = list(eval(conversions)) # Parse string safely
155
+
156
+ adc_channels += (
157
+ f" std::array<uint32_t, {len(conversions)}> {instance.lower()}_channels = "
158
+ f"{{ {', '.join(conversions)} }};\n"
159
+ )
160
+ periph_section += (
161
+ f" LibXR::STM32ADC {instance.lower()}(&h{instance.lower()}, "
162
+ f"RawData({instance.lower()}_buffer), {instance.lower()}_channels, 3.3f);\n"
163
+ )
164
+ elif periph == "FDCAN":
165
+ periph_section += (
166
+ f" LibXR::STM32CANFD {instance.lower()}(&h{instance.lower()}, "
167
+ f'"{instance.lower()}", 5);\n'
168
+ )
169
+ elif periph == "CAN":
170
+ periph_section += f' LibXR::STM32CAN {instance.lower()}(&h{instance.lower()}, "{instance.lower()}", 10);\n'
171
+ elif periph == "SPI":
172
+ tx_dma_enabled = config.get("DMA_TX", "DISABLE") == "ENABLE"
173
+ rx_dma_enabled = config.get("DMA_RX", "DISABLE") == "ENABLE"
174
+
175
+ tx_buffer = (
176
+ f"{instance.lower()}_buff_tx" if tx_dma_enabled else "{nullptr, 0}"
177
+ )
178
+ rx_buffer = (
179
+ f"{instance.lower()}_buff_rx" if rx_dma_enabled else "{nullptr, 0}"
180
+ )
181
+
182
+ periph_section += f" LibXR::STM32{periph} {instance.lower()}(&h{instance.lower()}, {tx_buffer}, {rx_buffer});\n"
183
+ elif periph == "USART":
184
+ tx_dma_enabled = config.get("DMA_TX", "DISABLE") == "ENABLE"
185
+ rx_dma_enabled = config.get("DMA_RX", "DISABLE") == "ENABLE"
186
+
187
+ tx_buffer = (
188
+ f"{instance.lower()}_buff_tx" if tx_dma_enabled else "{nullptr, 0}"
189
+ )
190
+ rx_buffer = (
191
+ f"{instance.lower()}_buff_rx" if rx_dma_enabled else "{nullptr, 0}"
192
+ )
193
+
194
+ periph_section += (
195
+ (
196
+ f" LibXR::STM32{periph} {instance.lower()}(&h{instance.lower()}, {tx_buffer}, {rx_buffer});\n"
197
+ )
198
+ .replace("USART", "UART")
199
+ .replace("husart", "huart")
200
+ )
201
+ elif periph == "I2C":
202
+ periph_section += f" LibXR::STM32I2C {instance.lower()}(&h{instance.lower()}, {instance.lower()}_buffer);\n"
203
+ elif periph == "TIM" and "Channels" in instances[instance]:
204
+ for channel in instances[instance]["Channels"]:
205
+ channel_num = channel.replace("CH", "")
206
+ pwm_section += f" LibXR::STM32PWM pwm_{instance.lower()}_ch{channel_num}(&h{instance.lower()}, TIM_CHANNEL_{channel_num});\n"
207
+
208
+ return "\n" + adc_channels + pwm_section + periph_section
209
+
210
+
211
+ def generate_terminal_config(project_data, terminal_source):
212
+ """Generate Terminal configuration based on peripheral settings."""
213
+ usb_device = None
214
+ for instance, config in project_data["Peripherals"].get("USB", {}).items():
215
+ mode = config.get("Mode", "")
216
+ if "DEVICE" in instance.upper() or mode == "Device_Only":
217
+ usb_device = "hUsbDeviceFS"
218
+ elif "OTG_FS" in instance.upper():
219
+ usb_device = "hUsbOtgFS"
220
+
221
+ # Get all UART devices
222
+ uart_list = list(project_data["Peripherals"].get("USART", {}).keys()) + list(
223
+ project_data["Peripherals"].get("UART", {}).keys()
224
+ )
225
+
226
+ terminal_config = ""
227
+
228
+ if usb_device:
229
+ terminal_config = f" LibXR::STM32VirtualUART uart_cdc({usb_device}, 5, 5);\n"
230
+
231
+ if terminal_source != "":
232
+ terminal_config += f" STDIO::read_ = &{terminal_source}.read_port_;\n"
233
+ terminal_config += f" STDIO::write_ = &{terminal_source}.write_port_;\n"
234
+ elif usb_device:
235
+ terminal_config += " STDIO::read_ = &uart_cdc.read_port_;\n"
236
+ terminal_config += " STDIO::write_ = &uart_cdc.write_port_;\n"
237
+ elif uart_list:
238
+ first_uart = uart_list[0].lower()
239
+ terminal_config = f" STDIO::read_ = &{first_uart}.read_port_;\n"
240
+ terminal_config += f" STDIO::write_ = &{first_uart}.write_port_;\n"
241
+
242
+ if terminal_config:
243
+ terminal_config += ' RamFS ramfs("XRobot");\n'
244
+ terminal_config += " Terminal terminal(ramfs);\n"
245
+ terminal_config += " auto terminal_task = Timer::CreatetTask(terminal.TaskFun, &terminal, 10);\n"
246
+ terminal_config += " Timer::Add(terminal_task);\n"
247
+ terminal_config += " Timer::Start(terminal_task);\n"
248
+
249
+ return terminal_config
250
+
251
+
252
+ def preserve_user_code(existing_code, section):
253
+ """Preserve user code blocks between markers."""
254
+ start_marker = f"/* User Code Begin {section} */"
255
+ end_marker = f"/* User Code End {section} */"
256
+
257
+ if start_marker in existing_code and end_marker in existing_code:
258
+ preserved_code = existing_code.split(start_marker, 1)[1].split(end_marker, 1)[0]
259
+ return preserved_code.strip()
260
+
261
+ if section == 3:
262
+ return """
263
+ while (true) {
264
+ Thread::Sleep(UINT32_MAX);
265
+ }
266
+ """
267
+ else:
268
+ return "" # Return empty to preserve code structure
269
+
270
+
271
+ def generate_cpp_code(
272
+ project_data, project_name, terminal_source, buffer_sizes, existing_code=""
273
+ ):
274
+ timer_config = libxr_config.get("software_timer", (None, None))
275
+ if timer_config is None:
276
+ timer_pri = 2
277
+ timer_stack_depth = 512
278
+ libxr_config["software_timer"] = {"priority": timer_pri, "stack_depth": timer_stack_depth}
279
+ else:
280
+ timer_pri = timer_config["priority"]
281
+ timer_stack_depth = timer_config["stack_depth"]
282
+
283
+ """Generate complete C++ code."""
284
+ cpp_code_include = f"""#include \"database.hpp\"
285
+ #include \"libxr.hpp\"
286
+ #include \"main.h\"
287
+ #include \"app_main.h\"
288
+ #include \"stm32_adc.hpp\"
289
+ #include \"stm32_can.hpp\"
290
+ #include \"stm32_canfd.hpp\"
291
+ #include \"stm32_gpio.hpp\"
292
+ #include \"stm32_i2c.hpp\"
293
+ #include \"stm32_power.hpp\"
294
+ #include \"stm32_pwm.hpp\"
295
+ #include \"stm32_spi.hpp\"
296
+ #include \"stm32_timebase.hpp\"
297
+ #include \"stm32_uart.hpp\"
298
+ #include \"stm32_usb.hpp\"
299
+
300
+ using namespace LibXR;
301
+ """ + generate_extern_config(
302
+ project_data, buffer_sizes
303
+ )
304
+
305
+ cpp_code = (
306
+ cpp_code_include
307
+ + f"""
308
+
309
+ /* User Code Begin 1 */
310
+ """
311
+ + preserve_user_code(existing_code, 1)
312
+ + """
313
+ /* User Code End 1 */
314
+
315
+ extern \"C\" void app_main(void) {
316
+ /* User Code Begin 2 */
317
+ """
318
+ + preserve_user_code(existing_code, 2)
319
+ + f"""
320
+ /* User Code End 2 */
321
+
322
+ LibXR::STM32Timebase stm32_timebase;
323
+ LibXR::PlatformInit({timer_pri}, {timer_stack_depth});
324
+ LibXR::STM32PowerManager power_manager;
325
+ """
326
+ )
327
+
328
+ cpp_code += generate_gpio_config(project_data)
329
+ cpp_code += generate_peripherals_config(project_data)
330
+ cpp_code += generate_terminal_config(project_data, terminal_source)
331
+
332
+ cpp_code += (
333
+ """
334
+ /* User Code Begin 3 */
335
+ """
336
+ + preserve_user_code(existing_code, 3)
337
+ + """
338
+ /* User Code End 3 */
339
+ }
340
+ """
341
+ )
342
+
343
+ return cpp_code
344
+
345
+
346
+ def parse_arguments():
347
+ """Parse command-line arguments."""
348
+ parser = argparse.ArgumentParser(
349
+ description="Generate C++ code from JSON input with configurable DMA buffer sizes."
350
+ )
351
+
352
+ parser.add_argument(
353
+ "-i", "--input", type=str, required=True, default=24, help="Input file path."
354
+ )
355
+ parser.add_argument(
356
+ "-o", "--output", type=str, default=24, help="Output file path."
357
+ )
358
+
359
+ return parser.parse_args()
360
+
361
+
362
+ def generate_app_main_header(output_file):
363
+ """Generate app_main.h header file."""
364
+ with open(output_file, "w", encoding="utf-8") as f:
365
+ f.write("""#ifdef __cplusplus
366
+ extern "C" {
367
+ #endif
368
+
369
+ void app_main(void); // NOLINT
370
+
371
+ #ifdef __cplusplus
372
+ }
373
+ #endif
374
+ """)
375
+
376
+
377
+ def main():
378
+ global libxr_config
379
+
380
+ args = parse_arguments()
381
+
382
+ # Parse input and output paths
383
+ input_file = args.input
384
+ output_file = args.output if args.output else os.path.splitext(input_file)[0] + ".cpp"
385
+
386
+ # Parse buffer_sizes
387
+ buffer_sizes = {
388
+ "SPI": 32,
389
+ "USART": 128,
390
+ "I2C": 32,
391
+ "ADC": 32,
392
+ }
393
+
394
+ libxr_config_path = os.path.dirname(os.path.abspath(output_file)) + "/libxr_config.json"
395
+ print(libxr_config_path)
396
+
397
+ if os.path.exists(libxr_config_path):
398
+ try:
399
+ with open(libxr_config_path, "r", encoding="utf-8") as f:
400
+ libxr_config = json.load(f)
401
+ except (json.JSONDecodeError, IOError) as e:
402
+ print(f"Failed to load config: {e}, saving default config.")
403
+ with open(libxr_config_path, "w", encoding="utf-8") as f:
404
+ json.dump(libxr_config, f, indent=4, ensure_ascii=False)
405
+ else:
406
+ os.makedirs(os.path.dirname(libxr_config_path), exist_ok=True)
407
+ with open(libxr_config_path, "w", encoding="utf-8") as f:
408
+ json.dump(libxr_config, f, indent=4, ensure_ascii=False)
409
+
410
+ terminal_source = libxr_config.get("terminal_source", "")
411
+
412
+ # Read JSON data
413
+ try:
414
+ with open(input_file, "r", encoding="utf-8") as f:
415
+ project_data = json.load(f)
416
+ except FileNotFoundError:
417
+ print(f"Error: File {input_file} not found.")
418
+ sys.exit(1)
419
+ except json.JSONDecodeError:
420
+ print(f"Error: Failed to parse JSON file {input_file}.")
421
+ sys.exit(1)
422
+
423
+ # Read existing code (if any)
424
+ existing_code = ""
425
+ if os.path.exists(output_file):
426
+ with open(output_file, "r", encoding="utf-8") as f:
427
+ existing_code = f.read()
428
+
429
+ # Generate C++ code
430
+ cpp_code = generate_cpp_code(
431
+ project_data,
432
+ os.path.splitext(os.path.basename(input_file))[0],
433
+ terminal_source,
434
+ buffer_sizes,
435
+ existing_code,
436
+ )
437
+
438
+ # Write to output file
439
+ with open(output_file, "w", encoding="utf-8") as f:
440
+ f.write(cpp_code)
441
+
442
+ print(f"{output_file} generated successfully!")
443
+
444
+ # Generate app_main.h
445
+ header_file = os.path.join(os.path.dirname(output_file), "app_main.h")
446
+ with open(header_file, "w", encoding="utf-8") as f:
447
+ f.write("void app_main(void);\n")
448
+
449
+ generate_app_main_header(header_file)
450
+ print(f"{header_file} generated successfully!")
451
+
452
+ with open(libxr_config_path, "w", encoding="utf-8") as f:
453
+ # Write the JSON data (libxr_config) to the file
454
+ json.dump(libxr_config, f, indent=4, ensure_ascii=False)
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env python
2
+ import argparse
3
+ import fnmatch
4
+ import os
5
+ import re
6
+
7
+ file =(
8
+ '''set(CMAKE_CXX_STANDARD 20)
9
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
10
+
11
+ # LibXR
12
+ set(LIBXR_SYSTEM FreeRTOS)
13
+ set(LIBXR_DRIVER st)
14
+ add_subdirectory(Middlewares/Third_Party/LibXR)
15
+ target_link_libraries(
16
+ xr
17
+ stm32cubemx
18
+ )
19
+
20
+ target_include_directories(xr
21
+ PUBLIC $<TARGET_PROPERTY:stm32cubemx,INTERFACE_INCLUDE_DIRECTORIES>
22
+ PUBLIC Core/Inc
23
+ PUBLIC User
24
+ )
25
+
26
+ # Add include paths
27
+ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
28
+ # Add user defined include paths
29
+ PUBLIC $<TARGET_PROPERTY:xr,INTERFACE_INCLUDE_DIRECTORIES>
30
+ PUBLIC User
31
+ )
32
+
33
+ # Add linked libraries
34
+ target_link_libraries(${CMAKE_PROJECT_NAME}
35
+ stm32cubemx
36
+
37
+ # Add user defined libraries
38
+ xr
39
+ )
40
+
41
+
42
+ target_sources(${CMAKE_PROJECT_NAME}
43
+ PRIVATE User/app_main.cpp
44
+ )
45
+ '''
46
+ )
47
+
48
+ include_cmake_cmd = "include(${CMAKE_CURRENT_LIST_DIR}/cmake/LibXR.CMake)\n"
49
+
50
+
51
+ def main():
52
+ parser = argparse.ArgumentParser(description="Generate CMake file for LibXR.")
53
+ parser.add_argument("input_dir", type=str, help="CubeMX CMake Project Directory")
54
+
55
+ args = parser.parse_args()
56
+ input_directory = args.input_dir
57
+
58
+ if not os.path.isdir(input_directory):
59
+ print("Input directory does not exist.")
60
+ exit(1)
61
+
62
+ file_path = input_directory + "/cmake/LibXR.CMake"
63
+ if os.path.exists(file_path):
64
+ os.remove(file_path)
65
+
66
+ with open(file_path, "w") as f:
67
+ f.write(file)
68
+ f.close()
69
+
70
+ print("LibXR.CMake generated successfully.")
71
+
72
+ main_cmake_path = input_directory + "/CMakeLists.txt"
73
+ if os.path.exists(main_cmake_path):
74
+ if include_cmake_cmd not in open(main_cmake_path).read():
75
+ with open(main_cmake_path, "a") as f:
76
+ f.write('\n# Add LibXR\n' + include_cmake_cmd)
77
+ f.close()
78
+ print("LibXR.CMake included in CMakeLists.txt.")
79
+ else:
80
+ print("LibXR.CMake already included in CMakeLists.txt.")
81
+ else:
82
+ print("Error: CMakeLists.txt not found.")
83
+ exit(1)