refactor: centralized header copy script replaces per-module cp

- 新增 release/copy_headers.sh:统一管理公共头文件复制
- 从所有模块 makefile 中移除独立的 @cp 行
- release/src/public/makefile:all 目标依赖 headers(自动调用脚本)
- release/inc/.gitignore:仅 myBase.h 纳入版本管理
- 新增模块时只需在 copy_headers.sh 末尾追加一行 copy_module

新增模块流程:
1. 创建 src/public/<module>/inc/<header.h>
2. 在 release/copy_headers.sh 中追加 copy_module "<module>" "<header.h>"
3. make 时自动复制到 release/inc/
This commit is contained in:
ypc 2026-07-07 17:38:44 +08:00
parent 9d12019961
commit 7dd7572f46
23 changed files with 60 additions and 8687 deletions

51
release/copy_headers.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/bash
# ================================================================
# copy_headers.sh — 公共头文件复制到 release/inc/
#
# 用法:
# release/copy_headers.sh # 从工程根目录调用
# make headers # 通过 makefile 调用
#
# 新增模块时,在本脚本末尾追加一行:
# copy_module "模块名" "头文件名"
# ================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
SRC_DIR="$ROOT_DIR/src"
DST_DIR="$ROOT_DIR/release/inc"
echo "=== copying public headers to release/inc/ ==="
copy_module()
{
local module="$1"
local header="$2"
local src="$SRC_DIR/public/$module/inc/$header"
if [ -f "$src" ]
then
cp -f "$src" "$DST_DIR/"
echo " [$module] $header"
else
echo " [WARN] $src not found, skip"
fi
}
# ================================================================
# 公共库模块(按顺序添加)
# ================================================================
copy_module "liblist" "list.h"
copy_module "libfunc" "myFunc.h"
copy_module "liblog" "myLog.h"
copy_module "libmd5" "myMd5.h"
copy_module "libcJSON" "cJSON.h"
copy_module "libmy_xxhash" "xxhash.h"
copy_module "libtask" "myTask.h"
copy_module "libxml" "myXml.h"
copy_module "libxml" "tinyxml2.h"
copy_module "libcmd" "myCmd.h"
copy_module "libdatacenter" "myDatacenter.h"
echo "=== done ==="

5
release/inc/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# release/inc/ 目录下仅 myBase.h 纳入版本管理
# 其他头文件由 release/copy_headers.sh 在编译前生成
*
!myBase.h
!.gitignore

View File

@ -1,306 +0,0 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 19
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,203 +0,0 @@
/**
* @file list.h
* @brief Linux 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容)
* @details 将 struct list_head 嵌入宿主结构体,通过 list_entry 取回宿主指针。
* 所有操作 O(1),遍历 O(n)。
* C++ 兼容:变量名不使用 new/class/typeof 等关键字。
*/
#ifndef _LIST_H_
#define _LIST_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* ---- 链表节点 ---- */
struct list_head
{
struct list_head *next;
struct list_head *prev;
};
/* ---- 初始化 ---- */
#define LIST_HEAD_INIT(n) { &(n), &(n) }
#define LIST_HEAD(n) struct list_head n = LIST_HEAD_INIT(n)
/**
* @brief 运行时初始化链表头
*/
static inline void INIT_LIST_HEAD(struct list_head *h)
{
h->next = h;
h->prev = h;
}
/* ---- 内部辅助:在 prev 和 next 之间插入 node ---- */
static inline void __list_add(struct list_head *node,
struct list_head *prev,
struct list_head *next)
{
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
/* ---- 内部辅助:移除 prev 和 next 之间的节点 ---- */
static inline void __list_del(struct list_head *prev,
struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/* ---- 添加操作 ---- */
/** 头插法:插入到 head 之后(作为第一个元素) */
static inline void list_add(struct list_head *node, struct list_head *head)
{
__list_add(node, head, head->next);
}
/** 尾插法:插入到 head 之前(作为最后一个元素) */
static inline void list_add_tail(struct list_head *node, struct list_head *head)
{
__list_add(node, head->prev, head);
}
/* ---- 删除操作 ---- */
/** 从链表移除节点(不释放内存) */
static inline void list_del(struct list_head *e)
{
__list_del(e->prev, e->next);
}
/** 移除并重新初始化节点(安全删除,防止悬空指针) */
static inline void list_del_init(struct list_head *e)
{
__list_del(e->prev, e->next);
INIT_LIST_HEAD(e);
}
/* ---- 移动操作 ---- */
/** 将节点移动到新链表头部 */
static inline void list_move(struct list_head *l, struct list_head *h)
{
__list_del(l->prev, l->next);
list_add(l, h);
}
/** 将节点移动到新链表尾部 */
static inline void list_move_tail(struct list_head *l, struct list_head *h)
{
__list_del(l->prev, l->next);
list_add_tail(l, h);
}
/* ---- 替换操作 ---- */
/** 用 node 替换 old */
static inline void list_replace(struct list_head *old, struct list_head *node)
{
node->next = old->next;
node->next->prev = node;
node->prev = old->prev;
node->prev->next = node;
}
/** 替换后初始化被替换节点 */
static inline void list_replace_init(struct list_head *old,
struct list_head *node)
{
list_replace(old, node);
INIT_LIST_HEAD(old);
}
/* ---- 判断操作 ---- */
/** 判断链表是否为空 */
static inline int list_empty(const struct list_head *h)
{
return h->next == h;
}
/** 判断节点是否已链入链表 */
static inline int list_is_linked(const struct list_head *e)
{
return e->next != e;
}
/* ---- 节点 ↔ 宿主指针转换 ---- */
/** 从链表节点指针取回宿主结构体指针 */
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
/** 获取第一个宿主元素 */
#define list_first_entry(h, type, member) \
list_entry((h)->next, type, member)
/** 获取最后一个宿主元素 */
#define list_last_entry(h, type, member) \
list_entry((h)->prev, type, member)
/** 安全获取第一个元素(链表空返回 NULL) */
#define list_first_entry_or_null(h, type, member) \
(list_empty(h) ? NULL : list_first_entry(h, type, member))
/* ---- 遍历操作 ---- */
/** 遍历链表节点(仅获取 struct list_head 指针) */
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/** 安全遍历节点(可在遍历中删除 pos) */
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/** 遍历宿主元素 */
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, __typeof__(*pos), member))
/** 安全遍历宿主元素(可在遍历中删除 pos) */
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member), \
n = list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, \
n = list_entry(n->member.next, __typeof__(*n), member))
/* ---- 拼接操作 ---- */
/** 将 src 链表拼接到 dst 头部,src 被清空 */
static inline void list_splice_init(struct list_head *src,
struct list_head *dst)
{
if (!list_empty(src))
{
struct list_head *f = src->next;
struct list_head *l = src->prev;
struct list_head *a = dst->next;
f->prev = dst;
dst->next = f;
l->next = a;
a->prev = l;
INIT_LIST_HEAD(src);
}
}
#ifdef __cplusplus
}
#endif
#endif /* _LIST_H_ */

View File

