1.自动构建脚本新增对eclipse的支持。

This commit is contained in:
MacRsh
2023-12-17 22:08:18 +08:00
parent a635e6facd
commit 79ab618db7
5 changed files with 223 additions and 74 deletions

View File

@@ -169,24 +169,14 @@ int main(void)
![工程目录](document/picture/readme/project.png) ![工程目录](document/picture/readme/project.png)
5. 将文件加入到IDE中大部分IDE都能自动识别工程路径下的文件无需进行此步骤。编译器中添加 `mr-library` 5. 使用自动构建脚本,完成自动构建。在 `mr-library` 路径下,打开命令行工具,运行:
的包含路径。配置GNU语法。如果您使用的是非 `GCC` 编译器请使能GNU语法。
`MR` 配置脚本支持 `MDK` 工程自动配置。在 `mr-library` 路径下,打开命令行工具,运行 `python build.py -mdk` 自动完成配置(完成后跳过剩余步骤至 `配置菜单选项`)。 - `MDK``python build.py -mdk`
- `Eclipse``python build.py -ecl`
![MDK自动构建](document/picture/readme/build_mdk.png) `MDK`为例:
6. 配置自动初始化GCC环境查找您工程下以 `.ld` 为后缀的连接脚本文件(通常为 `link.ld`),在脚本文件中添加代码(如使用 `MDK` 等能自动生成链接脚本的环境,请跳过此步骤): ![MDK自动构建](document/picture/readme/build_mdk.png)
```c
/* mr-library auto init */
. = ALIGN(4);
_mr_auto_init_start = .;
KEEP(*(SORT(.auto_init*)))
_mr_auto_init_end = .;
```
![Ld](document/picture/readme/ld.png)
## 配置菜单选项 ## 配置菜单选项
@@ -206,6 +196,8 @@ int main(void)
4. 工程中引入 `#include "include/mr_lib.h"` 并在 `main` 函数中添加 `mr_auto_init();` 自动初始化函数,即可开始使用。 4. 工程中引入 `#include "include/mr_lib.h"` 并在 `main` 函数中添加 `mr_auto_init();` 自动初始化函数,即可开始使用。
注:更多命令可输入:`python build.py -h` 查看。
---------- ----------
# 先来点个灯吧 # 先来点个灯吧

View File

