summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2025-06-25 15:06:45 +0800
committerGitHub <[email protected]>2025-06-25 15:06:45 +0800
commit5a2352eb64f5a1039b37368f2a9c199db32957a0 (patch)
treef2153efa40eaef9ee4b3c66ad2eb74ea7d29b8d0 /tools
parent8e9872a55456b38d28b0d7d076905be84d0af7a2 (diff)
[scons] code cleanup for scons script. (#10429)
* [scons] move project_generation to targets; code clean for building.py.
Diffstat (limited to 'tools')
-rw-r--r--tools/WCS.py3
-rw-r--r--tools/building.py120
-rw-r--r--tools/hello/README.md49
-rw-r--r--tools/hello/SConscript4
-rw-r--r--tools/hello/hello.c22
-rw-r--r--tools/hello/hello.h29
-rw-r--r--tools/hello/package.json20
-rw-r--r--tools/package.py14
-rw-r--r--tools/preprocessor.py89
-rw-r--r--tools/release/buildbot.py1
-rw-r--r--tools/targets/__init__.py79
-rw-r--r--tools/targets/cdk.py (renamed from tools/cdk.py)0
-rw-r--r--tools/targets/cmake.py (renamed from tools/cmake.py)0
-rw-r--r--tools/targets/codeblocks.py (renamed from tools/codeblocks.py)11
-rw-r--r--tools/targets/codelite.py (renamed from tools/codelite.py)12
-rw-r--r--tools/targets/codelite_template.project (renamed from tools/codelite_template.project)0
-rw-r--r--tools/targets/codelite_template.workspace (renamed from tools/codelite_template.workspace)0
-rw-r--r--tools/targets/eclipse.py (renamed from tools/eclipse.py)7
-rw-r--r--tools/targets/esp_idf.py (renamed from tools/esp_idf.py)4
-rw-r--r--tools/targets/iar.py (renamed from tools/iar.py)4
-rw-r--r--tools/targets/keil.py (renamed from tools/keil.py)18
-rw-r--r--tools/targets/makefile.py (renamed from tools/makefile.py)25
-rw-r--r--tools/targets/rt_studio.py (renamed from tools/rt_studio.py)11
-rw-r--r--tools/targets/ses.py (renamed from tools/ses.py)0
-rw-r--r--tools/targets/template.cbp (renamed from tools/template.cbp)0
-rw-r--r--tools/targets/ua.py (renamed from tools/ua.py)0
-rw-r--r--tools/targets/vs.py (renamed from tools/vs.py)10
-rw-r--r--tools/targets/vs2012.py (renamed from tools/vs2012.py)11
-rw-r--r--tools/targets/vsc.py (renamed from tools/vsc.py)0
-rw-r--r--tools/targets/xmake.lua145
-rw-r--r--tools/targets/xmake.py (renamed from tools/xmake.py)4
-rw-r--r--tools/targets/zigbuild.py (renamed from tools/zigbuild.py)0
-rw-r--r--tools/testcases/README.md32
-rw-r--r--tools/testcases/mock_rtconfig.py35
-rw-r--r--tools/testcases/test_preprocessor.py116
-rw-r--r--tools/testcases/test_refactor.py121
-rw-r--r--tools/win32spawn.py188
-rw-r--r--tools/xmake.lua46
38 files changed, 888 insertions, 342 deletions
diff --git a/tools/WCS.py b/tools/WCS.py
index cf7de004d6..b2418fd3a0 100644
--- a/tools/WCS.py
+++ b/tools/WCS.py
@@ -426,9 +426,6 @@ def main():
# Print A Nice Message With Each Function and the WCS
print_all_fxns(call_graph)
-
-
-
def ThreadStackStaticAnalysis(env):
print('Start thread stack static analysis...')
diff --git a/tools/building.py b/tools/building.py
index f67c5a4b85..12689345e7 100644
--- a/tools/building.py
+++ b/tools/building.py
@@ -26,6 +26,7 @@
# 2024-04-21 Bernard Add toolchain detection in sdk packages
# 2025-01-05 Bernard Add logging as Env['log']
# 2025-03-02 ZhaoCake Add MkDist_Strip
+# 2025-01-05 Assistant Refactor SCons PreProcessor patch to independent class
import os
import sys
@@ -39,90 +40,14 @@ from SCons.Script import *
from utils import _make_path_relative
from mkdist import do_copy_file
from options import AddOptions
+from preprocessor import create_preprocessor_instance
+from win32spawn import Win32Spawn
BuildOptions = {}
Projects = []
Rtt_Root = ''
Env = None
-# SCons PreProcessor patch
-def start_handling_includes(self, t=None):
- """
- Causes the PreProcessor object to start processing #import,
- #include and #include_next lines.
-
- This method will be called when a #if, #ifdef, #ifndef or #elif
- evaluates True, or when we reach the #else in a #if, #ifdef,
- #ifndef or #elif block where a condition already evaluated
- False.
-
- """
- d = self.dispatch_table
- p = self.stack[-1] if self.stack else self.default_table
-
- for k in ('import', 'include', 'include_next', 'define'):
- d[k] = p[k]
-
-def stop_handling_includes(self, t=None):
- """
- Causes the PreProcessor object to stop processing #import,
- #include and #include_next lines.
-
- This method will be called when a #if, #ifdef, #ifndef or #elif
- evaluates False, or when we reach the #else in a #if, #ifdef,
- #ifndef or #elif block where a condition already evaluated True.
- """
- d = self.dispatch_table
- d['import'] = self.do_nothing
- d['include'] = self.do_nothing
- d['include_next'] = self.do_nothing
- d['define'] = self.do_nothing
-
-PatchedPreProcessor = SCons.cpp.PreProcessor
-PatchedPreProcessor.start_handling_includes = start_handling_includes
-PatchedPreProcessor.stop_handling_includes = stop_handling_includes
-
-class Win32Spawn:
- def spawn(self, sh, escape, cmd, args, env):
- # deal with the cmd build-in commands which cannot be used in
- # subprocess.Popen
- if cmd == 'del':
- for f in args[1:]:
- try:
- os.remove(f)
- except Exception as e:
- print('Error removing file: ' + e)
- return -1
- return 0
-
- import subprocess
-
- newargs = ' '.join(args[1:])
- cmdline = cmd + " " + newargs
-
- # Make sure the env is constructed by strings
- _e = dict([(k, str(v)) for k, v in env.items()])
-
- # Windows(tm) CreateProcess does not use the env passed to it to find
- # the executables. So we have to modify our own PATH to make Popen
- # work.
- old_path = os.environ['PATH']
- os.environ['PATH'] = _e['PATH']
-
- try:
- proc = subprocess.Popen(cmdline, env=_e, shell=False)
- except Exception as e:
- print('Error in calling command:' + cmdline.split(' ')[0])
- print('Exception: ' + os.strerror(e.errno))
- if (os.strerror(e.errno) == "No such file or directory"):
- print ("\nPlease check Toolchains PATH setting.\n")
-
- return e.errno
- finally:
- os.environ['PATH'] = old_path
-
- return proc.wait()
-
def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = []):
global BuildOptions
@@ -294,7 +219,7 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [
Env.Append(BUILDERS = {'BuildLib': bld})
# parse rtconfig.h to get used component
- PreProcessor = PatchedPreProcessor()
+ PreProcessor = create_preprocessor_instance()
f = open('rtconfig.h', 'r')
contents = f.read()
f.close()
@@ -433,7 +358,7 @@ def PrepareModuleBuilding(env, root_directory, bsp_directory):
Rtt_Root = root_directory
# parse bsp rtconfig.h to get used component
- PreProcessor = PatchedPreProcessor()
+ PreProcessor = create_preprocessor_instance()
f = open(bsp_directory + '/rtconfig.h', 'r')
contents = f.read()
f.close()
@@ -877,7 +802,7 @@ def DoBuilding(target, objects):
def GenTargetProject(program = None):
if GetOption('target') in ['mdk', 'mdk4', 'mdk5']:
- from keil import MDK2Project, MDK4Project, MDK5Project, ARMCC_Version
+ from targets.keil import MDK2Project, MDK4Project, MDK5Project, ARMCC_Version
if os.path.isfile('template.uvprojx') and GetOption('target') not in ['mdk4']: # Keil5
MDK5Project(GetOption('project-name') + '.uvprojx', Projects)
@@ -895,68 +820,68 @@ def GenTargetProject(program = None):
print("Keil-MDK project has generated successfully!")
if GetOption('target') == 'iar':
- from iar import IARProject, IARVersion
+ from targets.iar import IARProject, IARVersion
print("IAR Version: " + IARVersion())
IARProject(GetOption('project-name') + '.ewp', Projects)
print("IAR project has generated successfully!")
if GetOption('target') == 'vs':
- from vs import VSProject
+ from targets.vs import VSProject
VSProject(GetOption('project-name') + '.vcproj', Projects, program)
if GetOption('target') == 'vs2012':
- from vs2012 import VS2012Project
+ from targets.vs2012 import VS2012Project
VS2012Project(GetOption('project-name') + '.vcxproj', Projects, program)
if GetOption('target') == 'cb':
- from codeblocks import CBProject
+ from targets.codeblocks import CBProject
CBProject(GetOption('project-name') + '.cbp', Projects, program)
if GetOption('target') == 'ua':
- from ua import PrepareUA
+ from targets.ua import PrepareUA
PrepareUA(Projects, Rtt_Root, str(Dir('#')))
if GetOption('target') == 'vsc':
- from vsc import GenerateVSCode
+ from targets.vsc import GenerateVSCode
GenerateVSCode(Env)
if GetOption('cmsispack'):
from vscpyocd import GenerateVSCodePyocdConfig
GenerateVSCodePyocdConfig(GetOption('cmsispack'))
if GetOption('target') == 'cdk':
- from cdk import CDKProject
+ from targets.cdk import CDKProject
CDKProject(GetOption('project-name') + '.cdkproj', Projects)
if GetOption('target') == 'ses':
- from ses import SESProject
+ from targets.ses import SESProject
SESProject(Env)
if GetOption('target') == 'makefile':
- from makefile import TargetMakefile
+ from targets.makefile import TargetMakefile
TargetMakefile(Env)
if GetOption('target') == 'eclipse':
- from eclipse import TargetEclipse
+ from targets.eclipse import TargetEclipse
TargetEclipse(Env, GetOption('reset-project-config'), GetOption('project-name'))
if GetOption('target') == 'codelite':
- from codelite import TargetCodelite
+ from targets.codelite import TargetCodelite
TargetCodelite(Projects, program)
if GetOption('target') == 'cmake' or GetOption('target') == 'cmake-armclang':
- from cmake import CMakeProject
+ from targets.cmake import CMakeProject
CMakeProject(Env, Projects, GetOption('project-name'))
if GetOption('target') == 'xmake':
- from xmake import XMakeProject
+ from targets.xmake import XMakeProject
XMakeProject(Env, Projects)
if GetOption('target') == 'esp-idf':
- from esp_idf import ESPIDFProject
+ from targets.esp_idf import ESPIDFProject
ESPIDFProject(Env, Projects)
if GetOption('target') == 'zig':
- from zigbuild import ZigBuildProject
+ from targets.zigbuild import ZigBuildProject
ZigBuildProject(Env, Projects)
def EndBuilding(target, program = None):
@@ -1069,7 +994,7 @@ def GetVersion():
rtdef = os.path.join(Rtt_Root, 'include', 'rtdef.h')
# parse rtdef.h to get RT-Thread version
- prepcessor = PatchedPreProcessor()
+ prepcessor = create_preprocessor_instance()
f = open(rtdef, 'r')
contents = f.read()
f.close()
@@ -1109,4 +1034,3 @@ def PackageSConscript(package):
from package import BuildPackage
return BuildPackage(package)
-
diff --git a/tools/hello/README.md b/tools/hello/README.md
new file mode 100644
index 0000000000..c7a8a0d004
--- /dev/null
+++ b/tools/hello/README.md
@@ -0,0 +1,49 @@
+# Hello Component
+
+这是一个使用package.json配置的RT-Thread组件示例,展示了如何使用package.json来替代传统的SConscript中DefineGroup的方式。
+
+## 文件结构
+
+```
+hello/
+├── hello.h # 头文件
+├── hello.c # 源文件
+├── package.json # 组件配置文件
+├── SConscript # 构建脚本
+└── README.md # 说明文档
+```
+
+## package.json配置说明
+
+package.json文件包含了组件的所有构建信息:
+
+- `name`: 组件名称
+- `version`: 版本号
+- `description`: 组件描述
+- `author`: 作者信息
+- `license`: 许可证
+- `source_files`: 源文件列表
+- `CPPPATH`: 头文件搜索路径
+- `CPPDEFINES`: 预定义宏
+- `depends`: 依赖的组件
+
+## 使用方法
+
+1. 将hello文件夹复制到你的RT-Thread项目的components目录下
+2. 在应用代码中包含头文件:
+ ```c
+ #include "hello.h"
+ ```
+3. 调用hello_world函数:
+ ```c
+ hello_world(); // 输出: Hello World!
+ ```
+
+## 构建过程
+
+SConscript文件会:
+1. 导入package.py模块
+2. 调用BuildPackage函数处理package.json
+3. 自动创建DefineGroup并返回构建对象
+
+这种方式比传统的SConscript更加简洁和易于维护。 \ No newline at end of file
diff --git a/tools/hello/SConscript b/tools/hello/SConscript
new file mode 100644
index 0000000000..d75ecc66d7
--- /dev/null
+++ b/tools/hello/SConscript
@@ -0,0 +1,4 @@
+from package import *
+
+objs = BuildPackage()
+Return('objs')
diff --git a/tools/hello/hello.c b/tools/hello/hello.c
new file mode 100644
index 0000000000..f8c6fcc9c6
--- /dev/null
+++ b/tools/hello/hello.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2025-06-21 Bernard First version
+ */
+
+#include <rtthread.h>
+#include "hello.h"
+
+/**
+ * @brief Hello world function implementation
+ *
+ * This function prints "Hello World!" to the console using rt_kprintf
+ */
+void hello_world(void)
+{
+ rt_kprintf("Hello World!\n");
+}
diff --git a/tools/hello/hello.h b/tools/hello/hello.h
new file mode 100644
index 0000000000..b1f81388c9
--- /dev/null
+++ b/tools/hello/hello.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2025-06-21 Bernard First version
+ */
+
+#ifndef __HELLO_H__
+#define __HELLO_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Hello world function
+ *
+ * This function prints "Hello World!" to the console
+ */
+void hello_world(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HELLO_H__ */
diff --git a/tools/hello/package.json b/tools/hello/package.json
new file mode 100644
index 0000000000..1e390882b1
--- /dev/null
+++ b/tools/hello/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "hello",
+ "version": "1.0.0",
+ "description": "Hello World component for RT-Thread",
+ "author": "RT-Thread Development Team",
+ "license": "Apache-2.0",
+ "type": "rt-package",
+ "source_files": [
+ "hello.c"
+ ],
+ "CPPPATH": [
+ "."
+ ],
+ "CPPDEFINES": [
+ "HELLO"
+ ],
+ "depends": [
+ ""
+ ]
+} \ No newline at end of file
diff --git a/tools/package.py b/tools/package.py
index e9c43b66b7..f7a2ffa745 100644
--- a/tools/package.py
+++ b/tools/package.py
@@ -24,6 +24,8 @@
# this script is used to build group with package.json instead of SConscript
import os
+import json
+
from building import *
def ExtendPackageVar(package, var):
@@ -36,8 +38,14 @@ def ExtendPackageVar(package, var):
return v
-def BuildPackage(package):
- import json
+def BuildPackage(package = None):
+ if package is None:
+ package = os.path.join(GetCurrentDir(), 'package.json')
+
+ if not os.path.isfile(package):
+ print("%s/package.json not found" % GetCurrentDir())
+ return []
+
f = open(package)
package_json = f.read()
@@ -47,7 +55,7 @@ def BuildPackage(package):
package = json.loads(package_json)
# check package name
- if 'name' not in package:
+ if 'name' not in package or 'type' not in package or package['type'] != 'rt-package':
return []
# get depends
diff --git a/tools/preprocessor.py b/tools/preprocessor.py
new file mode 100644
index 0000000000..483c89c75b
--- /dev/null
+++ b/tools/preprocessor.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+#
+# File : preprocessor.py
+# This file is part of RT-Thread RTOS
+# COPYRIGHT (C) 2006 - 2025, RT-Thread Development Team
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Change Logs:
+# Date Author Notes
+# 2025-01-05 Assistant Extract SCons PreProcessor patch to independent class
+
+from SCons.Script import *
+
+class SConsPreProcessorPatch:
+ """
+ SCons PreProcessor patch class
+
+ This class provides methods to patch the SCons PreProcessor
+ to handle conditional compilation directives properly.
+ """
+
+ def __init__(self):
+ """Initialize the PreProcessor patch"""
+ self._patched_preprocessor = None
+ self._apply_patch()
+
+ def _apply_patch(self):
+ """
+ Apply the patch to SCons PreProcessor
+
+ This method patches the SCons.cpp.PreProcessor class with
+ custom methods for handling includes during conditional compilation.
+ """
+ from SCons import cpp
+
+ # Store reference to original PreProcessor
+ self._patched_preprocessor = cpp.PreProcessor
+
+ # Create bound methods for the patch
+ def start_handling_includes(preprocessor_self, t=None):
+ d = preprocessor_self.dispatch_table
+ p = preprocessor_self.stack[-1] if preprocessor_self.stack else preprocessor_self.default_table
+ for k in ('import', 'include', 'include_next', 'define'):
+ d[k] = p[k]
+
+ def stop_handling_includes(preprocessor_self, t=None):
+ d = preprocessor_self.dispatch_table
+ d['import'] = preprocessor_self.do_nothing
+ d['include'] = preprocessor_self.do_nothing
+ d['include_next'] = preprocessor_self.do_nothing
+ d['define'] = preprocessor_self.do_nothing
+
+ # Apply the patch methods
+ self._patched_preprocessor.start_handling_includes = start_handling_includes
+ self._patched_preprocessor.stop_handling_includes = stop_handling_includes
+
+ def get_patched_preprocessor(self):
+ return self._patched_preprocessor
+
+ def create_preprocessor_instance(self):
+ return self._patched_preprocessor()
+
+# Global instance for easy access
+_preprocessor_patch = None
+
+def get_patched_preprocessor():
+ global _preprocessor_patch
+ if _preprocessor_patch is None:
+ _preprocessor_patch = SConsPreProcessorPatch()
+ return _preprocessor_patch.get_patched_preprocessor()
+
+def create_preprocessor_instance():
+ global _preprocessor_patch
+ if _preprocessor_patch is None:
+ _preprocessor_patch = SConsPreProcessorPatch()
+ return _preprocessor_patch.create_preprocessor_instance() \ No newline at end of file
diff --git a/tools/release/buildbot.py b/tools/release/buildbot.py
index 0f9a8f96d9..9878d9c9c4 100644
--- a/tools/release/buildbot.py
+++ b/tools/release/buildbot.py
@@ -33,7 +33,6 @@ def update_project_file(project_dir):
command = ' --target=iar -s'
os.system('scons --directory=' + project_dir + command + ' > 1.txt')
-
def update_all_project_files(root_path):
# current path is dir
if os.path.isdir(root_path):
diff --git a/tools/targets/__init__.py b/tools/targets/__init__.py
new file mode 100644
index 0000000000..2c2d8542d7
--- /dev/null
+++ b/tools/targets/__init__.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+#
+# File : __init__.py
+# This file is part of RT-Thread RTOS
+# COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Change Logs:
+# Date Author Notes
+# 2025-01-XX Bernard Create targets module for IDE project generators
+
+# Import all target generators
+from . import keil
+from . import iar
+from . import vs
+from . import vs2012
+from . import codeblocks
+from . import ua
+from . import vsc
+from . import cdk
+from . import ses
+from . import eclipse
+from . import codelite
+from . import cmake
+from . import xmake
+from . import esp_idf
+from . import zigbuild
+from . import makefile
+from . import rt_studio
+
+# Export all target generator functions
+__all__ = [
+ # Keil MDK
+ 'keil',
+ # IAR
+ 'iar',
+ # Visual Studio
+ 'vs',
+ 'vs2012',
+ # Code::Blocks
+ 'codeblocks',
+ # Universal ARM
+ 'ua',
+ # VSCode
+ 'vsc',
+ # CDK
+ 'cdk',
+ # SEGGER Embedded Studio
+ 'ses',
+ # Eclipse
+ 'eclipse',
+ # CodeLite
+ 'codelite',
+ # CMake
+ 'cmake',
+ # XMake
+ 'xmake',
+ # ESP-IDF
+ 'esp_idf',
+ # Zig
+ 'zigbuild',
+ # Make
+ 'makefile',
+ # RT-Studio
+ 'rt_studio'
+] \ No newline at end of file
diff --git a/tools/cdk.py b/tools/targets/cdk.py
index 8a473f7291..8a473f7291 100644
--- a/tools/cdk.py
+++ b/tools/targets/cdk.py
diff --git a/tools/cmake.py b/tools/targets/cmake.py
index e998a48e8c..e998a48e8c 100644
--- a/tools/cmake.py
+++ b/tools/targets/cmake.py
diff --git a/tools/codeblocks.py b/tools/targets/codeblocks.py
index 907bd5371a..8e29f43800 100644
--- a/tools/codeblocks.py
+++ b/tools/targets/codeblocks.py
@@ -25,14 +25,17 @@
import os
import sys
import string
-import building
-
-import xml.etree.ElementTree as etree
+import uuid
+import utils
from xml.etree.ElementTree import SubElement
from utils import _make_path_relative
from utils import xml_indent
-import utils
+# Add parent directory to path to import building
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import building
+
+import xml.etree.ElementTree as etree
fs_encoding = sys.getfilesystemencoding()
diff --git a/tools/codelite.py b/tools/targets/codelite.py
index 9073cde072..b6f7dcd90f 100644
--- a/tools/codelite.py
+++ b/tools/targets/codelite.py
@@ -25,15 +25,17 @@
import os
import sys
import string
-import building
-import rtconfig
-
-import xml.etree.ElementTree as etree
+import uuid
+import utils
from xml.etree.ElementTree import SubElement
from utils import _make_path_relative
from utils import xml_indent
-import utils
+# Add parent directory to path to import building
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import building
+
+import xml.etree.ElementTree as etree
fs_encoding = sys.getfilesystemencoding()
diff --git a/tools/codelite_template.project b/tools/targets/codelite_template.project
index 0aa0ecc4c7..0aa0ecc4c7 100644
--- a/tools/codelite_template.project
+++ b/tools/targets/codelite_template.project
diff --git a/tools/codelite_template.workspace b/tools/targets/codelite_template.workspace
index 8f06e0ce2b..8f06e0ce2b 100644
--- a/tools/codelite_template.workspace
+++ b/tools/targets/codelite_template.workspace
diff --git a/tools/eclipse.py b/tools/targets/eclipse.py
index cb8d1050bc..050d8a184f 100644
--- a/tools/eclipse.py
+++ b/tools/targets/eclipse.py
@@ -13,7 +13,12 @@ import glob
import xml.etree.ElementTree as etree
from xml.etree.ElementTree import SubElement
-import rt_studio
+from . import rt_studio
+import sys
+import os
+
+# Add parent directory to path to import building and utils
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from building import *
from utils import *
from utils import _make_path_relative
diff --git a/tools/esp_idf.py b/tools/targets/esp_idf.py
index dc14f4ff2f..b6bdf8856a 100644
--- a/tools/esp_idf.py
+++ b/tools/targets/esp_idf.py
@@ -22,8 +22,8 @@ def GenerateCFiles(env,project):
cm_file.write( "\t" + path.replace("\\", "/") + "\n" )
src = open(f.rfile().abspath, 'r')
for line in src.readlines():
- if re.match('INIT_(BOARD|PREV|DEVICE|COMPONENT|ENV|APP)_EXPORT\(.+\)', line):
- init_export.append(re.search('\(.+\)', line).group(0)[1:-1])
+ if re.match(r'INIT_(BOARD|PREV|DEVICE|COMPONENT|ENV|APP)_EXPORT\(.+\)', line):
+ init_export.append(re.search(r'\(.+\)', line).group(0)[1:-1])
src.close()
cm_file.write("\n")
diff --git a/tools/iar.py b/tools/targets/iar.py
index 033cdb6de3..99223b24ba 100644
--- a/tools/iar.py
+++ b/tools/targets/iar.py
@@ -36,7 +36,7 @@ from utils import xml_indent
fs_encoding = sys.getfilesystemencoding()
-iar_workspace = '''<?xml version="1.0" encoding="iso-8859-1"?>
+iar_workspace = r'''<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
@@ -208,5 +208,5 @@ def IARVersion():
if not isinstance(stdout, str):
stdout = str(stdout, 'utf8') # Patch for Python 3
# example stdout: IAR ANSI C/C++ Compiler V8.20.1.14183/W32 for ARM
- iar_version = re.search('[\d\.]+', stdout).group(0)
+ iar_version = re.search(r'[\d\.]+', stdout).group(0)
return iar_version
diff --git a/tools/keil.py b/tools/targets/keil.py
index c878f5f508..d2b6e72e8a 100644
--- a/tools/keil.py
+++ b/tools/targets/keil.py
@@ -283,19 +283,13 @@ def MDK45Project(tree, target, script):
# get each group's LIBS flags
if 'LIBS' in group and group['LIBS']:
- for item in group['LIBS']:
- lib_path = ''
- for path_item in group['LIBPATH']:
- full_path = os.path.join(path_item, item + '.lib')
- if os.path.isfile(full_path): # has this library
- lib_path = full_path
- break
-
- if lib_path != '':
+ for item in group['LIBPATH']:
+ full_path = os.path.join(item, group['name'] + '.lib')
+ if os.path.isfile(full_path): # has this library
if group_tree != None:
- MDK4AddLibToGroup(ProjectFiles, group_tree, group['name'], lib_path, project_path)
+ MDK4AddLibToGroup(ProjectFiles, group_tree, group['name'], full_path, project_path)
else:
- group_tree = MDK4AddGroupForFN(ProjectFiles, groups, group['name'], lib_path, project_path)
+ group_tree = MDK4AddGroupForFN(ProjectFiles, groups, group['name'], full_path, project_path)
# write include path, definitions and link flags
IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath')
@@ -394,7 +388,7 @@ def MDK5Project(target, script):
print('UV4.exe is not available, please check your keil installation')
def MDK2Project(target, script):
- template = open('template.Uv2', "r")
+ template = open(os.path.join(os.path.dirname(__file__), 'template.Uv2'), 'r')
lines = template.readlines()
project = open(target, "w")
diff --git a/tools/makefile.py b/tools/targets/makefile.py
index 414e55a3f3..8be19fa96a 100644
--- a/tools/makefile.py
+++ b/tools/targets/makefile.py
@@ -1,6 +1,31 @@
+#
+# File : makefile.py
+# This file is part of RT-Thread RTOS
+# COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Change Logs:
+# Date Author Notes
+# 2015-01-20 Bernard Add copyright information
+
import os
import sys
+# Add parent directory to path to import utils
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils import *
from utils import _make_path_relative
import rtconfig
diff --git a/tools/rt_studio.py b/tools/targets/rt_studio.py
index 44dc0e82a0..2f3a4d7740 100644
--- a/tools/rt_studio.py
+++ b/tools/targets/rt_studio.py
@@ -2,7 +2,14 @@ import os
import re
from string import Template
-import rtconfig
+try:
+ import rtconfig
+except ImportError:
+ # Mock rtconfig for testing
+ class MockRtconfig:
+ pass
+ rtconfig = MockRtconfig()
+
import shutil
import time
@@ -275,7 +282,7 @@ def gen_org_eclipse_core_runtime_prefs(output_file_path):
def gen_cproject_file(output_file_path):
- template_file_path = os.path.join(os.path.dirname(output_file_path), "template.cproject")
+ template_file_path = os.path.join(os.path.dirname(__file__), 'template.cproject')
if os.path.exists(template_file_path):
try:
shutil.copy(template_file_path, output_file_path)
diff --git a/tools/ses.py b/tools/targets/ses.py
index 120d889e86..120d889e86 100644
--- a/tools/ses.py
+++ b/tools/targets/ses.py
diff --git a/tools/template.cbp b/tools/targets/template.cbp
index ac21c8b54d..ac21c8b54d 100644
--- a/tools/template.cbp
+++ b/tools/targets/template.cbp
diff --git a/tools/ua.py b/tools/targets/ua.py
index 218cd09584..218cd09584 100644
--- a/tools/ua.py
+++ b/tools/targets/ua.py
diff --git a/tools/vs.py b/tools/targets/vs.py
index 4da6dc1381..4cde4f0fc7 100644
--- a/tools/vs.py
+++ b/tools/targets/vs.py
@@ -25,13 +25,17 @@
import os
import sys
import string
-import building
+import uuid
import utils
-
-import xml.etree.ElementTree as etree
from xml.etree.ElementTree import SubElement
from utils import _make_path_relative
from utils import xml_indent
+
+# Add parent directory to path to import building
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import building
+
+import xml.etree.ElementTree as etree
fs_encoding = sys.getfilesystemencoding()
def VS_AddGroup(ProjectFiles, parent, name, files, libs, project_path):
diff --git a/tools/vs2012.py b/tools/targets/vs2012.py
index 7265163757..07fdcef0fc 100644
--- a/tools/vs2012.py
+++ b/tools/targets/vs2012.py
@@ -25,14 +25,17 @@
import os
import sys
import string
-import building
import uuid
-
-import xml.etree.ElementTree as etree
+import utils
from xml.etree.ElementTree import SubElement
from utils import _make_path_relative
from utils import xml_indent
-import utils
+
+# Add parent directory to path to import building
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import building
+
+import xml.etree.ElementTree as etree
fs_encoding = sys.getfilesystemencoding()
diff --git a/tools/vsc.py b/tools/targets/vsc.py
index c005bcf053..c005bcf053 100644
--- a/tools/vsc.py
+++ b/tools/targets/vsc.py
diff --git a/tools/targets/xmake.lua b/tools/targets/xmake.lua
new file mode 100644
index 0000000000..b685ae54ff
--- /dev/null
+++ b/tools/targets/xmake.lua
@@ -0,0 +1,145 @@
+add_rules("mode.debug", "mode.release")
+
+toolchain("arm-none-eabi")
+ set_kind("standalone")
+ set_sdkdir("/home/bernard/.env/tools/scripts/packages/arm-none-eabi-gcc-v13.2.rel1")
+toolchain_end()
+
+target("rt-thread")
+ set_kind("binary")
+ set_toolchains("arm-none-eabi")
+
+ add_files(
+ "applications/main.c",
+ "../../../components/libc/compilers/common/cctype.c",
+ "../../../components/libc/compilers/common/cstdlib.c",
+ "../../../components/libc/compilers/common/cstring.c",
+ "../../../components/libc/compilers/common/ctime.c",
+ "../../../components/libc/compilers/common/cunistd.c",
+ "../../../components/libc/compilers/common/cwchar.c",
+ "../../../components/libc/compilers/newlib/syscalls.c",
+ "../../../components/drivers/core/device.c",
+ "../../../components/drivers/ipc/completion_comm.c",
+ "../../../components/drivers/ipc/completion_up.c",
+ "../../../components/drivers/ipc/condvar.c",
+ "../../../components/drivers/ipc/dataqueue.c",
+ "../../../components/drivers/ipc/pipe.c",
+ "../../../components/drivers/ipc/ringblk_buf.c",
+ "../../../components/drivers/ipc/ringbuffer.c",
+ "../../../components/drivers/ipc/waitqueue.c",
+ "../../../components/drivers/ipc/workqueue.c",
+ "../../../components/drivers/pin/dev_pin.c",
+ "../../../components/drivers/serial/dev_serial.c",
+ "../libraries/HAL_Drivers/drivers/drv_gpio.c",
+ "../libraries/HAL_Drivers/drivers/drv_usart.c",
+ "../libraries/HAL_Drivers/drv_common.c",
+ "board/CubeMX_Config/Src/stm32f4xx_hal_msp.c",
+ "board/board.c",
+ "../../../components/finsh/shell.c",
+ "../../../components/finsh/msh.c",
+ "../../../components/finsh/msh_parse.c",
+ "../../../components/finsh/cmd.c",
+ "../../../src/clock.c",
+ "../../../src/components.c",
+ "../../../src/cpu_up.c",
+ "../../../src/defunct.c",
+ "../../../src/idle.c",
+ "../../../src/ipc.c",
+ "../../../src/irq.c",
+ "../../../src/kservice.c",
+ "../../../src/mem.c",
+ "../../../src/mempool.c",
+ "../../../src/object.c",
+ "../../../src/scheduler_comm.c",
+ "../../../src/scheduler_up.c",
+ "../../../src/thread.c",
+ "../../../src/timer.c",
+ "../../../src/klibc/kstring.c",
+ "../../../src/klibc/rt_vsscanf.c",
+ "../../../src/klibc/kstdio.c",
+ "../../../src/klibc/rt_vsnprintf_tiny.c",
+ "../../../src/klibc/kerrno.c",
+ "../../../libcpu/arm/common/atomic_arm.c",
+ "../../../libcpu/arm/common/div0.c",
+ "../../../libcpu/arm/common/showmem.c",
+ "../../../libcpu/arm/cortex-m4/context_gcc.S",
+ "../../../libcpu/arm/cortex-m4/cpuport.c",
+ "packages/stm32f4_cmsis_driver-latest/Source/Templates/gcc/startup_stm32f412zx.s",
+ "packages/stm32f4_cmsis_driver-latest/Source/Templates/system_stm32f4xx.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_dma_ex.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_usart.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_pwr_ex.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_cryp.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_gpio.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_rcc.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_cortex.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_pwr.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_cec.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_cryp_ex.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_dma.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_uart.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_rcc_ex.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_crc.c",
+ "packages/stm32f4_hal_driver-latest/Src/stm32f4xx_hal_rng.c"
+ )
+
+ add_includedirs(
+ "applications",
+ "packages/CMSIS-Core-latest/Include",
+ "../../../components/libc/compilers/newlib",
+ "../../../components/libc/compilers/common/include",
+ "../../../components/drivers/include",
+ "../../../components/drivers/smp_call",
+ "../../../components/drivers/phy",
+ "board",
+ "board/CubeMX_Config/Inc",
+ "../libraries/HAL_Drivers/drivers",
+ "../libraries/HAL_Drivers/drivers/config",
+ "../libraries/HAL_Drivers",
+ "../../../components/finsh",
+ ".",
+ "../../../include",
+ "../../../libcpu/arm/common",
+ "../../../libcpu/arm/cortex-m4",
+ "../../../components/libc/posix/ipc",
+ "../../../components/libc/posix/io/poll",
+ "../../../components/libc/posix/io/eventfd",
+ "../../../components/libc/posix/io/epoll",
+ "packages/stm32f4_cmsis_driver-latest/Include",
+ "packages/stm32f4_hal_driver-latest/Inc",
+ "packages/stm32f4_hal_driver-latest/Inc/Legacy"
+ )
+
+ add_defines(
+ "RT_USING_LIBC",
+ "RT_USING_NEWLIBC",
+ "STM32F412Zx",
+ "USE_HAL_DRIVER",
+ "_POSIX_C_SOURCE=1",
+ "__RTTHREAD__"
+ )
+
+ add_cflags(
+ " -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g" ,{force = true}
+ )
+ add_cxxflags(
+ " -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g" ,{force = true}
+ )
+
+ add_asflags(
+ " -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2" ,{force = true}
+ )
+
+ add_ldflags(
+ " -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=rt-thread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds" ,{force = true}
+ )
+
+ set_targetdir("./")
+ set_filename("rtthread.elf")
+
+ after_build(function(target)
+ os.exec("/home/bernard/.env/tools/scripts/packages/arm-none-eabi-gcc-v13.2.rel1/bin/arm-none-eabi-objcopy -O ihex rtthread.elf rtthread.hex")
+ os.exec("/home/bernard/.env/tools/scripts/packages/arm-none-eabi-gcc-v13.2.rel1/bin/arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin")
+ os.exec("/home/bernard/.env/tools/scripts/packages/arm-none-eabi-gcc-v13.2.rel1/bin/arm-none-eabi-size rtthread.elf")
+ end) \ No newline at end of file
diff --git a/tools/xmake.py b/tools/targets/xmake.py
index 668e18eeab..f90668f71f 100644
--- a/tools/xmake.py
+++ b/tools/targets/xmake.py
@@ -69,14 +69,14 @@ class XmakeProject:
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..')
- template_path = os.path.join(RTT_ROOT, "tools", "xmake.lua")
+ template_path = os.path.join(RTT_ROOT, "tools", "targets", "xmake.lua")
with open(template_path, "r") as f:
data = f.read()
data = Template(data)
data = data.safe_substitute(toolchain=self.toolchain, sdkdir=self.sdkdir, bindir=self.bindir, src_path=self.src_path, inc_path=self.inc_path,
define=self.define, cflags=self.cflags, cxxflags=self.cxxflags, asflags=self.asflags,
ldflags=self.ldflags, target="rt-thread")
- with open("xmake.lua", "w") as f:
+ with open(os.path.join(os.path.dirname(__file__), "xmake.lua"), "w") as f:
f.write(data)
diff --git a/tools/zigbuild.py b/tools/targets/zigbuild.py
index 8811639d34..8811639d34 100644
--- a/tools/zigbuild.py
+++ b/tools/targets/zigbuild.py
diff --git a/tools/testcases/README.md b/tools/testcases/README.md
new file mode 100644
index 0000000000..4025bd1ad5
--- /dev/null
+++ b/tools/testcases/README.md
@@ -0,0 +1,32 @@
+# 测试用例目录
+
+本目录包含 RT-Thread 工具的测试脚本。
+
+## 测试脚本
+
+### test_preprocessor.py
+SCons PreProcessor 补丁功能测试脚本。测试与 building.py 的集成,验证预处理器补丁是否正常工作。
+
+### test_refactor.py
+验证目标模块重构是否成功的测试脚本。测试内容包括:
+- 目标模块导入
+- Building.py 导入
+- 目标函数调用
+
+### mock_rtconfig.py
+用于测试的模拟 rtconfig 模块。在实际 rtconfig 不可用的测试场景中提供模拟的 rtconfig 模块。
+
+## 使用方法
+
+要运行测试,请导航到此目录并执行:
+
+```bash
+python test_preprocessor.py
+python test_refactor.py
+```
+
+## 说明
+
+- 这些测试脚本用于验证 RT-Thread 工具的功能
+- 可以独立运行或作为测试套件的一部分
+- mock_rtconfig.py 文件被其他测试脚本用来模拟 rtconfig 模块 \ No newline at end of file
diff --git a/tools/testcases/mock_rtconfig.py b/tools/testcases/mock_rtconfig.py
new file mode 100644
index 0000000000..0b81dd62f0
--- /dev/null
+++ b/tools/testcases/mock_rtconfig.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+#
+# Mock rtconfig module for testing purposes
+#
+
+# Mock configuration variables
+CROSS_TOOL = 'gcc'
+PLATFORM = 'gcc'
+CC = 'gcc'
+CXX = 'g++'
+AS = 'as'
+AR = 'ar'
+LINK = 'gcc'
+EXEC_PATH = '/usr/bin'
+
+# Mock functions
+def GetDepend(depend):
+ return True
+
+# Mock environment
+class MockEnv:
+ def __init__(self):
+ self.CPPPATH = []
+ self.CPPDEFINES = []
+ self.LIBS = []
+ self.LIBPATH = []
+ self.CFLAGS = []
+ self.CXXFLAGS = []
+ self.LINKFLAGS = []
+ self.ASFLAGS = []
+
+# Global variables
+Env = MockEnv()
+Rtt_Root = '/mock/rt-thread'
+Projects = [] \ No newline at end of file
diff --git a/tools/testcases/test_preprocessor.py b/tools/testcases/test_preprocessor.py
new file mode 100644
index 0000000000..11121dbda9
--- /dev/null
+++ b/tools/testcases/test_preprocessor.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# File : test_preprocessor_patch.py
+# This file is part of RT-Thread RTOS
+# COPYRIGHT (C) 2006 - 2025, RT-Thread Development Team
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Change Logs:
+# Date Author Notes
+# 2025-01-05 Assistant Test file for SCons PreProcessor patch
+
+import sys
+import os
+
+# Add current directory to path for imports
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+def test_preprocessor_patch():
+ """Test the SCons PreProcessor patch functionality"""
+ try:
+ from scons_preprocessor_patch import SConsPreProcessorPatch, create_preprocessor_instance
+
+ print("Testing SCons PreProcessor patch...")
+
+ # Test creating patch instance
+ patch = SConsPreProcessorPatch()
+ print("✓ SConsPreProcessorPatch instance created successfully")
+
+ # Test getting patched preprocessor
+ patched_class = patch.get_patched_preprocessor()
+ print("✓ Patched PreProcessor class retrieved successfully")
+
+ # Test creating preprocessor instance
+ preprocessor = create_preprocessor_instance()
+ print("✓ PreProcessor instance created successfully")
+
+ # Test basic functionality
+ test_content = """
+ #define TEST_MACRO 1
+ #ifdef TEST_MACRO
+ #define ENABLED_FEATURE 1
+ #else
+ #define DISABLED_FEATURE 1
+ #endif
+ """
+
+ preprocessor.process_contents(test_content)
+ namespace = preprocessor.cpp_namespace
+
+ print("✓ PreProcessor processed test content successfully")
+ print(f" - TEST_MACRO: {namespace.get('TEST_MACRO', 'Not found')}")
+ print(f" - ENABLED_FEATURE: {namespace.get('ENABLED_FEATURE', 'Not found')}")
+ print(f" - DISABLED_FEATURE: {namespace.get('DISABLED_FEATURE', 'Not found')}")
+
+ print("\n✓ All tests passed! SCons PreProcessor patch is working correctly.")
+ return True
+
+ except ImportError as e:
+ print(f"✗ Import error: {e}")
+ print("Make sure SCons is available in the environment")
+ return False
+ except Exception as e:
+ print(f"✗ Test failed: {e}")
+ return False
+
+def test_building_integration():
+ """Test integration with building.py"""
+ try:
+ # Test that the function is available from the patch module
+ from scons_preprocessor_patch import create_preprocessor_instance
+
+ print("\nTesting scons_preprocessor_patch integration...")
+
+ # Test that the function is available
+ preprocessor = create_preprocessor_instance()
+ print("✓ create_preprocessor_instance function works from scons_preprocessor_patch")
+
+ # Test basic processing
+ test_content = "#define BUILD_TEST 1"
+ preprocessor.process_contents(test_content)
+ namespace = preprocessor.cpp_namespace
+
+ print(f"✓ Integration test passed: BUILD_TEST = {namespace.get('BUILD_TEST', 'Not found')}")
+ return True
+
+ except Exception as e:
+ print(f"✗ Integration test failed: {e}")
+ return False
+
+if __name__ == "__main__":
+ print("SCons PreProcessor Patch Test Suite")
+ print("=" * 40)
+
+ success1 = test_preprocessor_patch()
+ success2 = test_building_integration()
+
+ if success1 and success2:
+ print("\n🎉 All tests passed! The refactoring was successful.")
+ sys.exit(0)
+ else:
+ print("\n❌ Some tests failed. Please check the implementation.")
+ sys.exit(1) \ No newline at end of file
diff --git a/tools/testcases/test_refactor.py b/tools/testcases/test_refactor.py
new file mode 100644
index 0000000000..9bc9757302
--- /dev/null
+++ b/tools/testcases/test_refactor.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Test script to verify the refactoring is successful
+
+import sys
+import os
+
+# Add current directory to path
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+# Mock rtconfig module for testing
+import mock_rtconfig
+sys.modules['rtconfig'] = mock_rtconfig
+
+def test_targets_import():
+ """Test if all target modules can be imported successfully"""
+ print("Testing targets module imports...")
+
+ try:
+ # Test importing targets module
+ import targets
+ print("✓ targets module imported successfully")
+
+ # Test importing individual target modules
+ target_modules = [
+ 'keil', 'iar', 'vs', 'vs2012', 'codeblocks', 'ua',
+ 'vsc', 'cdk', 'ses', 'eclipse', 'codelite',
+ 'cmake', 'xmake', 'esp_idf', 'zigbuild', 'makefile', 'rt_studio'
+ ]
+
+ for module_name in target_modules:
+ try:
+ module = getattr(targets, module_name)
+ print(f"✓ {module_name} module imported successfully")
+ except AttributeError as e:
+ print(f"✗ Failed to import {module_name}: {e}")
+ return False
+
+ return True
+
+ except ImportError as e:
+ print(f"✗ Failed to import targets module: {e}")
+ return False
+
+def test_building_import():
+ """Test if building.py can import target modules"""
+ print("\nTesting building.py imports...")
+
+ try:
+ # Test importing building module
+ import building
+ print("✓ building module imported successfully")
+
+ # Test if GenTargetProject function exists
+ if hasattr(building, 'GenTargetProject'):
+ print("✓ GenTargetProject function found")
+ else:
+ print("✗ GenTargetProject function not found")
+ return False
+
+ return True
+
+ except ImportError as e:
+ print(f"✗ Failed to import building module: {e}")
+ return False
+
+def test_target_functions():
+ """Test if target functions can be called"""
+ print("\nTesting target function calls...")
+
+ try:
+ # Test importing specific target functions
+ from targets.keil import MDK4Project, MDK5Project
+ print("✓ Keil target functions imported successfully")
+
+ from targets.iar import IARProject
+ print("✓ IAR target functions imported successfully")
+
+ from targets.eclipse import TargetEclipse
+ print("✓ Eclipse target functions imported successfully")
+
+ from targets.cmake import CMakeProject
+ print("✓ CMake target functions imported successfully")
+
+ import targets.rt_studio
+ print("✓ RT-Studio target functions imported successfully")
+
+ return True
+
+ except ImportError as e:
+ print(f"✗ Failed to import target functions: {e}")
+ return False
+
+def main():
+ """Main test function"""
+ print("RT-Thread Tools Refactoring Test")
+ print("=" * 40)
+
+ success = True
+
+ # Run all tests
+ if not test_targets_import():
+ success = False
+
+ if not test_building_import():
+ success = False
+
+ if not test_target_functions():
+ success = False
+
+ print("\n" + "=" * 40)
+ if success:
+ print("✓ All tests passed! Refactoring is successful.")
+ return 0
+ else:
+ print("✗ Some tests failed. Please check the errors above.")
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main()) \ No newline at end of file
diff --git a/tools/win32spawn.py b/tools/win32spawn.py
index 605e194713..961e08ddfe 100644
--- a/tools/win32spawn.py
+++ b/tools/win32spawn.py
@@ -1,7 +1,7 @@
#
# File : win32spawn.py
# This file is part of RT-Thread RTOS
-# COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
+# COPYRIGHT (C) 2006 - 2025, RT-Thread Development Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,163 +23,43 @@
#
import os
-import threading
-import sys
+import subprocess
-_PY2 = sys.version_info[0] < 3
-if _PY2:
- import Queue
-else:
- import queue as Queue
+class Win32Spawn:
+ def spawn(self, sh, escape, cmd, args, env):
+ # deal with the cmd build-in commands which cannot be used in
+ # subprocess.Popen
+ if cmd == 'del':
+ for f in args[1:]:
+ try:
+ os.remove(f)
+ except Exception as e:
+ print('Error removing file: ' + e)
+ return -1
+ return 0
-# Windows import
-import win32file
-import win32pipe
-import win32api
-import win32con
-import win32security
-import win32process
-import win32event
+ newargs = ' '.join(args[1:])
+ cmdline = cmd + " " + newargs
-class Win32Spawn(object):
- def __init__(self, cmd, shell=False):
- self.queue = Queue.Queue()
- self.is_terminated = False
- self.wake_up_event = win32event.CreateEvent(None, 0, 0, None)
+ # Make sure the env is constructed by strings
+ _e = dict([(k, str(v)) for k, v in env.items()])
- exec_dir = os.getcwd()
- comspec = os.environ.get("COMSPEC", "cmd.exe")
- cmd = comspec + ' /c ' + cmd
+ # Windows(tm) CreateProcess does not use the env passed to it to find
+ # the executables. So we have to modify our own PATH to make Popen
+ # work.
+ old_path = os.environ['PATH']
+ os.environ['PATH'] = _e['PATH']
- win32event.ResetEvent(self.wake_up_event)
+ try:
+ proc = subprocess.Popen(cmdline, env=_e, shell=False)
+ except Exception as e:
+ print('Error in calling command:' + cmdline.split(' ')[0])
+ print('Exception: ' + os.strerror(e.errno))
+ if (os.strerror(e.errno) == "No such file or directory"):
+ print ("\nPlease check Toolchains PATH setting.\n")
- currproc = win32api.GetCurrentProcess()
+ return e.errno
+ finally:
+ os.environ['PATH'] = old_path
- sa = win32security.SECURITY_ATTRIBUTES()
- sa.bInheritHandle = 1
-
- child_stdout_rd, child_stdout_wr = win32pipe.CreatePipe(sa, 0)
- child_stdout_rd_dup = win32api.DuplicateHandle(currproc, child_stdout_rd, currproc, 0, 0, win32con.DUPLICATE_SAME_ACCESS)
- win32file.CloseHandle(child_stdout_rd)
-
- child_stderr_rd, child_stderr_wr = win32pipe.CreatePipe(sa, 0)
- child_stderr_rd_dup = win32api.DuplicateHandle(currproc, child_stderr_rd, currproc, 0, 0, win32con.DUPLICATE_SAME_ACCESS)
- win32file.CloseHandle(child_stderr_rd)
-
- child_stdin_rd, child_stdin_wr = win32pipe.CreatePipe(sa, 0)
- child_stdin_wr_dup = win32api.DuplicateHandle(currproc, child_stdin_wr, currproc, 0, 0, win32con.DUPLICATE_SAME_ACCESS)
- win32file.CloseHandle(child_stdin_wr)
-
- startup_info = win32process.STARTUPINFO()
- startup_info.hStdInput = child_stdin_rd
- startup_info.hStdOutput = child_stdout_wr
- startup_info.hStdError = child_stderr_wr
- startup_info.dwFlags = win32process.STARTF_USESTDHANDLES
-
- cr_flags = 0
- cr_flags = win32process.CREATE_NEW_PROCESS_GROUP
-
- env = os.environ.copy()
- self.h_process, h_thread, dw_pid, dw_tid = win32process.CreateProcess(None, cmd, None, None, 1,
- cr_flags, env, os.path.abspath(exec_dir),
- startup_info)
-
- win32api.CloseHandle(h_thread)
-
- win32file.CloseHandle(child_stdin_rd)
- win32file.CloseHandle(child_stdout_wr)
- win32file.CloseHandle(child_stderr_wr)
-
- self.__child_stdout = child_stdout_rd_dup
- self.__child_stderr = child_stderr_rd_dup
- self.__child_stdin = child_stdin_wr_dup
-
- self.exit_code = -1
-
- def close(self):
- win32file.CloseHandle(self.__child_stdout)
- win32file.CloseHandle(self.__child_stderr)
- win32file.CloseHandle(self.__child_stdin)
- win32api.CloseHandle(self.h_process)
- win32api.CloseHandle(self.wake_up_event)
-
- def kill_subprocess():
- win32event.SetEvent(self.wake_up_event)
-
- def sleep(secs):
- win32event.ResetEvent(self.wake_up_event)
- timeout = int(1000 * secs)
- val = win32event.WaitForSingleObject(self.wake_up_event, timeout)
- if val == win32event.WAIT_TIMEOUT:
- return True
- else:
- # The wake_up_event must have been signalled
- return False
-
- def get(self, block=True, timeout=None):
- return self.queue.get(block=block, timeout=timeout)
-
- def qsize(self):
- return self.queue.qsize()
-
- def __wait_for_child(self):
- # kick off threads to read from stdout and stderr of the child process
- threading.Thread(target=self.__do_read, args=(self.__child_stdout, )).start()
- threading.Thread(target=self.__do_read, args=(self.__child_stderr, )).start()
-
- while True:
- # block waiting for the process to finish or the interrupt to happen
- handles = (self.wake_up_event, self.h_process)
- val = win32event.WaitForMultipleObjects(handles, 0, win32event.INFINITE)
-
- if val >= win32event.WAIT_OBJECT_0 and val < win32event.WAIT_OBJECT_0 + len(handles):
- handle = handles[val - win32event.WAIT_OBJECT_0]
- if handle == self.wake_up_event:
- win32api.TerminateProcess(self.h_process, 1)
- win32event.ResetEvent(self.wake_up_event)
- return False
- elif handle == self.h_process:
- # the process has ended naturally
- return True
- else:
- assert False, "Unknown handle fired"
- else:
- assert False, "Unexpected return from WaitForMultipleObjects"
-
- # Wait for job to finish. Since this method blocks, it can to be called from another thread.
- # If the application wants to kill the process, it should call kill_subprocess().
- def wait(self):
- if not self.__wait_for_child():
- # it's been killed
- result = False
- else:
- # normal termination
- self.exit_code = win32process.GetExitCodeProcess(self.h_process)
- result = self.exit_code == 0
- self.close()
- self.is_terminated = True
-
- return result
-
- # This method gets called on a worker thread to read from either a stderr
- # or stdout thread from the child process.
- def __do_read(self, handle):
- bytesToRead = 1024
- while 1:
- try:
- finished = 0
- hr, data = win32file.ReadFile(handle, bytesToRead, None)
- if data:
- self.queue.put_nowait(data)
- except win32api.error:
- finished = 1
-
- if finished:
- return
-
- def start_pipe(self):
- def worker(pipe):
- return pipe.wait()
-
- thrd = threading.Thread(target=worker, args=(self, ))
- thrd.start()
+ return proc.wait()
diff --git a/tools/xmake.lua b/tools/xmake.lua
deleted file mode 100644
index 07552919c9..0000000000
--- a/tools/xmake.lua
+++ /dev/null
@@ -1,46 +0,0 @@
-add_rules("mode.debug", "mode.release")
-
-toolchain("${toolchain}")
- set_kind("standalone")
- set_sdkdir("${sdkdir}")
-toolchain_end()
-
-target("${target}")
- set_kind("binary")
- set_toolchains("${toolchain}")
-
- add_files(
- ${src_path}
- )
-
- add_includedirs(
- ${inc_path}
- )
-
- add_defines(
- ${define}
- )
-
- add_cflags(
- "${cflags}" ,{force = true}
- )
- add_cxxflags(
- "${cxxflags}" ,{force = true}
- )
-
- add_asflags(
- "${asflags}" ,{force = true}
- )
-
- add_ldflags(
- "${ldflags}" ,{force = true}
- )
-
- set_targetdir("./")
- set_filename("rtthread.elf")
-
- after_build(function(target)
- os.exec("${bindir}/${toolchain}-objcopy -O ihex rtthread.elf rtthread.hex")
- os.exec("${bindir}/${toolchain}-objcopy -O binary rtthread.elf rtthread.bin")
- os.exec("${bindir}/${toolchain}-size rtthread.elf")
- end) \ No newline at end of file