前言
- 为了保证在window上运行,且体积小的问题,所以采用c语言编写生成脚本,
- 将相关路径由json文件进行配置,
- 使用了一个cjson库进行解析
- 项目构建使用的是cmake
项目代码
CMakeLists文件
cmake_minimum_required(VERSION 3.27)
project(txm_bat_script C)
set(CMAKE_C_STANDARD 11)
find_package(cJSON CONFIG REQUIRED)
configure_file(config.json ${CMAKE_CURRENT_BINARY_DIR}/config.json COPYONLY)
add_executable(txm_bat_script main.c
tx_app_module_build.c
tx_txm_lib_build.c)
target_link_libraries(txm_bat_script PRIVATE cjson)
main函数
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-14 shchl first version
*/
#include "main.h"
#include "cjson/cJSON.h"
FILE *configFile; /*配置文件*/
cJSON *rootJson;
char conf_data[4096];
int main(void) {
configFile = fopen("config.json", "r");
if (configFile) {
fseek(configFile, 0, SEEK_SET);
size_t readCnt = fread(conf_data, 1, 4096, configFile);
printf("read cnt:%zu\r\n", readCnt);
rootJson = cJSON_Parse(conf_data);
if (!rootJson) goto config_error;
build_txm_lib_cjson(rootJson);
build_app_module_bat_json(rootJson);
goto _exit;
}
config_error:
printf("json config error\r\n");
_exit:
if(configFile) fclose(configFile);
if (rootJson) cJSON_Delete(rootJson);
return 0;
}
构建txm静态库源文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-14 shchl thread txm lib 脚本构建
*/
#include "main.h"
#include <dirent.h>
#include <sys/stat.h>
/**
* @brief txm 源文件构建命令
*/
const char *tx_txm_lib_source_build_cmd =
"arm-none-eabi-gcc -c -g "
"-mcpu=cortex-m4 "
"-mfloat-abi=hard "
"-mfpu=vfpv4 "
"-mthumb "
"-fpic -fno-plt "
"-mno-pic-data-is-text-relative "
"-msingle-pic-base ";
static void build_txm_lib(char *txm_inc, char *bat_name, char **txm_src_lst, uint32_t cnt) {
FILE *pSaveFile = fopen(bat_name, "w");
DIR *pDir;
char *file_name;
if (pSaveFile) {
/*删除之前的静态库文件*/
fputs("del txm.a\n", pSaveFile);
for (int i = 0; i < cnt; ++i) {
file_name = txm_src_lst[i];
if (strstr(file_name, ".c")) {
/*单独添加接口编译源文件*/
fprintf(pSaveFile, "%s %s %s\n",
tx_txm_lib_source_build_cmd,
txm_inc,
file_name);
} else { /*认为就是目录*/
pDir = opendir(file_name);
if (pDir) {
struct dirent *pDirent = readdir(pDir);
while (pDirent) {
/*判断是否是.c文件*/
if (strstr(pDirent->d_name, ".c")) {
fprintf(pSaveFile, "%s %s %s\\%s\n",
tx_txm_lib_source_build_cmd,
txm_inc,
file_name,
pDirent->d_name);
} else if (strstr(pDirent->d_name, ".") && pDirent->d_namlen == 1) {
// 当前目录
} else if (strstr(pDirent->d_name, "..") && pDirent->d_namlen == 2) {
// 上一级目录
} else {
// 其他判断
}
pDirent = readdir(pDir);
}
closedir(pDir);
}
}
}
/*构建静态库*/
fputs("arm-none-eabi-ar -r txm.a *.o\n", pSaveFile);
/*删除.o文件*/
fputs("del *.o\n", pSaveFile);
fclose(pSaveFile);
}
}
cJSON *itm;
char txm_lib_include[4096] = {0}; /*头文件保存*/
char txm_bat_name[128] = {0};
char **txm_lib_src_dir;
uint32_t txm_lib_src_cnt = 0;
static int parse_txm_lib_include_array(cJSON *txm_itm) {
cJSON *inc_arr = cJSON_GetObjectItem(txm_itm, "lib_inc_arr");
if (!inc_arr) return -1;
int cnt = cJSON_GetArraySize(inc_arr);
int len = 0;
for (int i = 0; i < cnt; ++i) {
itm = cJSON_GetArrayItem(inc_arr, i);
len += sprintf(txm_lib_include + len, "\t-I%s", cJSON_GetStringValue(itm));
}
return 1;
}
static int parse_txm_lib_bat_name(cJSON *txm_itm) {
itm = cJSON_GetObjectItem(txm_itm, "bat_file_name");
if (!itm) return -1;
char *value = cJSON_GetStringValue(itm);
if (!value) return -1;
memcpy(txm_bat_name, value, strlen(value));
return 1;
}
static int parse_txm_lib_src_list(cJSON *txm_itm) {
cJSON *inc_arr = cJSON_GetObjectItem(txm_itm, "lib_src_dir_arr");
if (!inc_arr) return -1;
txm_lib_src_cnt = cJSON_GetArraySize(inc_arr);
txm_lib_src_dir = malloc(sizeof(char *) * txm_lib_src_cnt);
for (int i = 0; i < txm_lib_src_cnt; ++i) {
itm = cJSON_GetArrayItem(inc_arr, i);
txm_lib_src_dir[i] = strdup(cJSON_GetStringValue(itm));
}
return 1;
}
int build_txm_lib_cjson(cJSON *root) {
cJSON *txm_itm = cJSON_GetObjectItem(root, "txm_lib_config");
if (!txm_itm) return -1;
/*解析头文件*/
if (parse_txm_lib_include_array(txm_itm) == -1) return -1;
if (parse_txm_lib_bat_name(txm_itm) == -1)return -1;
if (parse_txm_lib_src_list(txm_itm) == -1)return -1;
build_txm_lib(txm_lib_include, txm_bat_name, txm_lib_src_dir, txm_lib_src_cnt);
/*释放内存*/
if (txm_lib_src_dir) {
for (int i = 0; i < txm_lib_src_cnt; ++i) {
free(txm_lib_src_dir[i]);
}
free(txm_lib_src_dir);
}
return 1;
}
构建app模块源文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-14 shchl 生成模块应用脚本代码
*/
#include "main.h"
/*指令格式*/
const char *common_del_cmd = "del *.o *.axf *.map"; /*通用删除指令*/
/**
* @brief 编译指令 c文件编译成 目标文件
*/
const char *module_compilar_to_obj_cmd =
"arm-none-eabi-gcc -c -g "
" -mcpu=cortex-m4 "
" -mfloat-abi=hard "
" -mfpu=vfpv4 -fpie -fno-plt "
" -mno-pic-data-is-text-relative "
" -msingle-pic-base ";
/**
* @brief 链接文件+目标文件
*/
const char *module_compilar_to_axf_cmd =
"arm-none-eabi-ld -A cortex-m4"
" -T %s %s "
" -e _txm_module_thread_shell_entry txm.a "
" -o app_module.axf"
" -M > app_module.map ";
const char *module_compilar_to_bin_cmd =
"\narm-none-eabi-objcopy -O binary app_module.axf \"app_module.bin\" "
"\narm-none-eabi-objcopy -O ihex app_module.axf \"app_module.hex\" ";
/*模块使用的头文件目录*/
//const char *module_inc_dir =
// "^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common\\inc "
// "^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\inc "
// "^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\inc ";
void build_app_module_bat(char *inc_list, char *asm_list, char *src_list, char *obj_list,char *link,char *bat) {
const char *cmd_asm_fmt = "%s %s\n"; /*汇编指令格式*/
const char *cmd_source_fmt = "%s %s %s\n"; /*汇编指令格式*/
FILE *pFile = fopen(bat, "w");
fprintf(pFile, "del *.bin *.hex\n");/*清除*/
/*汇编文件构建目标文件*/
fprintf(pFile, cmd_asm_fmt, module_compilar_to_obj_cmd, asm_list);
/*源文件构建目标文件*/
fprintf(pFile, cmd_source_fmt, module_compilar_to_obj_cmd, inc_list, src_list);
/*目标文件构建axf 文件*/
fprintf(pFile, module_compilar_to_axf_cmd, link, obj_list);
/*生成bin文件和map文件*/
fprintf(pFile, "%s", module_compilar_to_bin_cmd);
/*删除 构建中间文件*/
fprintf(pFile, "\n%s\n", common_del_cmd);/*清除*/
fclose(pFile);
}
static char app_module_inc_str[4096];
static char app_module_src_str[2048];
static char app_module_asm_str[1024];
static char app_module_obj_list[4096];
static char app_module_link[64];
static char app_module_bat[64];
static int app_module_obj_cur_len = 0;
char *strReplace(const char *original, const char *substr, const char *replace) {
char *tok = NULL;
char *newstr = NULL;
char *oldstr = NULL;
char *head = NULL;
if (original == NULL || substr == NULL || replace == NULL) {
return NULL;
}
newstr = strdup(original);
head = newstr;
while ((tok = strstr(head, substr))) {
oldstr = newstr;
newstr = (char *) malloc(strlen(oldstr) - strlen(substr) + strlen(replace) + 1);
/*failed to alloc mem, free old string and return NULL */
if (newstr == NULL) {
free(oldstr);
return NULL;
}
memcpy(newstr, oldstr, tok - oldstr);
memcpy(newstr + (tok - oldstr), replace, strlen(replace));
memcpy(newstr + (tok - oldstr) + strlen(replace), tok + strlen(substr),
strlen(oldstr) - strlen(substr) - (tok - oldstr));
memset(newstr + strlen(oldstr) - strlen(substr) + strlen(replace), 0, 1);
head = newstr + (tok - oldstr) + strlen(replace);
free(oldstr);
}
return newstr;
}
static int parse_app_module_inc_list(cJSON *module_itm) {
cJSON *inc_dir_arr_itm = cJSON_GetObjectItem(module_itm, "module_inc_dir");
if (!inc_dir_arr_itm) return -1;
int size = cJSON_GetArraySize(inc_dir_arr_itm);
int idx = 0;
for (int i = 0; i < size; ++i) {
cJSON *itm = cJSON_GetArrayItem(inc_dir_arr_itm, i);
if (!itm) return -1;
char *value = cJSON_GetStringValue(itm);
idx += sprintf(app_module_inc_str + idx, " -I%s ", value);
}
return 1;
}
static void add_file_name_to_obj_list(char *file_name) {
/*去掉头*/
char *post = strrchr(file_name, '\\') + 1;
/*去掉尾部*/
char *src = strtok(post, ".");
app_module_obj_cur_len += sprintf(app_module_obj_list + app_module_obj_cur_len, " %s.o", src);
}
static int parse_app_module_asm_list(cJSON *module_itm) {
cJSON *inc_dir_arr_itm = cJSON_GetObjectItem(module_itm, "module_asm_file_list");
if (!inc_dir_arr_itm) return -1;
int size = cJSON_GetArraySize(inc_dir_arr_itm);
int idx = 0;
for (int i = 0; i < size; ++i) {
cJSON *itm = cJSON_GetArrayItem(inc_dir_arr_itm, i);
if (!itm) return -1;
char *value = cJSON_GetStringValue(itm);
idx += sprintf(app_module_asm_str + idx, " %s ", value);
add_file_name_to_obj_list(value);
}
return 1;
}
static int parse_app_module_src_list(cJSON *module_itm) {
cJSON *inc_dir_arr_itm = cJSON_GetObjectItem(module_itm, "module_c_source_file_list");
if (!inc_dir_arr_itm) return -1;
int size = cJSON_GetArraySize(inc_dir_arr_itm);
int idx = 0;
for (int i = 0; i < size; ++i) {
cJSON *itm = cJSON_GetArrayItem(inc_dir_arr_itm, i);
if (!itm) return -1;
char *value = cJSON_GetStringValue(itm);
idx += sprintf(app_module_src_str + idx, " %s ", value);
add_file_name_to_obj_list(value);
}
return 1;
}
static int parse_app_module_link_file(cJSON *module_itm) {
cJSON *link_itm = cJSON_GetObjectItem(module_itm, "link_file");
if (!link_itm) return -1;
char *value = cJSON_GetStringValue(link_itm);
sprintf(app_module_link, "%s", value);
return 1;
}
static int parse_app_module_bat_file(cJSON *module_itm) {
cJSON *bat_itm = cJSON_GetObjectItem(module_itm, "bat_file_name");
if (!bat_itm) return -1;
char *value = cJSON_GetStringValue(bat_itm);
sprintf(app_module_bat, "%s", value);
return 1;
}
int build_app_module_bat_json(cJSON *root) {
cJSON *module_itm = cJSON_GetObjectItem(root, "txm_module_config");
if (parse_app_module_inc_list(module_itm) == -1)return -1;
if (parse_app_module_asm_list(module_itm) == -1)return -1;
if (parse_app_module_src_list(module_itm) == -1)return -1;
if (parse_app_module_link_file(module_itm) == -1)return -1;
if (parse_app_module_bat_file(module_itm) == -1)return -1;
printf("%s\n", app_module_obj_list);
printf("%s\n", app_module_link);
printf("%s\n", app_module_bat);
build_app_module_bat(app_module_inc_str,
app_module_asm_str,
app_module_src_str,
app_module_obj_list,
app_module_link,
app_module_bat);
return 1;
}
json配置文件(里面的文件可以配置成相对路径)
{
"txm_lib_config": {
"bat_file_name": "txm_lib_build.bat",
"lib_inc_arr": [
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common\\inc",
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\inc",
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\inc"
],
"lib_src_dir_arr": [
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\module_lib\\src",
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\module_lib\\src\\txm_module_thread_shell_entry.c"
]
},
"txm_module_config": {
"bat_file_name": "txm_module_build.bat",
"link_file": "..\\app_module.ld",
"module_inc_dir":[
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common\\inc",
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\inc",
"E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\inc"
],
"module_asm_file_list": [
"..\\app_module_preamble.S ",
"..\\app_module_setup.s "
],
"module_c_source_file_list": [
"..\\app_module.c"
]
}
}
测试(适用于cortex-m4,如果想使用其他内核,修改源码中的编译指令)