@ -1,77 +0,0 @@
/**
* @file myCmd.h
* @brief 命令处理框架 — 纯 C 接口
* @details 命令注册/分发/补全,内置 linenoise 行编辑。
* 通过 `__attribute__((constructor))` 实现模块自动注册。
*/
#ifndef _MY_CMD_H_
#define _MY_CMD_H_
#include "myBase.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
const char *name;
void (*func)(int argc, char *argv[]);
const char *desc;
void (*complete)(const char *buf, char ***completions, int *ncomp);
} stru_cmd;
/** 注册命令 */
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]),
const char *desc, void (*complete)(const char *, char ***, int *));
/** 获取所有已注册命令列表 */
stru_cmd *cmd_manager_get_commands(unsigned int *out_count);
/** 打印帮助信息 */
void cmd_help(int argc, char *argv[]);
/** 按名称查找命令 */
stru_cmd *cmd_find(const char *name);
/** Tab 自动补全回调 */
void cmd_complete(const char *buf, char ***completions, int *ncomp);
/** 子命令补全 */
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp,
const char **subs, int sub_count);
/** 行编辑交互式输入 */
char *linenoise(const char *prompt);
/** 释放 linenoise 返回的内存 */
void linenoiseFree(void *ptr);
/** 添加历史记录 */
int linenoiseHistoryAdd(const char *line);
/** 释放所有历史 */
void linenoiseHistoryFree(void);
/** 设置自动补全回调 */
void lineniseSetCompletionCallback(void (*cb)(const char *, char ***, int *));
/** 注册命令宏(无补全) */
#define CMD_REGISTER(cmd_name, func_ptr, cmd_desc) \
__attribute__((constructor)) static void register_##func_ptr(void) \
{ \
cmd_manager_add_command(cmd_name, func_ptr, cmd_desc, NULL); \
}
/** 注册命令宏(带补全) */
#define CMD_REGISTER_C(cmd_name, func_ptr, cmd_desc, complete) \
__attribute__((constructor)) static void register_##func_ptr(void) \
{ \
cmd_manager_add_command(cmd_name, func_ptr, cmd_desc, complete); \
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,558 +0,0 @@
/**
* @file myDatacenter.h
* @brief 数据中心模块 — 纯 C 对外接口
* @details 信号注册/控制/查询 + 事件队列 + 异步执行 + 参数配置。
* 内部通过 libmy_xxhash 做 O(1) 哈希查找,
* 参数配置通过 libxml C 接口解耦。
* 对齐 RTU 原工程 libdatacenter v1 + v2 全部功能。
*/
#ifndef _MY_DATACENTER_H_
#define _MY_DATACENTER_H_
#include <stdint.h>
#include <stddef.h>
#include "xxhash.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* ===== 地址/描述/模块/错误信息最大长度 ===== */
#define DC_SADDR_MAX_LEN 128
#define DC_DESC_MAX_LEN 256
#define DC_UNIT_MAX_LEN 32
#define DC_MODULE_MAX_LEN 64
#define DC_ERR_MSG_MAX_LEN 256
/* ===== 容量限制 ===== */
#define DC_MAX_CALLBACKS 16
#define DC_MAX_LINK_SADDRS 32
#define DC_MAX_DATA_ZONES 8
#define DC_MAX_PENDING 64
/** datacenter 自身模块标识 */
#define MODULE_DATACENTER "datacenter"
/* ===== 控制类型枚举 ===== */
typedef enum
{
DC_CTRL_NONE = 0, /**< 无控制 */
DC_CTRL_DIRECT = 1, /**< 直控(直接执行,无需选择-确认) */
DC_CTRL_SBO = 2 /**< 选控(Select-Before-Operate 两阶段) */
} dc_ctrl_type_t;
/* ===== 控制步骤枚举 ===== */
typedef enum
{
DC_STEP_READY = 0, /**< 就绪/空闲 */
DC_STEP_SELECT = 1, /**< 选择(SBO 第一步:锁住信号并暂存选择值) */
DC_STEP_DIRECT = 2, /**< 执行(SBO 第二步确认写入,直控直接执行) */
DC_STEP_CANCEL = 3 /**< 取消(回退到 READY) */
} dc_ctrl_step_t;
/* ===== 错误码枚举 ===== */
typedef enum
{
DC_OK = 0, /**< 成功 */
DC_ERR_PARAM = -1, /**< 参数错误(NULL/越界) */
DC_ERR_NOTFOUND = -2, /**< 信号不存在 */
DC_ERR_TYPE = -3, /**< 数据类型不匹配 */
DC_ERR_STEP = -4, /**< SBO 步骤错误 */
DC_ERR_VAL = -5, /**< 值校验失败(越界/未变化) */
DC_ERR_TIMEOUT = -6, /**< 异步请求超时 */
DC_ERR_BUSY = -7, /**< 忙 */
DC_ERR_MEM = -8, /**< 内存不足 */
DC_ERR_FULL = -9, /**< 请求队列已满 */
DC_ERR_LOCKED = -10, /**< 已锁定 */
DC_ERR_EXISTS = -11, /**< 信号已存在(重复注册) */
DC_ERR_CANCEL = -12 /**< 异步请求已取消 */
} dc_error_t;
/* ===== 控制上下文 ===== */
typedef struct
{
uint8_t step; /**< 当前控制步骤(dc_ctrl_step_t) */
uint8_t type; /**< 控制类型(dc_ctrl_type_t) */
uint8_t data_type; /**< 数据类型(DATA_TYPE_*) */
uint8_t reserved; /**< 保留 */
void *p_data; /**< SELECT 时暂存选择值,DIRECT 时用于返校比对 */
} dc_ctrl_t;
/* ===== 信号参数元数据(min/max/step/unit) ===== */
typedef struct
{
float min; /**< 最小值 */
float max; /**< 最大值 */
float step; /**< 步长 */
char unit[DC_UNIT_MAX_LEN]; /**< 单位(如 "kV", "A", "Hz") */
} dc_param_meta_t;
/* ===== 回调函数类型 ===== */
/**
* @brief out 信号值变更回调(延迟触发,100ms 周期批量检测后调用)
* @param saddr 信号地址
* @param data_type 数据类型
* @param p_new 新值指针
* @param p_old 旧值指针
*/
typedef void (*dc_out_change_cb_t)(const char *saddr, uint8_t data_type,
const void *p_new, const void *p_old);
/**
* @brief yk/ao/param 信号控制变更回调(同步触发,控制场景即时响应)
* @param saddr 信号地址
* @param step 控制步骤
* @param data_type 数据类型
* @param zone 定值区号(param 信号使用,其他为 0)
* @param p_data 数据指针
*/
typedef void (*dc_signal_change_cb_t)(const char *saddr, dc_ctrl_step_t step,
uint8_t data_type, uint8_t zone,
const void *p_data);
/** @brief 事件队列消费回调 */
typedef void (*dc_queue_pop_cb_t)(void *p_data);
/**
* @brief 异步请求完成回调(通知发起方模块A)
* @param req_id 请求 ID
* @param result 结果码(DC_OK / DC_ERR_*)
* @param err 错误信息(成功时为空)
* @param arg 用户参数
*/
typedef void (*dc_async_result_cb_t)(uint32_t req_id, int result,
const char *err, void *arg);
/**
* @brief 异步执行回调(datacenter 调用模块B执行实际操作)
* @param req_id 请求 ID
* @param saddr 信号地址
* @param step 控制步骤
* @param data_type 数据类型
* @param zone 定值区号
* @param p_data 操作数据
* @param ctx 模块上下文
* @return 0 已接受(稍后通过 dc_set_result 返回结果),-1 拒绝
*/
typedef int (*dc_async_exec_cb_t)(uint32_t req_id, const char *saddr,
dc_ctrl_step_t step, uint8_t data_type,
uint8_t zone, const void *p_data, void *ctx);
/* ===== 内部数据结构(对调用方透明,通过 API 访问) ===== */
/** 回调条目 */
typedef struct
{
char module_id[DC_MODULE_MAX_LEN];
dc_out_change_cb_t out_cb;
dc_signal_change_cb_t ctrl_cb;
} dc_cb_entry_t;
/** 信号节点 */
typedef struct
{
uint32_t id;
XXH128_hash_t hash;
char saddr[DC_SADDR_MAX_LEN];
char desc[DC_DESC_MAX_LEN];
uint8_t data_type;
uint8_t ctrl_type;
void **vec_p_data;
int vec_p_data_count;
void *p_last_data;
char link_saddr[DC_SADDR_MAX_LEN];
char **link_saddrs;
int link_count;
dc_param_meta_t param;
dc_cb_entry_t cb_list[DC_MAX_CALLBACKS];
int cb_count;
char last_caller_module[DC_MODULE_MAX_LEN];
dc_async_exec_cb_t exec_cb;
void *module_ctx;
} dc_signal_t;
/* ==================================================================
* 模块生命周期
* ================================================================== */
/**
* @brief 初始化数据中心
* @param cfg_dir 配置文件目录(用于查找 param.xml)
* @return DC_OK 成功,<0 失败
*/
int dc_init(const char *cfg_dir);
/** @brief 清理数据中心,释放所有信号和队列资源 */
void dc_cleanup(void);
/**
* @brief 每 100ms 周期调用
* @details out 信号变化检测 + 批量触发回调 + 事件队列弹出 + 异步超时检测
*/
void dc_run_100ms(void);
/**
* @brief 每 1000ms 周期调用
* @details 检测参数配置变更标志,有变更则写 self_param.xml
*/
void dc_run_1000ms(void);
/* ==================================================================
* Out 信号注册(遥测/遥信输出)
* ================================================================== */
/**
* @brief 注册输出信号
* @param saddr 信号地址(唯一标识)
* @param desc 信号描述
* @param data_type 数据类型(DATA_TYPE_*)
* @param p_data 数据指针
* @param module_id 模块标识(用于回路阻断)
* @return DC_OK 成功,DC_ERR_EXISTS 重复注册
*/
int dc_signal_out(const char *saddr, const char *desc, uint8_t data_type,
void *p_data, const char *module_id);
/**
* @brief 注册输出信号并绑定变化回调
* @param cb 值变更回调(延迟触发,100ms 批量检测后调用)
*/
int dc_signal_out_with_callback(const char *saddr, const char *desc,
uint8_t data_type, void *p_data,
dc_out_change_cb_t cb, const char *module_id);
/**
* @brief 链接已有 out 信号,获取数据指针并注册回调
* @param p_data 输出:out 信号的数据指针
*/
int dc_signal_out_link_with_callback(const char *saddr, void **p_data,
dc_out_change_cb_t cb, const char *module_id);
/**
* @brief 设置输出信号值(标记脏,100ms 后触发变更检测和延迟回调)
* @param module_id 调用方模块标识(自身不会被回调——回路阻断)
*/
int dc_set_out_signal_val(const char *saddr, const void *set_data,
const char *module_id);
/* ==================================================================
* In 信号注册(输入信号,链接到 out 信号的数据指针)
* ================================================================== */
/**
* @brief 注册输入信号并链接到输出信号
* @param link_saddr 要链接的 out 信号地址
* @param p_data 输出:被链接 out 信号的数据指针
*/
int dc_signal_in(const char *saddr, const char *desc,
const char *link_saddr, void **p_data, const char *module_id);
/**
* @brief 注册输入信号并绑定回调(回调挂在被链接的 out 信号上)
*/
int dc_signal_in_with_callback(const char *saddr, const char *desc,
const char *link_saddr, void **p_data,
dc_out_change_cb_t cb, const char *module_id);
/* ==================================================================
* YK 信号(遥控)
* ================================================================== */
/**
* @brief 注册遥控信号
* @param ctrl_type 控制类型(DC_CTRL_DIRECT 直控 / DC_CTRL_SBO 选控)
* @param cb 控制变更回调(同步触发)
*/
int dc_signal_yk(const char *saddr, const char *desc,
uint8_t data_type, uint8_t ctrl_type, void *p_data,
dc_signal_change_cb_t cb, const char *module_id);
/** @brief 链接已有 YK 信号,获取数据指针并注册回调 */
int dc_signal_yk_link_with_callback(const char *saddr, void **p_data,
dc_signal_change_cb_t cb, const char *module_id);
/**
* @brief YK 同步设置(处理 SBO 流程:SELECT→DIRECT/CANCEL)
* @param step 控制步骤
* @param ctrl 控制上下文(进入时携带 type/data_type/p_data,执行完毕后回写当前 step)
* @param p_data 操作数据
*/
int dc_signal_yk_set_status(const char *saddr, dc_ctrl_step_t step,
dc_ctrl_t *ctrl, const void *p_data,
const char *module_id);
/**
* @brief YK 异步远程执行
* @param result_cb 结果回调
* @param timeout_ms 超时时间(毫秒),0 使用默认值
* @param request_id 输出:请求 ID
*/
int dc_yk_exec_async(const char *saddr, dc_ctrl_step_t step,
const dc_ctrl_t *ctrl, const void *p_data,
const char *module_id,
dc_async_result_cb_t result_cb, void *user_arg,
uint32_t timeout_ms, uint32_t *request_id);
/** @brief 设置 YK 异步执行结果(模块B回调) */
int dc_yk_set_result(uint32_t request_id, int result_code, const char *err_msg);
/** @brief 取消 YK 异步请求 */
int dc_yk_cancel_async(uint32_t request_id);
/** @brief 注册 YK 异步执行回调(模块B初始化时调用) */
int dc_yk_register_exec_cb(const char *saddr, dc_async_exec_cb_t exec_cb,
void *module_ctx);
/* ==================================================================
* AO 信号(模拟输出)
* ================================================================== */
/**
* @brief 注册 AO 信号
* @param ctrl_type 控制类型
* @param cb 控制变更回调(同步触发)
*/
int dc_signal_ao(const char *saddr, const char *desc,
uint8_t data_type, uint8_t ctrl_type, void *p_data,
dc_signal_change_cb_t cb, const char *module_id);
/** @brief 链接已有 AO 信号 */
int dc_signal_ao_link_with_callback(const char *saddr, void **p_data,
dc_signal_change_cb_t cb, const char *module_id);
/**
* @brief AO 同步设置(SBO 流程 + 值校验)
* @details DIRECT 执行后 ctrl->step 自动复位到 READY
*/
int dc_signal_ao_set_val(const char *saddr, dc_ctrl_step_t step,
dc_ctrl_t *ctrl, const void *p_data,
const char *module_id);
/** @brief AO 无校验设置(跳过 SBO 流程和值校验,用于初始化恢复) */
int dc_signal_ao_set_val_without_check(const char *saddr, uint8_t data_type,
const void *p_data, const char *module_id);
/** @brief AO 异步执行 */
int dc_ao_exec_async(const char *saddr, dc_ctrl_step_t step,
const dc_ctrl_t *ctrl, const void *p_data,
const char *module_id,
dc_async_result_cb_t result_cb, void *user_arg,
uint32_t timeout_ms, uint32_t *request_id);
/** @brief 设置 AO 异步执行结果 */
int dc_ao_set_result(uint32_t request_id, int result_code, const char *err_msg);
/** @brief 取消 AO 异步请求 */
int dc_ao_cancel_async(uint32_t request_id);
/** @brief 注册 AO 异步执行回调 */
int dc_ao_register_exec_cb(const char *saddr, dc_async_exec_cb_t exec_cb,
void *module_ctx);
/* ==================================================================
* Param 信号(参数/定值,多定值区)
* ================================================================== */
/**
* @brief 注册参数信号
* @param p_data 数据指针数组(每个 zone 一个指针)
* @param num_zones 定值区数量
*/
int dc_signal_param(const char *saddr, const char *desc,
uint8_t data_type, uint8_t ctrl_type,
void **p_data, int num_zones,
dc_signal_change_cb_t cb, const char *module_id);
/** @brief 链接已有参数信号 */
int dc_signal_param_link_with_callback(const char *saddr, void **p_data,
int num_zones,
dc_signal_change_cb_t cb,
const char *module_id);
/**
* @brief Param 同步设置(SBO + zone 值校验)
* @param setting_zone 定值区号(0-based)
*/
int dc_signal_param_set_val(const char *saddr, dc_ctrl_step_t step,
dc_ctrl_t *ctrl, uint8_t setting_zone,
const void *p_data, const char *module_id);
/** @brief Param 无校验设置 */
int dc_signal_param_set_val_without_check(const char *saddr, uint8_t data_type,
uint8_t setting_zone,
const void *p_data,
const char *module_id);
/** @brief Param 异步执行 */
int dc_param_exec_async(const char *saddr, dc_ctrl_step_t step,
const dc_ctrl_t *ctrl, uint8_t setting_zone,
const void *p_data, const char *module_id,
dc_async_result_cb_t result_cb, void *user_arg,
uint32_t timeout_ms, uint32_t *request_id);
/** @brief 设置 Param 异步执行结果 */
int dc_param_set_result(uint32_t request_id, int result_code,
const char *err_msg);
/** @brief 取消 Param 异步请求 */
int dc_param_cancel_async(uint32_t request_id);
/** @brief 注册 Param 异步执行回调 */
int dc_param_register_exec_cb(const char *saddr, dc_async_exec_cb_t exec_cb,
void *module_ctx);
/* ==================================================================
* 信号查询
* ================================================================== */
/** @brief 查询 out 信号信息 */
int dc_get_out_signal_info(const char *saddr, char *desc, int desc_len,
uint8_t *data_type, void **p_data);
/** @brief 查询 in 信号信息 */
int dc_get_in_signal_info(const char *saddr, char *desc, int desc_len,
uint8_t *data_type, void **p_data);
/** @brief 查询 AO 信号信息(含参数元数据) */
int dc_get_ao_signal_info(const char *saddr, char *desc, int desc_len,
uint8_t *data_type, dc_param_meta_t *p_meta,
uint8_t *ctrl_type, void **p_data);
/**
* @brief 查询 Param 信号信息(含多区数据指针列表)
* @param p_data_array 输出:数据指针数组(调用方提供缓冲区)
* @param p_count 输出:定值区数量
*/
int dc_get_param_signal_info(const char *saddr, char *desc, int desc_len,
uint8_t *data_type, dc_param_meta_t *p_meta,
uint8_t *ctrl_type,
void **p_data_array, int *p_count);
/** @brief 查询 YK 信号信息 */
int dc_get_yk_signal_info(const char *saddr, char *desc, int desc_len,
uint8_t *data_type, uint8_t *ctrl_type, void **p_data);
/** @brief 获取信号值的字符串表示 */
int dc_get_signal_val(const void *p_data, uint8_t data_type,
char *buf, int buf_len);
/**
* @brief 按类型统计信号数量
* @param type_str 类型字符串:"out"/"in"/"yk"/"ao"/"param"
* @return 信号数量
*/
int dc_get_signal_count(const char *type_str);
/**
* @brief 按类型和 ID 查询信号基本信息(供前端遍历)
* @param type_str "out"/"in"/"yk"/"ao"/"param"
* @param id 信号 ID
* @param saddr/saddr_len 输出:信号地址
* @param desc/desc_len 输出:描述
* @param data_type_str/type_str_len 输出:数据类型名称
* @param ctrl_type 输出:控制类型
* @param link_str/link_len 输出:链接信号的逗号分隔列表
*/
int dc_get_signal_info_by_id(const char *type_str, uint32_t id,
char *saddr, int saddr_len,
char *desc, int desc_len,
char *data_type_str, int type_str_len,
uint8_t *ctrl_type,
char *link_str, int link_len);
/* ==================================================================
* 事件/扰动/故障队列
* ================================================================== */
/** @brief SOE 事件入队 */
int dc_event_queue_push(void *p_soe);
/** @brief 注册 SOE 事件消费回调(支持多消费者) */
int dc_event_register_queue_pop(dc_queue_pop_cb_t cb);
/** @brief 扰动数据入队 */
int dc_disturb_dd_queue_push(void *p_dd);
/** @brief 注册扰动数据消费回调 */
int dc_disturb_dd_register_queue_pop(dc_queue_pop_cb_t cb);
/** @brief 故障数据入队 */
int dc_fault_queue_push(void *p_fault);
/** @brief 注册故障数据消费回调 */
int dc_fault_register_queue_pop(dc_queue_pop_cb_t cb);
/* ==================================================================
* 类型工具函数
* ================================================================== */
/** @brief 数据类型 ID → 名称(如 35 → "uint32_t") */
const char *dc_get_type_name(uint8_t data_type);
/** @brief 名称 → 数据类型 ID(如 "float" → 38) */
uint8_t dc_get_type_id_by_name(const char *name);
/** @brief 获取数据类型的字节长度 */
uint8_t dc_get_type_len(uint8_t data_type);
/** @brief 根据类型分配并清零内存 */
void *dc_create_data(uint8_t data_type);
/** @brief 根据类型释放内存 */
void dc_destroy_data(void *p_data, uint8_t data_type);
/** @brief 类型感知的值复制 */
int dc_copy_val(void *dst, const void *src, uint8_t data_type);
/** @brief 类型感知的值比较(0 = 相等,-1 = 不等) */
int dc_compare_val(const void *p1, const void *p2, uint8_t data_type);
/** @brief 字符串 → 值(如 "3.14" → 3.14f) */
int dc_set_val_from_str(void *p_data, uint8_t data_type, const char *str);
/* ==================================================================
* 参数配置与异步管理
* ================================================================== */
/** @brief 查询参数配置是否有未保存的变更(0=无,1=有) */
int dc_param_cfg_changed(void);
/** @brief 获取当前异步请求 pending 数量 */
int dc_async_pending_count(void);
/** @brief 设置全局默认异步超时时间(毫秒) */
void dc_async_set_default_timeout(uint32_t timeout_ms);
/** @brief 设置 YK 遥控默认异步超时(0=使用全局默认) */
void dc_async_set_timeout_yk(uint32_t timeout_ms);
/** @brief 设置 AO 调节默认异步超时(0=使用全局默认) */
void dc_async_set_timeout_ao(uint32_t timeout_ms);
/** @brief 设置 Param 定值默认异步超时(0=使用全局默认) */
void dc_async_set_timeout_param(uint32_t timeout_ms);
/* ==================================================================
* 导出
* ================================================================== */
/**
* @brief 保存所有已注册 out 信号到 XML
* @param path 目标文件路径
* @return DC_OK 成功,<0 失败
*/
int dc_save_out_signals_xml(const char *path);
#ifdef __cplusplus
}
#endif
#endif /* _MY_DATACENTER_H_ */

