mirror of https://github.com/RT-Thread/rt-thread
[scons] code cleanup for scons script. (#10429)
* [scons] move project_generation to targets; code clean for building.py.
This commit is contained in:
parent
8e9872a554
commit
5a2352eb64
|
@ -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...')
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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更加简洁和易于维护。
|
|
@ -0,0 +1,4 @@
|
|||
from package import *
|
||||
|
||||
objs = BuildPackage()
|
||||
Return('objs')
|
|
@ -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");
|
||||
}
|
|
@ -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__ */
|
|
@ -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": [
|
||||
""
|
||||
]
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
|
@ -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):
|
||||
|
|
|
@ -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'
|
||||
]
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
|
@ -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")
|
|
@ -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
|
|
@ -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")
|
|
@ -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
|
|
@ -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)
|
|
@ -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):
|
|
@ -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()
|
||||
|
|
@ -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)
|
|
@ -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)
|
||||
|
||||
|
|
@ -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 模块
|
|
@ -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 = []
|
|
@ -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)
|
|
@ -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())
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue