diff --git a/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg b/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg new file mode 100644 index 000000000..ee69c3958 --- /dev/null +++ b/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg @@ -0,0 +1,21 @@ +{ + "name": "zlibstatic", + "cflags": "$(pkg-config --cflags zlib)", + "libs": "$(pkg-config --libs zlib)", + "include": [ + "zconf.h", + "zlib.h" + ], + "trimPrefixes": ["Z_"], + "cplusplus": false, + "mix":true, + "deps":["c/os"], + "symMap":{ + "compress":"Compress", + "compress2":"Compress2", + "uncompress":"Uncompress", + "uncompress2":"Uncompress2", + "compressBound":"CompressBound" + }, + "libstatic": true +} diff --git a/_llcppgtest/zlibstatic/demo/crc32demo/demo.go b/_llcppgtest/zlibstatic/demo/crc32demo/demo.go new file mode 100644 index 000000000..7a6131fb8 --- /dev/null +++ b/_llcppgtest/zlibstatic/demo/crc32demo/demo.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + "unsafe" + "zlibstatic" +) + +func main() { + ul := zlibstatic.ULong(0) + data := "Hello world" + res := ul.Crc32Z( + (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.StringData(data))), + zlibstatic.ZSizeT(uintptr(len(data))), + ) + fmt.Printf("%08x\n", res) +} diff --git a/_llcppgtest/zlibstatic/demo/efficiency/efficiency.go b/_llcppgtest/zlibstatic/demo/efficiency/efficiency.go new file mode 100644 index 000000000..680838843 --- /dev/null +++ b/_llcppgtest/zlibstatic/demo/efficiency/efficiency.go @@ -0,0 +1,38 @@ +package main + +import ( + "unsafe" + "zlibstatic" + + "github.com/goplus/lib/c" +) + +func main() { + txt := []byte("zlib is a software library used for data compression. It was created by Jean-loup Gailly and Mark Adler and first released in 1995. zlib is designed to be a free, legally unencumbered—that is, not covered by any patents—alternative to the proprietary DEFLATE compression algorithm, which is often used in software applications for data compression.The library provides functions to compress and decompress data using the DEFLATE algorithm, which is a combination of the LZ77 algorithm and Huffman coding. zlib is notable for its versatility; it can be used in a wide range of applications, from web servers and web clients compressing HTTP data, to the compression of data for storage or transmission in various file formats, such as PNG, ZIP, and GZIP.") + txtLen := zlibstatic.ULong(len(txt)) + + for level := 0; level <= 9; level++ { + cmpSize := zlibstatic.ULongf(zlibstatic.CompressBound(txtLen)) + cmpData := make([]byte, int(cmpSize)) + data := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + source := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) + res := zlibstatic.Compress2(data, &cmpSize, source, txtLen, c.Int(level)) + if res != zlibstatic.OK { + c.Printf(c.Str("\nCompression failed at level %d: %d\n"), level, res) + continue + } + + c.Printf(c.Str("Compression level %d: Text length = %d, Compressed size = %d\n"), level, txtLen, cmpSize) + + ucmpSize := zlibstatic.ULongf(txtLen) + ucmp := make([]byte, int(ucmpSize)) + ucmpData := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + cmpSource := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + + unRes := zlibstatic.Uncompress(ucmpData, &ucmpSize, cmpSource, zlibstatic.ULong(cmpSize)) + if unRes != zlibstatic.OK { + c.Printf(c.Str("\nDecompression failed at level %d: %d\n"), level, unRes) + continue + } + } +} diff --git a/_llcppgtest/zlibstatic/demo/normal/normal.go b/_llcppgtest/zlibstatic/demo/normal/normal.go new file mode 100644 index 000000000..4b03e6c6e --- /dev/null +++ b/_llcppgtest/zlibstatic/demo/normal/normal.go @@ -0,0 +1,43 @@ +package main + +import ( + "unsafe" + "zlibstatic" + + "github.com/goplus/lib/c" +) + +func main() { + txt := []byte("zlib is a software library used for data compression. It was created by Jean-loup Gailly and Mark Adler and first released in 1995. zlib is designed to be a free, legally unencumbered—that is, not covered by any patents—alternative to the proprietary DEFLATE compression algorithm, which is often used in software applications for data compression.The library provides functions to compress and decompress data using the DEFLATE algorithm, which is a combination of the LZ77 algorithm and Huffman coding. zlib is notable for its versatility; it can be used in a wide range of applications, from web servers and web clients compressing HTTP data, to the compression of data for storage or transmission in various file formats, such as PNG, ZIP, and GZIP.") + txtLen := zlibstatic.ULong(len(txt)) + + cmpSize := zlibstatic.ULongf(zlibstatic.CompressBound(txtLen)) + cmpData := make([]byte, int(cmpSize)) + data := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + txtData := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) + + res := zlibstatic.Compress(data, &cmpSize, txtData, txtLen) + if res != zlibstatic.OK { + c.Printf(c.Str("\nCompression failed: %d\n"), res) + return + } + + c.Printf(c.Str("Text length = %d, Compressed size = %d\n"), txtLen, cmpSize) + + ucmpSize := zlibstatic.ULongf(txtLen) + ucmp := make([]byte, int(ucmpSize)) + ucmpPtr := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + + unRes := zlibstatic.Uncompress(ucmpPtr, &ucmpSize, data, zlibstatic.ULong(cmpSize)) + c.Printf(c.Str("Decompression result = %d, Decompressed size %d\n"), unRes, ucmpSize) + + if unRes != zlibstatic.OK { + c.Printf(c.Str("\nDecompression failed: %d\n"), unRes) + return + } + + c.Printf(c.Str("Decompressed data: \n")) + for i := 0; i < int(ucmpSize); i++ { + c.Printf(c.Str("%c"), ucmp[i]) + } +} diff --git a/_llcppgtest/zlibstatic/llcppg.cfg b/_llcppgtest/zlibstatic/llcppg.cfg new file mode 100644 index 000000000..cd53cad4e --- /dev/null +++ b/_llcppgtest/zlibstatic/llcppg.cfg @@ -0,0 +1,20 @@ +{ + "name": "zlibstatic", + "cflags": "$(pkg-config --cflags zlib)", + "libs": "$(pkg-config --libs zlib)", + "include": [ + "zconf.h", + "zlib.h" + ], + "trimPrefixes": ["Z_"], + "cplusplus": false, + "deps":["c/os"], + "symMap":{ + "compress":"Compress", + "compress2":"Compress2", + "uncompress":"Uncompress", + "uncompress2":"Uncompress2", + "compressBound":"CompressBound" + }, + "libstatic": true +} diff --git a/_xtool/llcppsymg/internal/symg/lib_test.go b/_xtool/llcppsymg/internal/symg/lib_test.go index fcbc08bbd..5ee33d235 100644 --- a/_xtool/llcppsymg/internal/symg/lib_test.go +++ b/_xtool/llcppsymg/internal/symg/lib_test.go @@ -165,7 +165,7 @@ func TestGenDylibPaths(t *testing.T) { } if err != nil { - t.Fatalf("expected no error, got %w", err) + t.Fatalf("expected no error, got %v", err) } if !reflect.DeepEqual(notFounds, tc.wantNotFound) { diff --git a/_xtool/llcppsymg/internal/symg/symg.go b/_xtool/llcppsymg/internal/symg/symg.go index 593c8e046..2501957be 100644 --- a/_xtool/llcppsymg/internal/symg/symg.go +++ b/_xtool/llcppsymg/internal/symg/symg.go @@ -10,6 +10,7 @@ import ( "github.com/goplus/llcppg/_xtool/internal/clangtool" "github.com/goplus/llcppg/_xtool/internal/header" "github.com/goplus/llcppg/_xtool/internal/ld" + "github.com/goplus/llcppg/_xtool/internal/symbol" llcppg "github.com/goplus/llcppg/config" "github.com/goplus/llgo/xtool/nm" ) @@ -37,11 +38,11 @@ type Config struct { TrimPrefixes []string SymMap map[string]string IsCpp bool - libMode LibMode + LibMode LibMode } func Do(conf *Config) (symbolTable []*llcppg.SymbolInfo, err error) { - symbols, err := fetchSymbols(conf.Libs, conf.libMode) + symbols, err := fetchSymbols(conf.Libs, conf.LibMode) if err != nil { return } @@ -117,7 +118,7 @@ func fetchSymbols(lib string, mode LibMode) ([]*nm.Symbol, error) { for _, libFile := range libFiles { args := []string{"-g"} - if runtime.GOOS == "linux" { + if runtime.GOOS == "linux" && mode == symbol.ModeDynamic { args = append(args, "-D") } diff --git a/_xtool/llcppsymg/llcppsymg.go b/_xtool/llcppsymg/llcppsymg.go index aef494361..b6a7c0b53 100644 --- a/_xtool/llcppsymg/llcppsymg.go +++ b/_xtool/llcppsymg/llcppsymg.go @@ -21,6 +21,7 @@ import ( "fmt" "os" + "github.com/goplus/llcppg/_xtool/internal/symbol" "github.com/goplus/llcppg/_xtool/llcppsymg/internal/symg" llcppg "github.com/goplus/llcppg/config" args "github.com/goplus/llcppg/internal/arg" @@ -64,6 +65,11 @@ func main() { fmt.Fprintln(os.Stderr, "Failed to parse config file:", ags.CfgFile) } + libMode := symbol.ModeDynamic + if conf.LibStatic { + libMode = symbol.ModeStatic + } + symbolTable, err := symg.Do(&symg.Config{ Libs: conf.Libs, CFlags: conf.CFlags, @@ -72,6 +78,7 @@ func main() { TrimPrefixes: conf.TrimPrefixes, SymMap: conf.SymMap, IsCpp: conf.Cplusplus, + LibMode: libMode, }) check(err) diff --git a/config/config.go b/config/config.go index 44486a974..b50229457 100644 --- a/config/config.go +++ b/config/config.go @@ -33,6 +33,7 @@ type Config struct { Mix bool `json:"mix,omitempty"` SymMap map[string]string `json:"symMap,omitempty"` TypeMap map[string]string `json:"typeMap,omitempty"` + LibStatic bool `json:"libstatic,omitempty"` } func NewDefault() *Config { diff --git a/config/config_test.go b/config/config_test.go index fff625f0f..70fce1ab8 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -120,6 +120,25 @@ func TestGetConfByByte(t *testing.T) { mode: useStdin, }, + { + name: "Static library configuration", + input: `{ + "name": "mylib", + "cflags": "-I/opt/homebrew/include", + "include": ["mylib.h"], + "libs": "-L/opt/homebrew/lib -lmylib", + "libstatic": true + }`, + expect: llconfig.Config{ + Name: "mylib", + CFlags: "-I/opt/homebrew/include", + Include: []string{"mylib.h"}, + Libs: "-L/opt/homebrew/lib -lmylib", + LibStatic: true, + }, + mode: useFile, + }, + { name: "Invalid JSON", input: `{invalid json}`,