View File

@ -1,323 +0,0 @@
/**
* @file myFunc.h
* @brief 基础工具函数接口 — 65 个函数,7 大分类
* @details 校验计算 / 字符串转换 / 时间处理 / 文件目录操作 /
* 进程管理 / 环境变量路径 / IPC 消息队列
*/
#ifndef _MY_FUNC_H_
#define _MY_FUNC_H_
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief 系统时间结构体(位域存储,用于嵌入式装置内部表示)
* @note year: 7bit(0-127+1900), month:4bit(1-12), day:5bit(1-31)
* hour:5bit(0-23), min:6bit(0-59), ms:16bit(0-59999)
*/
typedef struct
{
uint32_t ms : 16; /* 毫秒(实际存储秒*1000+毫秒,范围 0-59999) */
uint32_t min : 6; /* 分钟 0-59 */
uint32_t : 2; /* 保留 */
uint32_t hour: 5; /* 小时 0-23 */
uint32_t : 3; /* 保留 */
uint32_t day : 5; /* 日期 1-31 */
uint32_t week: 3; /* 星期 */
uint32_t month:4; /* 月份 1-12 */
uint32_t : 4; /* 保留 */
uint32_t year: 7; /* 年份偏移(实际值-1900),范围 0-127 */
uint32_t : 1; /* 保留 */
} stru_time_sys;
/**
* @brief 日历时间结构体(Unix 时间 + 微秒)
*/
typedef struct
{
time_t sec; /* Unix 时间戳(秒) */
time_t usec; /* 微秒部分 */
} stru_time_cal;
/**
* @brief IPC 消息文本载荷
*/
typedef struct
{
int qid; /* 响应队列 ID */
int type; /* 响应类型(enum_ipc_resp) */
int len; /* 有效数据长度 */
char text[4096]; /* 消息内容 */
} stru_ipc_text;
/**
* @brief IPC 响应类型
*/
typedef enum
{
IPC_RESP_NONE = 1, /* 无需响应 */
IPC_RESP_ONCE, /* 单次响应 */
IPC_RESP_ALWAYS /* 持续响应 */
} enum_ipc_resp;
/**
* @brief IPC 消息(System V 消息队列格式)
*/
typedef struct
{
long id; /* 消息类型 ID */
stru_ipc_text t; /* 消息载荷 */
} stru_ipc_msg;
/**
* @brief 文件描述头结构(256 字节,含 CRC 校验)
* @note flag 魔数为 0xA55AA55AA55AA55A
*/
#pragma pack(1)
typedef struct
{
uint64_t flag; /* 魔数标识 0xA55AA55AA55AA55A */
char ver[16]; /* 版本号 */
char author[16]; /* 作者 */
char modify[32]; /* 修改时间 YYYY-MM-DD HH-MM-SS */
uint16_t crc; /* CRC16 校验 */
char desc[128]; /* 附加描述 */
char bak[54]; /* 对齐填充(总计 256 字节) */
} stru_file_info;
#pragma pack()
/* ================================================================
* 校验计算函数(CRC16 使用 Modbus 多项式 0xA001)
* ================================================================ */
/** 8 位累加校验和 */
uint8_t func_cal_sum_byte(const uint8_t *d, uint32_t n);
/** 16 位累加校验和 */
uint16_t func_cal_sum_word(const uint8_t *d, uint32_t n);
/** CRC16(Modbus 多项式,初始值 0xFFFF) */
uint16_t func_cal_crc16(const uint8_t *d, uint32_t n);
/** CRC32(标准多项式,初始值 0xFFFFFFFF) */
uint32_t func_cal_crc32(const uint8_t *d, uint32_t n);
/** 文件 CRC16(4KB 缓冲区流式计算) */
uint16_t func_cal_file_crc16(const char *path);
/** 文件 CRC32(4KB 缓冲区流式计算) */
uint32_t func_cal_file_crc32(const char *path);
/* ================================================================
* 字符串转换函数
* ================================================================ */
/** 单个十六进制字符 → 数值('F'→15) */
uint8_t func_hex_ch(char c);
/** 单个十进制字符 → 数值('9'→9) */
uint8_t func_dec_ch(char c);
/** 十六进制字符串 "FF" → int 255 */
int func_hex2dec(char *s);
/** 十进制字符串 "255" → int 255(支持负号) */
int func_dec2dec(char *s);
/**
* @brief 十六进制字符串 → 字节缓冲区
* @param s 源字符串(如 "0102FF")
* @param dst 目标缓冲区
* @param len [out]实际字节数
* @return 0 成功,-1 奇数长度
*/
int func_hex2buf(const char *s, char *dst, int *len);
/**
* @brief int → 十进制字符串,右对齐前补零
* @param width 最小宽度(不足补 0,如 width=4 val=255 → "0255")
*/
char *func_dec2str(char *buf, int sz, int val, int width);
/** int → 十六进制字符串(width=0 时不补零) */
char *func_hex2str(char *buf, int sz, int val, int width);
/** float → 字符串 */
char *func_float2str(char *buf, int sz, float f, int width);
/** 字节数组 → 十六进制字符串(如 {0x01,0xFF} → "01FF") */
char *func_buf2str(char *buf, int sz, const char *src, int n);
/** 字符串按空格分割为 argc/argv */
int func_str2argv(char *s, uint8_t *argc, char *argv[], uint8_t max);
/* ================================================================
* 时间处理函数
* ================================================================ */
/** 系统时间 → "YYYY-MM-DD HH:MM:SS.mmm" 格式字符串 */
char *func_time_sys2str(char *buf, int sz, stru_time_sys *t);
/** 字符串 → 系统时间,解析失败返回 -1 */
int func_str2time_sys(const char *s, stru_time_sys *t);
/** 获取当前时间(type: 1=stru_time_sys, 2=stru_time_cal) */
int func_get_time(void *t, int type);
/** 设置系统时间(需要 root 权限) */
int func_set_time(void *t, int type);
/** 系统时间 → 日历时间 */
void func_time_sys2cal(stru_time_sys *src, stru_time_cal *dst);
/** 日历时间 → 系统时间 */
void func_time_cal2sys(stru_time_cal *src, stru_time_sys *dst);
/* ================================================================
* 文件目录操作函数
* ================================================================ */
/** 判断目录是否存在(返回 1=存在, 0=不存在) */
int func_dir_exist(const char *p);
/** 递归创建目录 */
int func_make_dirs(const char *p);
/** 递归删除目录(含所有内容) */
int func_del_dirs(const char *p);
/** 通过系统命令删除目录(rm -rf) */
int func_del_dirs_cmd(const char *p);
/** 判断文件是否存在(返回 1=存在, 0=不存在) */
int func_file_exist(const char *p);
/** 获取文件大小(字节),失败返回 0 */
uint32_t func_file_size(const char *p);
/** 读取文件到预分配缓冲区,out 返回实际读取字节数 */
int func_read_file(const char *p, char *buf, uint32_t cap, uint32_t *out);
/** 读取文件到动态分配缓冲区(调用者负责 free) */
uint8_t *func_read_file_alloc(const char *p, uint32_t *out);
/** 写缓冲区到文件(覆盖模式) */
int func_write_file(const char *p, const char *buf, uint32_t n);
/**
* @brief 读取结构化的文件描述头
* @param check 1=校验 flag 和 CRC,0=直接读取
*/
int func_read_file_info(const char *p, stru_file_info *info, int check);
/* ================================================================
* 进程管理函数(基于 /proc 文件系统)
* ================================================================ */
/** 获取当前进程名称 */
int func_proc_self_name(char *buf, uint32_t sz);
/** 通过 PID 获取进程名称 */
int func_proc_name_by_pid(int pid, char *buf, uint32_t sz);
/** 获取当前进程 PID */
int func_proc_pid(void);
/** 通过进程名称获取 PID(返回 -1 表示未找到) */
int func_proc_pid_by_name(const char *name);
/** 通过 PID 判断进程是否存在 */
int func_proc_exist_by_pid(int pid);
/** 通过名称判断进程是否存在 */
int func_proc_exist_by_name(const char *name);
/** 通过 PID 获取进程可执行文件路径 */
int func_proc_path_by_pid(int pid, char *buf, uint32_t sz);
/** 获取当前进程可执行文件路径 */
int func_proc_self_path(char *buf, uint32_t sz);
/** 获取当前进程所在目录 */
int func_proc_self_dir(char *buf, uint32_t sz);
/* ================================================================
* 环境变量路径函数
* ================================================================ */
/** 获取工作目录路径(环境变量 WORK_PATH) */
int func_get_work_path(char *buf, uint32_t sz);
/** 获取系统配置路径(SYS_CFG_PATH) */
int func_get_syscfg_path(char *buf, uint32_t sz);
/** 获取应用根路径(APP_ROOT_PATH) */
int func_get_app_root(char *buf, uint32_t sz);
/** 获取历史数据根路径(HIS_ROOT_PATH) */
int func_get_his_root(char *buf, uint32_t sz);
/** 获取日志根路径(LOG_ROOT_PATH) */
int func_get_log_root(char *buf, uint32_t sz);
/** 获取数据库根路径(DBC_ROOT_PATH) */
int func_get_dbc_root(char *buf, uint32_t sz);
/** 获取脚本路径(SHELL_PATH) */
int func_get_shell_path(char *buf, uint32_t sz);
/** 获取更新包路径(UPDATE_PATH) */
int func_get_update_path(char *buf, uint32_t sz);
/** 拼接应用路径:APP_ROOT_PATH/app_name */
int func_get_app_path(const char *app, char *buf, uint32_t sz);
/** 拼接应用配置路径:APP_ROOT_PATH/app_name/ext */
int func_get_app_cfg(const char *app, const char *ext, char *buf, uint32_t sz);
/** 拼接应用历史路径:HIS_ROOT_PATH/app_name */
int func_get_app_his(const char *app, char *buf, uint32_t sz);
/** 拼接应用日志路径:LOG_ROOT_PATH/app_name */
int func_get_app_log(const char *app, char *buf, uint32_t sz);
/* ================================================================
* IPC 消息队列函数(System V 消息队列)
* ================================================================ */
/** 按进程名创建消息队列 */
int func_ipc_create_by_name(char *name, int *qid);
/** 按 PID 创建消息队列 */
int func_ipc_create_by_pid(int pid, int *qid);
/** 按进程名获取消息队列 ID(不存在则创建) */
int func_ipc_get_by_name(const char *name, int *qid);
/** 按 PID 获取消息队列 ID(不存在则创建) */
int func_ipc_get_by_pid(int pid, int *qid);
/** 发送原始字节到消息队列 */
int func_ipc_send_buf(int qid, uint8_t *tx, uint32_t n);
/** 从消息队列接收原始字节 */
int func_ipc_recv_buf(int qid, uint8_t *rx, uint32_t n);
/** 发送结构体消息 */
int func_ipc_send_msg(int qid, stru_ipc_msg *m);
/** 接收结构体消息 */
int func_ipc_recv_msg(int qid, stru_ipc_msg *m);
/** 删除消息队列 */
int func_ipc_delete(int qid);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,69 +0,0 @@
/**
* @file myLog.h
* @brief 异步日志系统接口(纯 C)
* @details 支持 INFO/ERROR 两级日志,非阻塞写入。
* 首次调用 log_prt 时自动初始化(pthread_once 懒启动),无需手动 init。
* 控制台支持彩色 ANSI 输出,文件支持按大小自动轮转。
*/
#ifndef _MY_LOG_H_
#define _MY_LOG_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/** 日志级别:INFO(普通信息,白色输出) */
#define LOG_INFO 0
/** 日志级别:ERROR(错误信息,红色输出) */
#define LOG_ERROR 1
/**
* @brief 手动初始化日志系统(可选,首次 log_prt 会自动触发)
* @param dir 日志文件目录路径,传 NULL 则使用默认 /tmp/logs
* @return 0 成功
*/
int log_init(const char *dir);
/**
* @brief 核心日志打印函数(非阻塞,消息入队列后立即返回)
* @param level 日志级别(LOG_INFO 或 LOG_ERROR)
* @param file 源文件名(通常传 __FILE__)
* @param func 函数名(通常传 __FUNCTION__)
* @param line 行号(通常传 __LINE__)
* @param fmt printf 格式化字符串
* @param ... 可变参数
*/
void log_prt(uint32_t level, const char *file, const char *func,
uint32_t line, const char *fmt, ...);
/** 开启日志文件写入 */
void log_file_on(void);
/** 关闭日志文件写入 */
void log_file_off(void);
/** 开启控制台彩色输出 */
void log_console_on(void);
/** 关闭控制台输出 */
void log_console_off(void);
/** 等待异步队列清空(阻塞直到所有消息写入完成) */
void log_flush(void);
/** 停止工作线程、关闭文件、释放消息池 */
void log_cleanup(void);
/** INFO 级别便捷日志宏 */
#define LOG_I(fmt, ...) log_prt(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
/** ERROR 级别便捷日志宏 */
#define LOG_E(fmt, ...) log_prt(LOG_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,58 +0,0 @@
/**
* @file myMd5.h
* @brief MD5 消息摘要算法接口(RFC 1321)
* @details 计算 128 位哈希值,支持流式输入。
* 提供单次调用便捷函数 md5_string()。
*/
#ifndef _MY_MD5_H_
#define _MY_MD5_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief MD5 计算上下文(状态 + 计数 + 待处理缓冲区)
*/
typedef struct
{
uint32_t state[4]; /* A, B, C, D 四个 32 位状态寄存器 */
uint32_t count[2]; /* 位计数(低 32 位, 高 32 位) */
unsigned char buf[64]; /* 待处理数据缓冲区(64 字节) */
} stru_md5_ctx;
/**
* @brief 初始化 MD5 上下文
* @param ctx 上下文指针(设置魔数 A=0x67452301 B=0xefcdab89 C=0x98badcfe D=0x10325476)
*/
void md5_start(stru_md5_ctx *ctx);
/**
* @brief 输入待计算数据(可多次调用,支持流式处理)
* @param ctx 上下文指针
* @param data 数据缓冲区
* @param len 数据长度(字节)
*/
void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len);
/**
* @brief 完成计算,输出 16 字节 MD5 摘要
* @param ctx 上下文指针
* @param result 输出缓冲区(至少 16 字节)
*/
void md5_final(stru_md5_ctx *ctx, unsigned char result[16]);
/**
* @brief 单次调用便捷函数:计算字符串的 MD5,返回大写十六进制字符串
* @param input 输入字符串(以 '\0' 结尾)
* @param output 输出缓冲区(至少 33 字节,含结尾 '\0')
*/
void md5_string(const char *input, char output[33]);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,236 +0,0 @@
/**
* @file myTask.h
* @brief 任务框架接口 — 定时器 + 事件 + 消息队列(C 接口)
* @details 基于 SPEC §8 原工程分析。
* 定时器基于 timerfd + epoll 实现,精确到毫秒。
* 事件基于位图 + pthread 条件变量实现。
* 消息队列基于环形缓冲区 + 互斥锁 + 条件变量实现。
*/
#ifndef _MY_TASK_H_
#define _MY_TASK_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* ================================================================
* 通用定义
* ================================================================ */
/** 定时器回调函数类型 */
typedef void (*timer_func_cb)(void *arg);
/** 不透明句柄类型 */
typedef void *stru_task_timer_t;
typedef void *stru_task_event_t;
typedef void *stru_task_msg_queue_t;
/* ================================================================
* 定时器标志
* ================================================================ */
/** 单次触发(到期后自动停止) */
#define TASK_TIMER_FLAG_ONCE 0x01
/** 周期触发(到期后自动重新计时) */
#define TASK_TIMER_FLAG_PERIODIC 0x02
/* ================================================================
* 事件等待方式
* ================================================================ */
/** 永久等待(不超时) */
#define TASK_EVENT_WAIT_FOREVER 0xFFFFFFFF
/** 事件标记:等待所有位都置位(AND 模式) */
#define TASK_EVENT_FLAG_AND 0x01
/** 事件标记:等待任意位置位(OR 模式) */
#define TASK_EVENT_FLAG_OR 0x02
/** 事件标记:接收后自动清除已匹配的位 */
#define TASK_EVENT_FLAG_CLEAR 0x04
/* ================================================================
* 通用延时
* ================================================================ */
/**
* @brief 任务延时(毫秒级阻塞等待)
* @param ms 延时毫秒数
*/
void task_sleep_ms(uint32_t ms);
/* ================================================================
* 事件 API
* ================================================================ */
/**
* @brief 创建事件对象
* @param name 事件名称(调试用)
* @return 事件句柄,失败返回 NULL
*/
stru_task_event_t task_event_create(const char *name);
/**
* @brief 销毁事件对象
* @param p_event 事件句柄
* @return 0 成功,-1 失败
*/
int task_event_destroy(stru_task_event_t p_event);
/**
* @brief 发送事件(设置事件位)
* @param p_event 事件句柄
* @param event 要设置的事件位掩码
* @return 0 成功,-1 失败
*/
int task_event_send(stru_task_event_t p_event, uint32_t event);
/**
* @brief 等待事件
* @param p_event 事件句柄
* @param set 期望的事件位掩码
* @param opt 等待选项(TASK_EVENT_FLAG_AND/OR/CLEAR 组合)
* @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待)
* @param recved 输出参数:实际收到的事件位
* @return 0 成功,-1 超时或失败
*/
int task_event_recv(stru_task_event_t p_event, uint32_t set, uint32_t opt,
uint32_t timeout_ms, uint32_t *recved);
/**
* @brief 清除事件位
* @param p_event 事件句柄
* @param event 要清除的事件位掩码
* @return 0 成功,-1 失败
*/
int task_event_clear(stru_task_event_t p_event, uint32_t event);
/**
* @brief 查询当前事件位(非阻塞)
* @param p_event 事件句柄
* @return 当前事件位掩码
*/
uint32_t task_event_query(stru_task_event_t p_event);
/* ================================================================
* 消息队列 API
* ================================================================ */
/**
* @brief 创建定长消息队列
* @param name 队列名称(调试用)
* @param msg_size 每条消息的最大字节数
* @param msg_num 队列容量(最大消息条数)
* @return 队列句柄,失败返回 NULL
*/
stru_task_msg_queue_t task_msg_queue_create(const char *name,
uint32_t msg_size, uint32_t msg_num);
/**
* @brief 销毁消息队列
* @param p_queue 队列句柄
* @return 0 成功,-1 失败
*/
int task_msg_queue_destroy(stru_task_msg_queue_t p_queue);
/**
* @brief 发送消息(队列满时阻塞等待)
* @param p_queue 队列句柄
* @param msg 消息内容指针
* @param size 消息实际字节数(<= msg_size)
* @return 0 成功,-1 失败
*/
int task_msg_queue_send(stru_task_msg_queue_t p_queue, const void *msg,
uint32_t size);
/**
* @brief 发送消息(带超时)
* @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待)
* @return 0 成功,-1 超时或失败
*/
int task_msg_queue_send_timeout(stru_task_msg_queue_t p_queue, const void *msg,
uint32_t size, uint32_t timeout_ms);
/**
* @brief 接收消息(带超时)
* @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待)
* @return 0 成功,-1 超时或失败
*/
int task_msg_queue_recv(stru_task_msg_queue_t p_queue, void *msg,
uint32_t size, uint32_t timeout_ms);
/**
* @brief 尝试接收消息(非阻塞,队列空立即返回 -1)
* @return 0 成功,-1 队列空
*/
int task_msg_queue_try_recv(stru_task_msg_queue_t p_queue, void *msg,
uint32_t size);
/**
* @brief 获取队列中当前消息数
*/
uint32_t task_msg_queue_get_count(stru_task_msg_queue_t p_queue);
/**
* @brief 获取队列剩余可用空间(条数)
*/
uint32_t task_msg_queue_space(stru_task_msg_queue_t p_queue);
/* ================================================================
* 定时器 API
* ================================================================ */
/**
* @brief 创建定时器(创建后不会自动启动,需调用 task_timer_start)
* @param name 定时器名称(调试用)
* @param fun_cb 到期回调函数
* @param arg 回调参数
* @param timeout_ms 定时周期(毫秒)
* @param flags 标志位(TASK_TIMER_FLAG_ONCE 或 TASK_TIMER_FLAG_PERIODIC)
* @return 定时器句柄,失败返回 NULL
*/
stru_task_timer_t task_timer_create(const char *name, timer_func_cb fun_cb,
void *arg, uint32_t timeout_ms, int flags);
/**
* @brief 启动定时器
* @return 0 成功,-1 失败
*/
int task_timer_start(stru_task_timer_t p_timer);
/**
* @brief 停止定时器
* @return 0 成功,-1 失败
*/
int task_timer_stop(stru_task_timer_t p_timer);
/**
* @brief 重启定时器(可修改周期)
* @param timeout_ms 新的定时周期(毫秒)
* @return 0 成功,-1 失败
*/
int task_timer_restart(stru_task_timer_t p_timer, uint32_t timeout_ms);
/**
* @brief 销毁定时器
* @return 0 成功,-1 失败
*/
int task_timer_destroy(stru_task_timer_t p_timer);
/**
* @brief 查询定时器是否在运行
* @return 1=运行中,0=已停止
*/
int task_timer_is_active(stru_task_timer_t p_timer);
#ifdef __cplusplus
}
#endif
#endif /* _MY_TASK_H_ */

