2025年1月

由于打算在特定的杰理MCU中引入第三方的库zlib实现deflate/inflate压缩和解压, 发现比较好的方式是单独选择核心文件进行编译.
zlib官网 https://www.zlib.net/
当前最新的zlib源码 : https://www.zlib.net/zlib-1.3.1.tar.gz
解压缩后, 让cursor生成了一个核心代码的makefile替代原zlib目录下的makefile,使用杰理br25的编译器,自己根据杰理官方的项目中的makefile, 增加了complier flags

TOOL_DIR := C:/JL/pi32/bin
CC    := $(TOOL_DIR)/clang.exe
CXX   := $(TOOL_DIR)/clang.exe
LD    := $(TOOL_DIR)/pi32v2-lto-wrapper.exe
AR    := $(TOOL_DIR)/pi32v2-lto-ar.exe
MKDIR := mkdir_win -p
RM    := rm -rf

# Compiler flags
CFLAGS  = -O2 -Wall -DZ_SOLO \
    -target pi32v2 \
    -mcpu=r3 \
    -integrated-as \
    -flto \
    -Wuninitialized \
    -Wno-invalid-noreturn \
    -fno-common \
    -integrated-as \
    -Oz \
    -g \
    -flto \
    -fallow-pointer-null \
    -fprefer-gnu-section \
    -Wno-shift-negative-value \
    -Wundef \
    -fms-extensions \
    -w \

LDFLAGS =

# Source files
# SRCS = adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c \
#        gzwrite.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c
SRCS = deflate.c inflate.c zutil.c
# Object files
OBJS = $(SRCS:.c=.o)

# Library name
LIBRARY = libz.a

# Default target
all: $(LIBRARY)

# Rule to build the library
$(LIBRARY): $(OBJS)
    $(AR) rcs $@ $(OBJS)

# Rule to compile source files
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

# Clean target
clean:
    $(RM) $(OBJS) $(LIBRARY)

.PHONY: all clean

zlib目录中运行make, 成功生成libz.a文件.

杰理的官方项目使用Code::Blocks作为编码IDE, 在Code::Blocks项目中添加libz.a: 菜单 > Project > Build Options > Linker Settings > Link Libraries中增加libz.a.
PS: 不放心还可以在other options中增加-LD:\d3\_git\c_proj\SDK_ble\apps\soundbox\zlib

注意, 上面只编译了核心的一些函数, 部分函数如compress/decompress没有. 要检查zlib中有哪些函数: c:\jl\pi32\bin\llvm-nm libz.a
显示如下:

deflate.o:
         U _dist_code
         U _length_code
         U _tr_align
         U _tr_flush_bits
         U _tr_flush_block
         U _tr_init
         U _tr_stored_block
         U adler32
-------- d configuration_table
         U crc32
-------- T deflate
-------- T deflateBound
-------- T deflateCopy
-------- T deflateEnd
-------- T deflateGetDictionary
-------- T deflateInit2_
-------- T deflateInit_
-------- T deflateParams
-------- T deflatePending
-------- T deflatePrime
-------- T deflateReset
-------- T deflateResetKeep
-------- T deflateSetDictionary
-------- T deflateSetHeader
-------- t deflateStateCheck
-------- T deflateTune
-------- D deflate_copyright
-------- t deflate_fast
-------- t deflate_slow
-------- t deflate_stored
-------- t fill_window
-------- t flush_pending
-------- t longest_match
-------- t putShortMSB
-------- t read_buf
-------- t slide_hash
         U z_errmsg
         U zmemcpy
         U zmemzero

inflate.o:
         U adler32
         U crc32
-------- d fixedtables.distfix
-------- d fixedtables.lenfix
-------- T inflate
-------- d inflate.order
-------- T inflateCodesUsed
-------- T inflateCopy
-------- T inflateEnd
-------- T inflateGetDictionary
-------- T inflateGetHeader
-------- T inflateInit2_
-------- T inflateInit_
-------- T inflateMark
-------- T inflatePrime
-------- T inflateReset
-------- T inflateReset2
-------- T inflateResetKeep
-------- T inflateSetDictionary
-------- t inflateStateCheck
-------- T inflateSync
-------- T inflateSyncPoint
-------- T inflateUndermine
-------- T inflateValidate
         U inflate_fast
         U inflate_table
-------- t syncsearch
-------- t updatewindow
         U zmemcpy

zutil.o:
-------- T zError
-------- D z_errmsg
-------- T zlibCompileFlags
-------- T zlibVersion
-------- T zmemcmp
-------- T zmemcpy
-------- T zmemzero

然后在项目的headers中增加zlib.h文件.
示例:


#define CHUNK 16384

int compress_data(const char *src, size_t src_len, unsigned char *dest, size_t *dest_len) {
    int ret;
    z_stream strm;

    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;

    ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
    if (ret != Z_OK) return ret;

    strm.avail_in = src_len;
    strm.next_in = (unsigned char *)src;
    strm.avail_out = CHUNK;
    strm.next_out = dest;

    ret = deflate(&strm, Z_FINISH);
    if (ret != Z_STREAM_END) {
        deflateEnd(&strm);
        return ret;
    }

    *dest_len = CHUNK - strm.avail_out;

    deflateEnd(&strm);
    return Z_OK;
}

int decompress_data(const unsigned char *src, size_t src_len, char *dest, size_t *dest_len) {
    int ret;
    z_stream strm;

    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;

    ret = inflateInit(&strm);
    if (ret != Z_OK) return ret;

    strm.avail_in = src_len;
    strm.next_in = (unsigned char *)src;

    strm.avail_out = CHUNK;
    strm.next_out = (unsigned char *)dest;

    ret = inflate(&strm, Z_NO_FLUSH);

    if (ret != Z_STREAM_END) {
        inflateEnd(&strm);
        return ret;
    }

    *dest_len = CHUNK - strm.avail_out;

    inflateEnd(&strm);

    return Z_OK;
}

int test_zlib() {
    const char *original_data = "Hello, World! This is a test of the zlib compression library.";

    size_t original_length = strlen(original_data) + 1; // +1 for null terminator

    unsigned char compressed[CHUNK];

   // Compress the data
   size_t compressed_length;
   if(compress_data(original_data, original_length, compressed, &compressed_length) != Z_OK){
       printf("Failed to compress data\n");
       return 1;
   }

   printf("Original length: %zu\n", original_length);
   printf("Compressed length: %zu\n", compressed_length);

   // Decompress the data
   char decompressed[CHUNK];
   size_t decompressed_length;
   if(decompress_data(compressed, compressed_length, decompressed, &decompressed_length) != Z_OK){
       printf("Failed to decompress data\n");
       return 1;
   }

   printf("Decompressed length: %zu\n", decompressed_length);
   printf("Decompressed data: %s\n", decompressed);


   return 0;
}

在主函数中引用test_zlib()就可以编译了. 实测编译通过.