@@ -182,30 +182,15 @@ version (the `MR` scripting tool relies on Python, install it yourself if there
![project directory](document/picture/readme/project.png) ![project directory](document/picture/readme/project.png)
5. Add the files to the IDE (most ides automatically recognize the files in the project path, eliminating the need for 5. Use the automatic build script to complete the automatic build. In the `mr-library` path, open the command line tool and run:
this step). Add `mr-library` to the compiler
Contains the path. Configure the GNU syntax. If you are using a non-gcc compiler, enable GNU syntax.
The `MR` configuration script supports the `MDK` project automatic configuration. In the `mr-library` path, open the - `MDK``python build.py -mdk`
command line tool and run `python build.py -mdk` to complete the configuration automatically (when done, skip the - `Eclipse``python build.py -ecl`
remaining steps to `Configuration menu options`).
Take `MDK` as an example:
![MDK auto build](document/picture/readme/build_mdk.png) ![MDK auto build](document/picture/readme/build_mdk.png)
6. Configure automatic initialization (GCC environment), find the connection script file with suffix `.ld `under your
project (usually` link.ld `), and add code to the script file (such as using the environment that can automatically
generate link scripts such as` MDK `, please skip this step) :
```c
/* mr-library auto init */
. = ALIGN(4);
_mr_auto_init_start = .;
KEEP(*(SORT(.auto_init*)))
_mr_auto_init_end = .;
```
![Ld](document/picture/readme/ld.png)
## Configure Menu Options ## Configure Menu Options
1. Open the command line tool in the `mr-library` directory and run `python build.py -m` for menu configuration. 1. Open the command line tool in the `mr-library` directory and run `python build.py -m` for menu configuration.
@@ -228,6 +213,8 @@ version (the `MR` scripting tool relies on Python, install it yourself if there
4. In the project, introduce `#include` include/mr_lib.h `and add` mr_auto_init() `to` main `function; ` 4. In the project, introduce `#include` include/mr_lib.h `and add` mr_auto_init() `to` main `function; `
Automatically initialize the function and start using it. Automatically initialize the function and start using it.
Note: More commands can be entered: `python build.py -h` to view.
---------- ----------
# Let`s Light an LED # Let`s Light an LED

222
build.py
View File

@@ -1,5 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
"""
@copyright (c) 2023, MR Development Team
@license SPDX-License-Identifier: Apache-2.0
@date 2023-12-17 MacRsh First version
"""
import os import os
import pip import pip
import argparse import argparse
@@ -15,11 +23,13 @@ try:
except ImportError: except ImportError:
print("Package not installed, installing...") print("Package not installed, installing...")
install_package('lxml') install_package('lxml')
from lxml import etree
try: try:
from kconfiglib import Kconfig from kconfiglib import Kconfig
except ImportError: except ImportError:
install_package('kconfiglib') install_package('kconfiglib')
from kconfiglib import Kconfig
try: try:
import curses import curses
@@ -30,20 +40,28 @@ except ImportError:
class MDK5: class MDK5:
def __init__(self, mdk_path): def __init__(self, mdk_path):
# Get MDK path # Get MDK project file
mdk_file = []
for root, dirs, fs in os.walk(mdk_path): for root, dirs, fs in os.walk(mdk_path):
for f in fs: for f in fs:
if f.endswith(".uvprojx"): if f.endswith(".uvprojx"):
mdk_path = os.path.join(root, f) mdk_file = os.path.join(root, f)
self.path = os.path.dirname(mdk_path) break
self.file = mdk_path if mdk_file:
self.name = os.path.basename(mdk_path) break
self.tree = etree.parse(mdk_path) # Check mdk file, init self
self.root = self.tree.getroot() if mdk_file:
self.path = os.path.dirname(mdk_file)
self.file = mdk_file
self.tree = etree.parse(mdk_file)
self.root = self.tree.getroot()
else:
print("Error: .uvprojx file not found")
exit(1)
def add_include_path(self, path): def add_include_path(self, path):
# Fix path # Fix path
path = os.path.relpath(path, os.path.abspath(self.path)).replace('\\', '/') path = os.path.relpath(path, self.path).replace('\\', '/')
# Add path # Add path
inc_path = self.tree.xpath("//Cads/VariousControls/IncludePath")[0] inc_path = self.tree.xpath("//Cads/VariousControls/IncludePath")[0]
exist_paths = inc_path.text.split(';') exist_paths = inc_path.text.split(';')
@@ -56,11 +74,12 @@ class MDK5:
self.add_include_path(path) self.add_include_path(path)
def add_files_new_group(self, name, files): def add_files_new_group(self, name, files):
# Fix path # Fix name and files
name = name.replace('\\', '/') name = name.replace('\\', '/')
fix_files = [] fix_files = []
for file in files: for file in files:
fix_files.append(file.replace('\\', '/')) file = os.path.relpath(file, self.path).replace('\\', '/')
fix_files.append(file)
files = fix_files files = fix_files
# Add group # Add group
groups_node = self.tree.find('//Groups') groups_node = self.tree.find('//Groups')
@@ -69,7 +88,7 @@ class MDK5:
group_node = etree.SubElement(groups_node, "Group") group_node = etree.SubElement(groups_node, "Group")
group_name_node = etree.SubElement(group_node, "GroupName") group_name_node = etree.SubElement(group_node, "GroupName")
group_name_node.text = name group_name_node.text = name
# Check files exist # Check files
if files is None: if files is None:
return return
# Add files # Add files
@@ -77,7 +96,7 @@ class MDK5:
if files_node is None: if files_node is None:
files_node = etree.SubElement(group_node, "Files") files_node = etree.SubElement(group_node, "Files")
for file in files: for file in files:
# Add files # Add file
file_node = files_node.find(f"./File[FileName='{os.path.basename(file)}']") file_node = files_node.find(f"./File[FileName='{os.path.basename(file)}']")
if file_node is None: if file_node is None:
file_node = etree.SubElement(files_node, "File") file_node = etree.SubElement(files_node, "File")
@@ -113,16 +132,22 @@ class MDK5:
files = [] files = []
for root, dirs, fs in os.walk(path): for root, dirs, fs in os.walk(path):
for f in fs: for f in fs:
files.append(os.path.relpath(os.path.join(root, f), os.path.abspath(self.path))) files.append(os.path.relpath(os.path.join(root, f), self.path))
self.add_files_new_group(path, files) self.add_files_new_group(path, files)
def add_path_c_files(self, path): def add_path_c_files(self, path):
# Get c files
files = [] files = []
for root, dirs, fs in os.walk(path): for root, dirs, fs in os.walk(path):
for f in fs: for f in fs:
if f.endswith(".c") or f.endswith(".cpp") or f.endswith(".cxx"): if f.endswith(".c") or f.endswith(".cpp") or f.endswith(".cxx"):
files.append(os.path.relpath(os.path.join(root, f), os.path.abspath(self.path))) file = os.path.relpath(os.path.join(root, f), self.path)
self.add_files_new_group(path, files) files.append(file)
# Fix name
name = os.path.relpath(path, self.path).replace('\\', '/').replace("../", "")
# Add group
if files:
self.add_files_new_group(name, files)
def use_gnu(self, enable=True): def use_gnu(self, enable=True):
# Check uAC6 # Check uAC6
@@ -142,6 +167,106 @@ class MDK5:
print("Build successfully") print("Build successfully")
class Eclipse:
def __init__(self, eclipse_path):
# Get eclipse project file
eclipse_file = []
for root, dirs, fs in os.walk(eclipse_path):
for f in fs:
if f.endswith(".cproject"):
eclipse_file = os.path.join(root, f)
break
if eclipse_file:
break
# Check eclipse file, init self
if eclipse_file:
self.path = os.path.dirname(eclipse_file)
self.file = eclipse_file
self.tree = etree.parse(eclipse_file)
self.root = self.tree.getroot()
else:
print("Error:.cproject file not found")
exit(1)
def add_include_path(self, path):
# Fix path
path = os.path.relpath(path, self.file).replace('\\', '/')
# Find all include path node
inc_path_nodes = self.tree.findall(".//option[@valueType='includePath']")
for inc_path_node in inc_path_nodes:
inc_path_node_id = inc_path_node.get('id')
# Check path node
if 'c.compiler' in inc_path_node_id and 'include' in inc_path_node_id:
# Add path
list_option = inc_path_node.find(f".//listOptionValue[@value='{path}']")
if list_option is None:
list_option = etree.SubElement(inc_path_node, "listOptionValue")
list_option.set('builtIn', "false")
list_option.set('value', path)
print("Include %s" % path)
break
def use_auto_init(self):
# Find ld file
ld_file = []
for root, dirs, files in os.walk(self.path):
for file in files:
if file.endswith(".ld"):
ld_file = os.path.join(root, file)
break
if ld_file:
break
# Check ld file
if ld_file:
with open(ld_file) as fr:
content = fr.read()
pos = content.find('.text :')
# Check pos
if pos == -1:
print("Use auto init failed")
# Check auto init is existed
if content.find('/* mr-library auto init */') == -1:
# Find pos offset
pos_offset = content[pos:].find('}')
# Check pos offset
if pos_offset == -1:
print("Use auto init failed")
pos = pos + pos_offset
# Use auto init
with open(ld_file, 'w') as fw:
front = content[:pos]
auto_init = """
/* mr-library auto init */
. = ALIGN(4);
_mr_auto_init_start = .;
KEEP(*(SORT(.auto_init*)))
_mr_auto_init_end = .;
"""
back = content[pos:]
fw.write(front + auto_init + back)
fw.close()
fr.close()
print("Use auto init")
def save(self):
self.tree.write(self.file, pretty_print=True, encoding="utf-8", xml_declaration=True)
print("Build successfully")
class MR:
def __init__(self):
self.path = os.path.dirname(__file__)
self.files_paths = []
for root, dirs, files in os.walk(self.path):
if root == self.path:
for path in dirs:
file_path = os.path.join(root, path)
self.files_paths.append(file_path)
break
self.project_path = os.path.dirname(self.path)
def show_logo(): def show_logo():
print(" __ __ _ _ _ ") print(" __ __ _ _ _ ")
print("| \/ | _ __ | | (_) | |__ _ __ __ _ _ __ _ _") print("| \/ | _ __ | | (_) | |__ _ __ __ _ _ __ _ _")
@@ -151,37 +276,76 @@ def show_logo():
print(" |___/") print(" |___/")
def build_mdk(): def show_license():
# Mr-library path license_file = os.path.join(os.path.dirname(__file__), "LICENSE")
mr_path = os.path.dirname(__file__) try:
mr_c_paths = ['mr-library/device', 'mr-library/driver', 'mr-library/source'] with open(license_file) as fr:
# MDK path print(fr.read())
mdk_file = os.path.dirname(mr_path) except OSError:
print(
"This software is provided subject to the terms of the Apache License 2.0, the full text of which is not "
"currently available due to missing license documentation. By continuing to use the Software, you agree "
"to be bound by the terms of the Apache License 2.0. The full license text is available at "
"http://www.apache.org/licenses/LICENSE-2.0. We advise you to review the license terms in full before use"
"to ensure you understand and agree to be bound by all provisions contained therein.")
print(
"本软件根据Apache许可证2.0版本条款提供,由于许可证文件缺失,当前无法获取完整许可内容。继续使用本软件,"
"代表您同意接受并遵守Apache许可证2.0版本的所有条款。完整许可证可在http://www.apache.org/licenses/LICENSE-2.0查看。建议您在使用前全面复核许可证内容,"
"以确保完全理解并同意接受其中的所有规定。")
# Build
mdk_proj = MDK5(mdk_file) def build_mdk():
mdk_proj.add_include_path(mr_path) mr = MR()
for mr_c_path in mr_c_paths: # MDK project
mdk_proj.add_path_files(mr_c_path) mdk_proj = MDK5(mr.project_path)
# Include path
mdk_proj.add_include_path(mr.path)
# Add all c files
for files_path in mr.files_paths:
mdk_proj.add_path_c_files(files_path)
# Use gnu
mdk_proj.use_gnu(True) mdk_proj.use_gnu(True)
# Save
mdk_proj.save() mdk_proj.save()
def build_eclipse():
mr = MR()
# Eclipse project
eclipse_proj = Eclipse(mr.project_path)
# Include path
eclipse_proj.add_include_path(mr.path)
# Use auto init
eclipse_proj.use_auto_init()
# Save
eclipse_proj.save()
def menuconfig(): def menuconfig():
subprocess.run(["menuconfig"], check=True) subprocess.run(["menuconfig"], check=True)
subprocess.run(["python", "kconfig.py"], check=True) subprocess.run(["python", "kconfig.py"], check=True)
if __name__ == '__main__': if __name__ == '__main__':
# Show mr-library logo # Show logo
show_logo() show_logo()
# Parse arguments
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-mdk", "--mdk", action="store_true", help="Build with MDK")
parser.add_argument("-m", "--menuconfig", action="store_true", help="Run menuconfig") parser.add_argument("-m", "--menuconfig", action="store_true", help="Run menuconfig")
parser.add_argument("-mdk", "--mdk", action="store_true", help="Build with MDK")
parser.add_argument("-ecl", "--eclipse", action="store_true", help="Build with Eclipse")
parser.add_argument("-lic", "--license", action="store_true", help="Show license")
args = parser.parse_args() args = parser.parse_args()
# Build
if args.mdk: if args.mdk:
build_mdk() build_mdk()
elif args.eclipse:
build_eclipse()
# Menuconfig
if args.menuconfig: if args.menuconfig:
menuconfig() menuconfig()
# Show license
if args.license:
show_license()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,5 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
"""
@copyright (c) 2023, MR Development Team
@license SPDX-License-Identifier: Apache-2.0
@date 2023-12-17 MacRsh First version
"""
import re import re
import pip import pip
@@ -20,18 +28,13 @@ except ImportError:
def generate_config(kconfig_file, config_in, config_out, header_out): def generate_config(kconfig_file, config_in, config_out, header_out):
print("Parsing " + kconfig_file)
kconf = Kconfig(kconfig_file, warn_to_stderr=False, kconf = Kconfig(kconfig_file, warn_to_stderr=False,
suppress_traceback=True) suppress_traceback=True)
# Load config files # Load config
print(kconf.load_config(config_in)) kconf.load_config(config_in)
kconf.write_config(config_out)
# Write merged config kconf.write_autoconf(header_out)
print(kconf.write_config(config_out))
# Write headers
print(kconf.write_autoconf(header_out))
with open(header_out, 'r+') as header_file: with open(header_out, 'r+') as header_file:
content = header_file.read() content = header_file.read()
@@ -59,6 +62,9 @@ def generate_config(kconfig_file, config_in, config_out, header_out):
header_file.write("#endif /* __cplusplus */\n\n") header_file.write("#endif /* __cplusplus */\n\n")
header_file.write("#endif /* _MR_CONFIG_H_ */\n") header_file.write("#endif /* _MR_CONFIG_H_ */\n")
header_file.close()
print("Config file generate successfully")
def main(): def main():
kconfig_file = 'Kconfig' kconfig_file = 'Kconfig'