View File

@ -1,72 +0,0 @@
/**
* @file myXml.h
* @brief XML 解析库 — 纯 C 接口封装 tinyxml2
* @details 提供不透明句柄的 C 风格 XML DOM 操作。
* 内部 C++ tinyxml2 实现,外部纯 C 兼容。
*/
#ifndef _MY_XML_H_
#define _MY_XML_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* 不透明句柄 */
typedef void *myXmlDoc_t;
typedef void *myXmlElem_t;
/* ========== 文档生命周期 ========== */
/** 从文件加载 XML 文档,失败返回 NULL */
myXmlDoc_t myXml_load_file(const char *path);
/** 新建空 XML 文档(含 XML 声明) */
myXmlDoc_t myXml_new_doc(const char *root_name);
/** 释放文档 */
void myXml_free_doc(myXmlDoc_t doc);
/** 获取根元素 */
myXmlElem_t myXml_root_elem(myXmlDoc_t doc);
/** 保存文档到文件 */
int myXml_save_file(myXmlDoc_t doc, const char *path);
/* ========== 元素查询 ========== */
/** 查找第一个匹配名称的子元素 */
myXmlElem_t myXml_first_child(myXmlElem_t parent, const char *name);
/** 查找下一个匹配名称的兄弟元素 */
myXmlElem_t myXml_next_sibling(myXmlElem_t elem, const char *name);
/** 获取字符串属性,不存在返回默认值 */
const char *myXml_attr_str(myXmlElem_t elem, const char *name, const char *def_val);
/** 获取 float 属性,不存在返回默认值 */
float myXml_attr_float(myXmlElem_t elem, const char *name, float def_val);
/** 获取 int 属性,不存在返回默认值 */
int myXml_attr_int(myXmlElem_t elem, const char *name, int def_val);
/* ========== 元素创建 ========== */
/** 为父节点创建子元素 */
myXmlElem_t myXml_new_child(myXmlElem_t parent, const char *name);
/** 设置字符串属性 */
void myXml_set_attr(myXmlElem_t elem, const char *name, const char *value);
/** 设置 int 属性 */
void myXml_set_attr_int(myXmlElem_t elem, const char *name, int value);
/** 设置 float 属性 */
void myXml_set_attr_float(myXmlElem_t elem, const char *name, float value);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@ OBJS := $(patsubst $(S)/%.c,$(B)/%.o,$(SRCS))
F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View File

@ -12,7 +12,6 @@ F := $(CXX_FLAGS) $(I)
.PHONY: all .PHONY: all
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)

View File

@ -12,7 +12,6 @@ F := $(CXX_FLAGS) $(I)
.PHONY: all .PHONY: all
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)

View File

@ -10,7 +10,6 @@ OBJS := $(patsubst $(S)/%.c,$(B)/%.o,$(SRCS))
F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View File

@ -3,7 +3,6 @@ DST := $(ROOT_DIR)/release/inc
SRC_H := $(SRC_ROOT_DIR)/public/liblist/inc/list.h SRC_H := $(SRC_ROOT_DIR)/public/liblist/inc/list.h
all: all:
@mkdir -p $(DST) @mkdir -p $(DST)
@cp -f $(SRC_H) $(DST)/ 2>/dev/null && echo "[liblist] copied" || echo "[liblist] skip"
clean: clean:
@rm -f $(DST)/list.h @rm -f $(DST)/list.h
rebuild: clean all rebuild: clean all

View File

@ -10,7 +10,6 @@ OBJS := $(patsubst $(S)/%.c,$(B)/%.o,$(SRCS))
F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/libfunc/inc F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/libfunc/inc
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View File

@ -10,7 +10,6 @@ OBJS := $(patsubst $(S)/%.c,$(B)/%.o,$(SRCS))
F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View File

@ -10,7 +10,6 @@ OBJS := $(patsubst $(S)/%.c,$(B)/%.o,$(SRCS))
F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc F := $(C_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View File

@ -12,7 +12,6 @@ F := $(C_FLAGS) $(I)
.PHONY: all .PHONY: all
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)

View File

@ -12,7 +12,6 @@ F := $(CXX_FLAGS) $(I)
.PHONY: all .PHONY: all
all: all:
@mkdir -p $(ROOT_DIR)/release/inc @mkdir -p $(ROOT_DIR)/release/inc
@cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true
@$(MAKE) $(O) @$(MAKE) $(O)
$(O): $(OBJS) $(O): $(OBJS)

View File

@ -2,7 +2,9 @@ SUBDIRS := ./liblist ./libfunc ./liblog ./libmd5 ./libcJSON ./libmy_xxhash ./lib
define make_subdir define make_subdir
@for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done @for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
endef endef
.PHONY: all clean rebuild ROOT_DIR := $(realpath $(CURDIR)/../../..)
all:; $(call make_subdir,all) .PHONY: all clean rebuild headers
headers:; @cd $(ROOT_DIR) && ./release/copy_headers.sh
all: headers; $(call make_subdir,all)
clean:; $(call make_subdir,clean) clean:; $(call make_subdir,clean)
rebuild: clean all rebuild: clean all