From 6a83de355adec0e83105835708e25f33ae018939 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:49:43 +0000 Subject: [PATCH 01/16] Initial plan From 0e95f6a482bd8d580dbf556a25e441dbb6c010df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:53:26 +0000 Subject: [PATCH 02/16] Initial plan for adding libstatic support Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- parser/testdata/func/hfile/forwarddecl.h.i | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 parser/testdata/func/hfile/forwarddecl.h.i diff --git a/parser/testdata/func/hfile/forwarddecl.h.i b/parser/testdata/func/hfile/forwarddecl.h.i new file mode 100644 index 00000000..c3395222 --- /dev/null +++ b/parser/testdata/func/hfile/forwarddecl.h.i @@ -0,0 +1,10 @@ +# 1 "/home/runner/work/llcppg/llcppg/parser/testdata/func/hfile/forwarddecl.h" +# 1 "" 1 +# 1 "" 3 +# 453 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "/home/runner/work/llcppg/llcppg/parser/testdata/func/hfile/forwarddecl.h" 2 +void foo0(); +void foo1(int a); +void foo2(int a,...); From 3d094edbe90af9d8be06024be9e50b6d150ba125 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:59:30 +0000 Subject: [PATCH 03/16] Implement libstatic configuration support for static library symbol reading Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _xtool/llcppsymg/internal/symg/lib_test.go | 84 +++++++++++++++++++++- _xtool/llcppsymg/internal/symg/symg.go | 4 +- _xtool/llcppsymg/llcppsymg.go | 7 ++ config/config.go | 1 + config/config_test.go | 19 +++++ 5 files changed, 112 insertions(+), 3 deletions(-) diff --git a/_xtool/llcppsymg/internal/symg/lib_test.go b/_xtool/llcppsymg/internal/symg/lib_test.go index fcbc08bb..703afbbe 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) { @@ -188,3 +188,85 @@ func TestGenDylibPaths(t *testing.T) { } } + +func TestLibModeConfiguration(t *testing.T) { + testCases := []struct { + name string + libName string + mode symbol.Mode + expected string // expected file extension + }{ + { + name: "Dynamic library mode", + libName: "test", + mode: symbol.ModeDynamic, + expected: getExpectedDynamicExt(), + }, + { + name: "Static library mode", + libName: "test", + mode: symbol.ModeStatic, + expected: ".a", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tempDir, err := os.MkdirTemp("", "libmode_test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tempDir) + + // Create the expected library file + expectedFileName := fmt.Sprintf("lib%s%s", tc.libName, tc.expected) + expectedPath := filepath.Join(tempDir, expectedFileName) + + file, err := os.Create(expectedPath) + if err != nil { + t.Fatalf("Failed to create test file %s: %v", expectedPath, err) + } + file.Close() + + // Test that the library can be found with the correct mode + foundPath, err := symbol.FindLibFile(tempDir, tc.libName, tc.mode) + if err != nil { + t.Fatal(err) + } + + if foundPath != expectedPath { + t.Errorf("Expected path %s, got %s", expectedPath, foundPath) + } + + // Test that the Libs.Files method respects the mode + libs := &symg.Libs{ + Paths: []string{tempDir}, + Names: []string{tc.libName}, + } + + foundPaths, notFound, err := libs.Files([]string{}, tc.mode) + if err != nil { + t.Fatal(err) + } + + if len(notFound) > 0 { + t.Errorf("Expected no missing libraries, but found: %v", notFound) + } + + if len(foundPaths) != 1 { + t.Errorf("Expected 1 library path, got %d", len(foundPaths)) + } + + if foundPaths[0] != expectedPath { + t.Errorf("Expected path %s, got %s", expectedPath, foundPaths[0]) + } + }) + } +} + +func getExpectedDynamicExt() string { + if runtime.GOOS == "linux" { + return ".so" + } + return ".dylib" +} diff --git a/_xtool/llcppsymg/internal/symg/symg.go b/_xtool/llcppsymg/internal/symg/symg.go index 593c8e04..fccaf382 100644 --- a/_xtool/llcppsymg/internal/symg/symg.go +++ b/_xtool/llcppsymg/internal/symg/symg.go @@ -37,11 +37,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 } diff --git a/_xtool/llcppsymg/llcppsymg.go b/_xtool/llcppsymg/llcppsymg.go index aef49436..b6a7c0b5 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 44486a97..b5022945 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 fff625f0..70fce1ab 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}`, From f04b76b84da37c158c03be12b9791d07459dc0c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 03:07:29 +0000 Subject: [PATCH 04/16] Remove unnecessary intermediate file and update .gitignore Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- .gitignore | 3 +++ parser/testdata/func/hfile/forwarddecl.h.i | 10 ---------- 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 parser/testdata/func/hfile/forwarddecl.h.i diff --git a/.gitignore b/.gitignore index 8a4df88d..a1d671f9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out +# Preprocessor intermediate files +*.h.i + # Dependency directories (remove the comment below to include it) # vendor/ diff --git a/parser/testdata/func/hfile/forwarddecl.h.i b/parser/testdata/func/hfile/forwarddecl.h.i deleted file mode 100644 index c3395222..00000000 --- a/parser/testdata/func/hfile/forwarddecl.h.i +++ /dev/null @@ -1,10 +0,0 @@ -# 1 "/home/runner/work/llcppg/llcppg/parser/testdata/func/hfile/forwarddecl.h" -# 1 "" 1 -# 1 "" 3 -# 453 "" 3 -# 1 "" 1 -# 1 "" 2 -# 1 "/home/runner/work/llcppg/llcppg/parser/testdata/func/hfile/forwarddecl.h" 2 -void foo0(); -void foo1(int a); -void foo2(int a,...); From 72448b28cfc8e8d33ab483a3c07302e73cca3ba6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 03:17:30 +0000 Subject: [PATCH 05/16] Remove unnecessary .gitignore entry for *.h.i files Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index a1d671f9..8a4df88d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,9 +15,6 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out -# Preprocessor intermediate files -*.h.i - # Dependency directories (remove the comment below to include it) # vendor/ From bc80a8d340121b42618f217baf71ac56822b294b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 04:09:31 +0000 Subject: [PATCH 06/16] Remove problematic TestLibModeConfiguration test to fix llgo compatibility Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _xtool/llcppsymg/internal/symg/lib_test.go | 80 ---------------------- 1 file changed, 80 deletions(-) diff --git a/_xtool/llcppsymg/internal/symg/lib_test.go b/_xtool/llcppsymg/internal/symg/lib_test.go index 703afbbe..8e24c137 100644 --- a/_xtool/llcppsymg/internal/symg/lib_test.go +++ b/_xtool/llcppsymg/internal/symg/lib_test.go @@ -189,84 +189,4 @@ func TestGenDylibPaths(t *testing.T) { } } -func TestLibModeConfiguration(t *testing.T) { - testCases := []struct { - name string - libName string - mode symbol.Mode - expected string // expected file extension - }{ - { - name: "Dynamic library mode", - libName: "test", - mode: symbol.ModeDynamic, - expected: getExpectedDynamicExt(), - }, - { - name: "Static library mode", - libName: "test", - mode: symbol.ModeStatic, - expected: ".a", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - tempDir, err := os.MkdirTemp("", "libmode_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - // Create the expected library file - expectedFileName := fmt.Sprintf("lib%s%s", tc.libName, tc.expected) - expectedPath := filepath.Join(tempDir, expectedFileName) - - file, err := os.Create(expectedPath) - if err != nil { - t.Fatalf("Failed to create test file %s: %v", expectedPath, err) - } - file.Close() - - // Test that the library can be found with the correct mode - foundPath, err := symbol.FindLibFile(tempDir, tc.libName, tc.mode) - if err != nil { - t.Fatal(err) - } - - if foundPath != expectedPath { - t.Errorf("Expected path %s, got %s", expectedPath, foundPath) - } - - // Test that the Libs.Files method respects the mode - libs := &symg.Libs{ - Paths: []string{tempDir}, - Names: []string{tc.libName}, - } - - foundPaths, notFound, err := libs.Files([]string{}, tc.mode) - if err != nil { - t.Fatal(err) - } - if len(notFound) > 0 { - t.Errorf("Expected no missing libraries, but found: %v", notFound) - } - - if len(foundPaths) != 1 { - t.Errorf("Expected 1 library path, got %d", len(foundPaths)) - } - - if foundPaths[0] != expectedPath { - t.Errorf("Expected path %s, got %s", expectedPath, foundPaths[0]) - } - }) - } -} - -func getExpectedDynamicExt() string { - if runtime.GOOS == "linux" { - return ".so" - } - return ".dylib" -} From e47e67982ba4794c3382bb9e5ebda1fe225e62a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 06:16:54 +0000 Subject: [PATCH 07/16] Remove unexpected empty lines and add zlib-static demo for libstatic testing Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _llcppgtest/zlib-static/conf/linux/llcppg.cfg | 21 +++++++++ .../zlib-static/demo/crc32demo/demo.go | 17 ++++++++ .../zlib-static/demo/efficiency/efficiency.go | 38 ++++++++++++++++ _llcppgtest/zlib-static/demo/normal/normal.go | 43 +++++++++++++++++++ _llcppgtest/zlib-static/llcppg.cfg | 20 +++++++++ _xtool/llcppsymg/internal/symg/lib_test.go | 2 - 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 _llcppgtest/zlib-static/conf/linux/llcppg.cfg create mode 100644 _llcppgtest/zlib-static/demo/crc32demo/demo.go create mode 100644 _llcppgtest/zlib-static/demo/efficiency/efficiency.go create mode 100644 _llcppgtest/zlib-static/demo/normal/normal.go create mode 100644 _llcppgtest/zlib-static/llcppg.cfg diff --git a/_llcppgtest/zlib-static/conf/linux/llcppg.cfg b/_llcppgtest/zlib-static/conf/linux/llcppg.cfg new file mode 100644 index 00000000..741a0660 --- /dev/null +++ b/_llcppgtest/zlib-static/conf/linux/llcppg.cfg @@ -0,0 +1,21 @@ +{ + "name": "zlib-static", + "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/zlib-static/demo/crc32demo/demo.go b/_llcppgtest/zlib-static/demo/crc32demo/demo.go new file mode 100644 index 00000000..980fd6db --- /dev/null +++ b/_llcppgtest/zlib-static/demo/crc32demo/demo.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + "unsafe" + "zlib-static" +) + +func main() { + ul := zlib_static.ULong(0) + data := "Hello world" + res := ul.Crc32Z( + (*zlib_static.Bytef)(unsafe.Pointer(unsafe.StringData(data))), + zlib_static.ZSizeT(uintptr(len(data))), + ) + fmt.Printf("%08x\n", res) +} diff --git a/_llcppgtest/zlib-static/demo/efficiency/efficiency.go b/_llcppgtest/zlib-static/demo/efficiency/efficiency.go new file mode 100644 index 00000000..b1e98a8b --- /dev/null +++ b/_llcppgtest/zlib-static/demo/efficiency/efficiency.go @@ -0,0 +1,38 @@ +package main + +import ( + "unsafe" + "zlib-static" + + "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 := zlib_static.ULong(len(txt)) + + for level := 0; level <= 9; level++ { + cmpSize := zlib_static.ULongf(zlib_static.CompressBound(txtLen)) + cmpData := make([]byte, int(cmpSize)) + data := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + source := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) + res := zlib_static.Compress2(data, &cmpSize, source, txtLen, c.Int(level)) + if res != zlib_static.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 := zlib_static.ULongf(txtLen) + ucmp := make([]byte, int(ucmpSize)) + ucmpData := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + cmpSource := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + + unRes := zlib_static.Uncompress(ucmpData, &ucmpSize, cmpSource, zlib_static.ULong(cmpSize)) + if unRes != zlib_static.OK { + c.Printf(c.Str("\nDecompression failed at level %d: %d\n"), level, unRes) + continue + } + } +} diff --git a/_llcppgtest/zlib-static/demo/normal/normal.go b/_llcppgtest/zlib-static/demo/normal/normal.go new file mode 100644 index 00000000..9f15e416 --- /dev/null +++ b/_llcppgtest/zlib-static/demo/normal/normal.go @@ -0,0 +1,43 @@ +package main + +import ( + "unsafe" + "zlib-static" + + "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 := zlib_static.ULong(len(txt)) + + cmpSize := zlib_static.ULongf(zlib_static.CompressBound(txtLen)) + cmpData := make([]byte, int(cmpSize)) + data := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + txtData := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) + + res := zlib_static.Compress(data, &cmpSize, txtData, txtLen) + if res != zlib_static.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 := zlib_static.ULongf(txtLen) + ucmp := make([]byte, int(ucmpSize)) + ucmpPtr := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + + unRes := zlib_static.Uncompress(ucmpPtr, &ucmpSize, data, zlib_static.ULong(cmpSize)) + c.Printf(c.Str("Decompression result = %d, Decompressed size %d\n"), unRes, ucmpSize) + + if unRes != zlib_static.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/zlib-static/llcppg.cfg b/_llcppgtest/zlib-static/llcppg.cfg new file mode 100644 index 00000000..2789ccae --- /dev/null +++ b/_llcppgtest/zlib-static/llcppg.cfg @@ -0,0 +1,20 @@ +{ + "name": "zlib-static", + "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 8e24c137..5ee33d23 100644 --- a/_xtool/llcppsymg/internal/symg/lib_test.go +++ b/_xtool/llcppsymg/internal/symg/lib_test.go @@ -188,5 +188,3 @@ func TestGenDylibPaths(t *testing.T) { } } - - From 4aad4845a854345638fcb2cd8cd33194dcca8a74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 06:44:26 +0000 Subject: [PATCH 08/16] Fix symbol extraction for static libraries by removing -D flag Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _xtool/llcppsymg/internal/symg/symg.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_xtool/llcppsymg/internal/symg/symg.go b/_xtool/llcppsymg/internal/symg/symg.go index fccaf382..2501957b 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" ) @@ -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") } From 09012efc78957e5afdef61d916af47a021925ca7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:03:00 +0000 Subject: [PATCH 09/16] Fix zlib-static demo package name to be valid Go identifier Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _llcppgtest/zlib-static/conf/linux/llcppg.cfg | 2 +- .../zlib-static/demo/crc32demo/demo.go | 8 +++---- .../zlib-static/demo/efficiency/efficiency.go | 24 +++++++++---------- _llcppgtest/zlib-static/demo/normal/normal.go | 22 ++++++++--------- _llcppgtest/zlib-static/llcppg.cfg | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/_llcppgtest/zlib-static/conf/linux/llcppg.cfg b/_llcppgtest/zlib-static/conf/linux/llcppg.cfg index 741a0660..ee69c395 100644 --- a/_llcppgtest/zlib-static/conf/linux/llcppg.cfg +++ b/_llcppgtest/zlib-static/conf/linux/llcppg.cfg @@ -1,5 +1,5 @@ { - "name": "zlib-static", + "name": "zlibstatic", "cflags": "$(pkg-config --cflags zlib)", "libs": "$(pkg-config --libs zlib)", "include": [ diff --git a/_llcppgtest/zlib-static/demo/crc32demo/demo.go b/_llcppgtest/zlib-static/demo/crc32demo/demo.go index 980fd6db..7a6131fb 100644 --- a/_llcppgtest/zlib-static/demo/crc32demo/demo.go +++ b/_llcppgtest/zlib-static/demo/crc32demo/demo.go @@ -3,15 +3,15 @@ package main import ( "fmt" "unsafe" - "zlib-static" + "zlibstatic" ) func main() { - ul := zlib_static.ULong(0) + ul := zlibstatic.ULong(0) data := "Hello world" res := ul.Crc32Z( - (*zlib_static.Bytef)(unsafe.Pointer(unsafe.StringData(data))), - zlib_static.ZSizeT(uintptr(len(data))), + (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.StringData(data))), + zlibstatic.ZSizeT(uintptr(len(data))), ) fmt.Printf("%08x\n", res) } diff --git a/_llcppgtest/zlib-static/demo/efficiency/efficiency.go b/_llcppgtest/zlib-static/demo/efficiency/efficiency.go index b1e98a8b..68083884 100644 --- a/_llcppgtest/zlib-static/demo/efficiency/efficiency.go +++ b/_llcppgtest/zlib-static/demo/efficiency/efficiency.go @@ -2,35 +2,35 @@ package main import ( "unsafe" - "zlib-static" + "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 := zlib_static.ULong(len(txt)) + txtLen := zlibstatic.ULong(len(txt)) for level := 0; level <= 9; level++ { - cmpSize := zlib_static.ULongf(zlib_static.CompressBound(txtLen)) + cmpSize := zlibstatic.ULongf(zlibstatic.CompressBound(txtLen)) cmpData := make([]byte, int(cmpSize)) - data := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) - source := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) - res := zlib_static.Compress2(data, &cmpSize, source, txtLen, c.Int(level)) - if res != zlib_static.OK { + 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 := zlib_static.ULongf(txtLen) + ucmpSize := zlibstatic.ULongf(txtLen) ucmp := make([]byte, int(ucmpSize)) - ucmpData := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) - cmpSource := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + ucmpData := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + cmpSource := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) - unRes := zlib_static.Uncompress(ucmpData, &ucmpSize, cmpSource, zlib_static.ULong(cmpSize)) - if unRes != zlib_static.OK { + 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/zlib-static/demo/normal/normal.go b/_llcppgtest/zlib-static/demo/normal/normal.go index 9f15e416..4b03e6c6 100644 --- a/_llcppgtest/zlib-static/demo/normal/normal.go +++ b/_llcppgtest/zlib-static/demo/normal/normal.go @@ -2,36 +2,36 @@ package main import ( "unsafe" - "zlib-static" + "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 := zlib_static.ULong(len(txt)) + txtLen := zlibstatic.ULong(len(txt)) - cmpSize := zlib_static.ULongf(zlib_static.CompressBound(txtLen)) + cmpSize := zlibstatic.ULongf(zlibstatic.CompressBound(txtLen)) cmpData := make([]byte, int(cmpSize)) - data := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) - txtData := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) + data := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(cmpData))) + txtData := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(txt))) - res := zlib_static.Compress(data, &cmpSize, txtData, txtLen) - if res != zlib_static.OK { + 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 := zlib_static.ULongf(txtLen) + ucmpSize := zlibstatic.ULongf(txtLen) ucmp := make([]byte, int(ucmpSize)) - ucmpPtr := (*zlib_static.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) + ucmpPtr := (*zlibstatic.Bytef)(unsafe.Pointer(unsafe.SliceData(ucmp))) - unRes := zlib_static.Uncompress(ucmpPtr, &ucmpSize, data, zlib_static.ULong(cmpSize)) + unRes := zlibstatic.Uncompress(ucmpPtr, &ucmpSize, data, zlibstatic.ULong(cmpSize)) c.Printf(c.Str("Decompression result = %d, Decompressed size %d\n"), unRes, ucmpSize) - if unRes != zlib_static.OK { + if unRes != zlibstatic.OK { c.Printf(c.Str("\nDecompression failed: %d\n"), unRes) return } diff --git a/_llcppgtest/zlib-static/llcppg.cfg b/_llcppgtest/zlib-static/llcppg.cfg index 2789ccae..cd53cad4 100644 --- a/_llcppgtest/zlib-static/llcppg.cfg +++ b/_llcppgtest/zlib-static/llcppg.cfg @@ -1,5 +1,5 @@ { - "name": "zlib-static", + "name": "zlibstatic", "cflags": "$(pkg-config --cflags zlib)", "libs": "$(pkg-config --libs zlib)", "include": [ From f9844c624e8383c1631736a4ecd34d4705b989e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:18:58 +0000 Subject: [PATCH 10/16] Rename zlib-static folder to zlibstatic to match package name Co-authored-by: luoliwoshang <51194195+luoliwoshang@users.noreply.github.com> --- _llcppgtest/{zlib-static => zlibstatic}/conf/linux/llcppg.cfg | 0 _llcppgtest/{zlib-static => zlibstatic}/demo/crc32demo/demo.go | 0 .../{zlib-static => zlibstatic}/demo/efficiency/efficiency.go | 0 _llcppgtest/{zlib-static => zlibstatic}/demo/normal/normal.go | 0 _llcppgtest/{zlib-static => zlibstatic}/llcppg.cfg | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename _llcppgtest/{zlib-static => zlibstatic}/conf/linux/llcppg.cfg (100%) rename _llcppgtest/{zlib-static => zlibstatic}/demo/crc32demo/demo.go (100%) rename _llcppgtest/{zlib-static => zlibstatic}/demo/efficiency/efficiency.go (100%) rename _llcppgtest/{zlib-static => zlibstatic}/demo/normal/normal.go (100%) rename _llcppgtest/{zlib-static => zlibstatic}/llcppg.cfg (100%) diff --git a/_llcppgtest/zlib-static/conf/linux/llcppg.cfg b/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg similarity index 100% rename from _llcppgtest/zlib-static/conf/linux/llcppg.cfg rename to _llcppgtest/zlibstatic/conf/linux/llcppg.cfg diff --git a/_llcppgtest/zlib-static/demo/crc32demo/demo.go b/_llcppgtest/zlibstatic/demo/crc32demo/demo.go similarity index 100% rename from _llcppgtest/zlib-static/demo/crc32demo/demo.go rename to _llcppgtest/zlibstatic/demo/crc32demo/demo.go diff --git a/_llcppgtest/zlib-static/demo/efficiency/efficiency.go b/_llcppgtest/zlibstatic/demo/efficiency/efficiency.go similarity index 100% rename from _llcppgtest/zlib-static/demo/efficiency/efficiency.go rename to _llcppgtest/zlibstatic/demo/efficiency/efficiency.go diff --git a/_llcppgtest/zlib-static/demo/normal/normal.go b/_llcppgtest/zlibstatic/demo/normal/normal.go similarity index 100% rename from _llcppgtest/zlib-static/demo/normal/normal.go rename to _llcppgtest/zlibstatic/demo/normal/normal.go diff --git a/_llcppgtest/zlib-static/llcppg.cfg b/_llcppgtest/zlibstatic/llcppg.cfg similarity index 100% rename from _llcppgtest/zlib-static/llcppg.cfg rename to _llcppgtest/zlibstatic/llcppg.cfg From 5963ea7cf3807c90d7352dc595facbcfae8b7b1c Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Fri, 27 Jun 2025 18:10:21 +0800 Subject: [PATCH 11/16] test(demotest):with static mode --- _llcppgtest/zlibstatic/conf/linux/llcppg.cfg | 21 --------- _llcppgtest/zlibstatic/demo/crc32demo/demo.go | 17 -------- .../zlibstatic/demo/efficiency/efficiency.go | 38 ---------------- _llcppgtest/zlibstatic/demo/normal/normal.go | 43 ------------------- _llcppgtest/zlibstatic/llcppg.cfg | 20 --------- cmd/llcppgtest/demo/demo.go | 22 ++++++++++ 6 files changed, 22 insertions(+), 139 deletions(-) delete mode 100644 _llcppgtest/zlibstatic/conf/linux/llcppg.cfg delete mode 100644 _llcppgtest/zlibstatic/demo/crc32demo/demo.go delete mode 100644 _llcppgtest/zlibstatic/demo/efficiency/efficiency.go delete mode 100644 _llcppgtest/zlibstatic/demo/normal/normal.go delete mode 100644 _llcppgtest/zlibstatic/llcppg.cfg diff --git a/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg b/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg deleted file mode 100644 index ee69c395..00000000 --- a/_llcppgtest/zlibstatic/conf/linux/llcppg.cfg +++ /dev/null @@ -1,21 +0,0 @@ -{ - "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 deleted file mode 100644 index 7a6131fb..00000000 --- a/_llcppgtest/zlibstatic/demo/crc32demo/demo.go +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 68083884..00000000 --- a/_llcppgtest/zlibstatic/demo/efficiency/efficiency.go +++ /dev/null @@ -1,38 +0,0 @@ -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 deleted file mode 100644 index 4b03e6c6..00000000 --- a/_llcppgtest/zlibstatic/demo/normal/normal.go +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index cd53cad4..00000000 --- a/_llcppgtest/zlibstatic/llcppg.cfg +++ /dev/null @@ -1,20 +0,0 @@ -{ - "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/cmd/llcppgtest/demo/demo.go b/cmd/llcppgtest/demo/demo.go index 986f4fdd..f5a69fa6 100644 --- a/cmd/llcppgtest/demo/demo.go +++ b/cmd/llcppgtest/demo/demo.go @@ -1,6 +1,7 @@ package demo import ( + "encoding/json" "fmt" "os" @@ -97,6 +98,27 @@ func RunGenPkgDemo(demoRoot string, confDir string) error { return fmt.Errorf("config file not found: %s", configFile) } + configFileContent, err := os.ReadFile(configFile) + if err != nil { + return fmt.Errorf("failed to read config file: %w", err) + } + + configFileMap := make(map[string]interface{}) + err = json.Unmarshal(configFileContent, &configFileMap) + if err != nil { + return fmt.Errorf("failed to unmarshal config file: %w", err) + } + // write libstatic to config file + configFileMap["libstatic"] = true + configFileContent, err = json.Marshal(configFileMap) + if err != nil { + return fmt.Errorf("failed to marshal config file: %w", err) + } + err = os.WriteFile(configFile, configFileContent, os.ModePerm) + if err != nil { + return fmt.Errorf("failed to write config file: %w", err) + } + llcppgArgs := []string{"-v", "-mod", demoPkgName} outDir := filepath.Join(absPath, "out") From f298dd710c5e045ed6881babc5041b0f87f6a4c3 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 30 Jun 2025 14:13:10 +0800 Subject: [PATCH 12/16] chore:remove test demo --- cmd/llcppgtest/demo/demo.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/cmd/llcppgtest/demo/demo.go b/cmd/llcppgtest/demo/demo.go index f5a69fa6..986f4fdd 100644 --- a/cmd/llcppgtest/demo/demo.go +++ b/cmd/llcppgtest/demo/demo.go @@ -1,7 +1,6 @@ package demo import ( - "encoding/json" "fmt" "os" @@ -98,27 +97,6 @@ func RunGenPkgDemo(demoRoot string, confDir string) error { return fmt.Errorf("config file not found: %s", configFile) } - configFileContent, err := os.ReadFile(configFile) - if err != nil { - return fmt.Errorf("failed to read config file: %w", err) - } - - configFileMap := make(map[string]interface{}) - err = json.Unmarshal(configFileContent, &configFileMap) - if err != nil { - return fmt.Errorf("failed to unmarshal config file: %w", err) - } - // write libstatic to config file - configFileMap["libstatic"] = true - configFileContent, err = json.Marshal(configFileMap) - if err != nil { - return fmt.Errorf("failed to marshal config file: %w", err) - } - err = os.WriteFile(configFile, configFileContent, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to write config file: %w", err) - } - llcppgArgs := []string{"-v", "-mod", demoPkgName} outDir := filepath.Join(absPath, "out") From 6830aae8c1b2226341bff007d37faf4c752f8fe3 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 30 Jun 2025 15:19:34 +0800 Subject: [PATCH 13/16] e2etest:check static lib mode --- _cmptest/llcppgend_test.go | 61 +++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/_cmptest/llcppgend_test.go b/_cmptest/llcppgend_test.go index 5cc09fb5..d5e89b0f 100644 --- a/_cmptest/llcppgend_test.go +++ b/_cmptest/llcppgend_test.go @@ -1,8 +1,10 @@ package _cmptest import ( + "encoding/json" "fmt" "io" + "maps" "os" "os/exec" "path/filepath" @@ -114,7 +116,7 @@ var mkdirTempLazily = sync.OnceValue(func() string { return dir }) -func logFile(tc testCase) (*os.File, error) { +func logFile(tc testCase, isStatic bool) (*os.File, error) { caseName := fmt.Sprintf("%s-%s-llcppg-%s-%s", runtime.GOOS, runtime.GOARCH, tc.pkg.Name, tc.pkg.Version) dirPath := filepath.Join(mkdirTempLazily(), caseName) @@ -123,6 +125,9 @@ func logFile(tc testCase) (*os.File, error) { return nil, err } + if isStatic { + return os.Create(filepath.Join(dirPath, fmt.Sprintf("%s-static.log", caseName))) + } return os.Create(filepath.Join(dirPath, fmt.Sprintf("%s.log", caseName))) } @@ -131,13 +136,23 @@ func TestEnd2End(t *testing.T) { tc := tc t.Run(fmt.Sprintf("%s/%s", tc.pkg.Name, tc.pkg.Version), func(t *testing.T) { t.Parallel() - testFrom(t, tc, false) + testFrom(t, tc, false, false) + }) + t.Run(fmt.Sprintf("%s/%s-static", tc.pkg.Name, tc.pkg.Version), func(t *testing.T) { + t.Parallel() + testFrom(t, tc, true, false) }) } } -func testFrom(t *testing.T, tc testCase, gen bool) { - logFile, err := logFile(tc) +func testFrom(t *testing.T, tc testCase, isStatic bool, gen bool) { + null, err := os.OpenFile(os.DevNull, os.O_RDWR, 0644) + if err != nil { + t.Fatal(err) + } + defer null.Close() + + logFile, err := logFile(tc, isStatic) if err != nil { t.Fatal(err) } @@ -160,10 +175,42 @@ func testFrom(t *testing.T, tc testCase, gen bool) { cfgPath := filepath.Join(wd, tc.dir, tc.pkg.Name, config.LLCPPG_CFG) processCfgPath := filepath.Join(resultDir, config.LLCPPG_CFG) - copyFile(cfgPath, processCfgPath) + + // when isStatic is true, replace the libstatic=False to libstatic=True + if !isStatic { + copyFile(cfgPath, processCfgPath) + } else { + cfgContent, err := os.ReadFile(cfgPath) + if err != nil { + t.Fatal(err) + } + var cfg map[string]interface{} + err = json.Unmarshal(cfgContent, &cfg) + if err != nil { + t.Fatal(err) + } + cfg["libstatic"] = true + cfgContent, err = json.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(processCfgPath, cfgContent, os.ModePerm) + if err != nil { + t.Fatal(err) + } + } + + if tc.config == nil { + tc.config = make(map[string]string) + } + + conanOpt := maps.Clone(tc.config) + if isStatic { + conanOpt["options"] = "*:shared=False " + conanOpt["options"] + } conanInstallMutex.Lock() - _, err = conan.NewConanInstaller(tc.config).Install(tc.pkg, conanDir) + _, err = conan.NewConanInstaller(conanOpt).Install(tc.pkg, conanDir) conanInstallMutex.Unlock() if err != nil { t.Fatal(err) @@ -180,7 +227,7 @@ func testFrom(t *testing.T, tc testCase, gen bool) { // llcppg.symb.json is a middle file os.Remove(filepath.Join(resultDir, config.LLCPPG_SYMB)) - copyFile(processCfgPath, filepath.Join(resultDir, tc.pkg.Name, config.LLCPPG_CFG)) + copyFile(cfgPath, filepath.Join(resultDir, tc.pkg.Name, config.LLCPPG_CFG)) if gen { os.RemoveAll(dir) From 042ab6f7b6ca9d85ae989d1a5df9d9a1d81ab144 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 30 Jun 2025 16:15:42 +0800 Subject: [PATCH 14/16] chore:libstatic to staticLib --- _cmptest/llcppgend_test.go | 4 ++-- _xtool/llcppsymg/llcppsymg.go | 2 +- config/config.go | 2 +- config/config_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_cmptest/llcppgend_test.go b/_cmptest/llcppgend_test.go index d5e89b0f..6515a137 100644 --- a/_cmptest/llcppgend_test.go +++ b/_cmptest/llcppgend_test.go @@ -176,7 +176,7 @@ func testFrom(t *testing.T, tc testCase, isStatic bool, gen bool) { cfgPath := filepath.Join(wd, tc.dir, tc.pkg.Name, config.LLCPPG_CFG) processCfgPath := filepath.Join(resultDir, config.LLCPPG_CFG) - // when isStatic is true, replace the libstatic=False to libstatic=True + // when isStatic is true, replace the staticLib=False to staticLib=True if !isStatic { copyFile(cfgPath, processCfgPath) } else { @@ -189,7 +189,7 @@ func testFrom(t *testing.T, tc testCase, isStatic bool, gen bool) { if err != nil { t.Fatal(err) } - cfg["libstatic"] = true + cfg["staticLib"] = true cfgContent, err = json.Marshal(cfg) if err != nil { t.Fatal(err) diff --git a/_xtool/llcppsymg/llcppsymg.go b/_xtool/llcppsymg/llcppsymg.go index b6a7c0b5..787b1e93 100644 --- a/_xtool/llcppsymg/llcppsymg.go +++ b/_xtool/llcppsymg/llcppsymg.go @@ -66,7 +66,7 @@ func main() { } libMode := symbol.ModeDynamic - if conf.LibStatic { + if conf.StaticLib { libMode = symbol.ModeStatic } diff --git a/config/config.go b/config/config.go index b5022945..2433e5f7 100644 --- a/config/config.go +++ b/config/config.go @@ -33,7 +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"` + StaticLib bool `json:"staticLib,omitempty"` } func NewDefault() *Config { diff --git a/config/config_test.go b/config/config_test.go index 70fce1ab..21870f1e 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -127,14 +127,14 @@ func TestGetConfByByte(t *testing.T) { "cflags": "-I/opt/homebrew/include", "include": ["mylib.h"], "libs": "-L/opt/homebrew/lib -lmylib", - "libstatic": true + "staticLib": true }`, expect: llconfig.Config{ Name: "mylib", CFlags: "-I/opt/homebrew/include", Include: []string{"mylib.h"}, Libs: "-L/opt/homebrew/lib -lmylib", - LibStatic: true, + StaticLib: true, }, mode: useFile, }, From 02e66957a488196088f2763a3c951d9fec637c85 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 30 Jun 2025 17:29:39 +0800 Subject: [PATCH 15/16] dylib -> lib to descript --- _xtool/llcppsymg/internal/symg/lib.go | 4 +-- _xtool/llcppsymg/internal/symg/symg_test.go | 36 ++++++++++----------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/_xtool/llcppsymg/internal/symg/lib.go b/_xtool/llcppsymg/internal/symg/lib.go index 5b987df7..0217c90d 100644 --- a/_xtool/llcppsymg/internal/symg/lib.go +++ b/_xtool/llcppsymg/internal/symg/lib.go @@ -28,9 +28,9 @@ func ParseLibs(libs string) *Libs { type LibMode = symbol.Mode // searches for each library name in the provided paths and default paths, -// appending the appropriate file extension (.dylib for macOS, .so for Linux). +// appending the appropriate file extension (.dylib for macOS, .so for Linux at dylib mode, .a for static mode). // -// Example: For "-L/opt/homebrew/lib -llua -lm": +// Example: For "-L/opt/homebrew/lib -llua -lm" and at dylib mode: // - It will search for liblua.dylib (on macOS) or liblua.so (on Linux) // - System libs like -lm are ignored and included in notFound // diff --git a/_xtool/llcppsymg/internal/symg/symg_test.go b/_xtool/llcppsymg/internal/symg/symg_test.go index a0670824..9ff528a0 100644 --- a/_xtool/llcppsymg/internal/symg/symg_test.go +++ b/_xtool/llcppsymg/internal/symg/symg_test.go @@ -73,13 +73,13 @@ func TestGenMethodName(t *testing.T) { func TestGetCommonSymbols(t *testing.T) { testCases := []struct { name string - dylibSymbols []*nm.Symbol + libSymbols []*nm.Symbol headerSymbols map[string]*symg.SymbolInfo expect []*llcppg.SymbolInfo }{ { name: "Lua symbols", - dylibSymbols: []*nm.Symbol{ + libSymbols: []*nm.Symbol{ {Name: addSymbolPrefixUnder("lua_absindex", false)}, {Name: addSymbolPrefixUnder("lua_arith", false)}, {Name: addSymbolPrefixUnder("lua_atpanic", false)}, @@ -102,7 +102,7 @@ func TestGetCommonSymbols(t *testing.T) { }, { name: "INIReader and Std library symbols", - dylibSymbols: []*nm.Symbol{ + libSymbols: []*nm.Symbol{ {Name: addSymbolPrefixUnder("ZNK9INIReader12GetInteger64ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_x", true)}, {Name: addSymbolPrefixUnder("ZNK9INIReader7GetRealERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_d", true)}, {Name: addSymbolPrefixUnder("ZNK9INIReader10ParseErrorEv", true)}, @@ -124,7 +124,7 @@ func TestGetCommonSymbols(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - commonSymbols := symg.GetCommonSymbols(tc.dylibSymbols, tc.headerSymbols) + commonSymbols := symg.GetCommonSymbols(tc.libSymbols, tc.headerSymbols) if !reflect.DeepEqual(commonSymbols, tc.expect) { t.Fatalf("expect %v, but got %v", tc.expect, commonSymbols) } @@ -381,14 +381,14 @@ class INIReader { func TestGen(t *testing.T) { gen := false testCases := []struct { - name string - path string - dylibSymbols []string + name string + path string + libSymbols []string }{ { name: "c", path: "./testdata/c", - dylibSymbols: []string{ + libSymbols: []string{ "Foo_Print", "Foo_ParseWithLength", "Foo_Delete", @@ -410,7 +410,7 @@ func TestGen(t *testing.T) { { name: "cpp", path: "./testdata/cpp", - dylibSymbols: []string{ + libSymbols: []string{ "ZN3FooC1EPKc", "ZN3FooC1EPKcl", "ZN3FooD1Ev", @@ -422,7 +422,7 @@ func TestGen(t *testing.T) { { name: "inireader", path: "./testdata/inireader", - dylibSymbols: []string{ + libSymbols: []string{ "ZN9INIReaderC1EPKc", "ZN9INIReaderC1EPKcl", "ZN9INIReaderD1Ev", @@ -433,7 +433,7 @@ func TestGen(t *testing.T) { { name: "lua", path: "./testdata/lua", - dylibSymbols: []string{ + libSymbols: []string{ "lua_error", "lua_next", "lua_concat", @@ -443,7 +443,7 @@ func TestGen(t *testing.T) { { name: "cjson", path: "./testdata/cjson", - dylibSymbols: []string{ + libSymbols: []string{ "cJSON_Print", "cJSON_ParseWithLength", "cJSON_Delete", @@ -454,14 +454,14 @@ func TestGen(t *testing.T) { { name: "isl", path: "./testdata/isl", - dylibSymbols: []string{ + libSymbols: []string{ "isl_pw_qpolynomial_get_ctx", }, }, { name: "gpgerror", path: "./testdata/gpgerror", - dylibSymbols: []string{ + libSymbols: []string{ "gpg_strsource", "gpg_strerror_r", "gpg_strerror", @@ -500,11 +500,11 @@ func TestGen(t *testing.T) { } // trim to nm symbols - var dylibsymbs []*nm.Symbol - for _, symb := range tc.dylibSymbols { - dylibsymbs = append(dylibsymbs, &nm.Symbol{Name: addSymbolPrefixUnder(symb, cfg.Cplusplus)}) + var libSymbols []*nm.Symbol + for _, symb := range tc.libSymbols { + libSymbols = append(libSymbols, &nm.Symbol{Name: addSymbolPrefixUnder(symb, cfg.Cplusplus)}) } - symbols := symg.GetCommonSymbols(dylibsymbs, headerSymbolMap) + symbols := symg.GetCommonSymbols(libSymbols, headerSymbolMap) if err != nil { t.Fatal(err) } From 408930d2f223f22513900a2a70e45ef925514ed3 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 30 Jun 2025 17:50:37 +0800 Subject: [PATCH 16/16] llcppsymg:unit case for fetch static symbol --- _xtool/llcppsymg/internal/symg/symg_test.go | 130 +++++++++++++------- 1 file changed, 88 insertions(+), 42 deletions(-) diff --git a/_xtool/llcppsymg/internal/symg/symg_test.go b/_xtool/llcppsymg/internal/symg/symg_test.go index 9ff528a0..42771987 100644 --- a/_xtool/llcppsymg/internal/symg/symg_test.go +++ b/_xtool/llcppsymg/internal/symg/symg_test.go @@ -569,57 +569,103 @@ const char* test_function_3(void) { } defer os.Remove(cSourcePath) - var libPath string - var compileCmd []string - if runtime.GOOS == "darwin" { - libPath = filepath.Join(tempDir, "libtest.dylib") - compileCmd = []string{"clang", "-shared", "-fPIC", "-o", libPath, cSourcePath} - } else if runtime.GOOS == "linux" { - libPath = filepath.Join(tempDir, "libtest.so") - compileCmd = []string{"gcc", "-shared", "-fPIC", "-o", libPath, cSourcePath} - } else { - t.Skip("Unsupported platform for this test") + testCases := []struct { + name string + mode symbol.Mode + libExt string + }{ + { + name: "Dynamic Library", + mode: symbol.ModeDynamic, + libExt: getDynamicLibExt(), + }, + { + name: "Static Library", + mode: symbol.ModeStatic, + libExt: ".a", + }, } - cmd := exec.Command(compileCmd[0], compileCmd[1:]...) - output, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("Failed to compile test library: %v\nOutput: %s", err, output) - } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + libPath := filepath.Join(tempDir, "libtest"+tc.libExt) + var compileCmd []string + + if tc.mode == symbol.ModeDynamic { + if runtime.GOOS == "darwin" { + compileCmd = []string{"clang", "-shared", "-fPIC", "-o", libPath, cSourcePath} + } else if runtime.GOOS == "linux" { + compileCmd = []string{"gcc", "-shared", "-fPIC", "-o", libPath, cSourcePath} + } else { + t.Fatal("Unsupported platform for this test") + } + } else { // ModeStatic + objPath := filepath.Join(tempDir, "test.o") + if runtime.GOOS == "darwin" { + compileCmd = []string{"clang", "-c", "-o", objPath, cSourcePath} + } else if runtime.GOOS == "linux" { + compileCmd = []string{"gcc", "-c", "-o", objPath, cSourcePath} + } else { + t.Fatal("Unsupported platform for this test") + } - if _, err := os.Stat(libPath); os.IsNotExist(err) { - t.Fatal("Dynamic library was not created") - } + cmd := exec.Command(compileCmd[0], compileCmd[1:]...) + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Failed to compile object file: %v\nOutput: %s", err, output) + } - libDir := tempDir - libFlag := fmt.Sprintf("-L%s -ltest", libDir) + compileCmd = []string{"ar", "rcs", libPath, objPath} + } - symbols, err := symg.FetchSymbols(libFlag, symbol.ModeDynamic) - if err != nil { - t.Fatalf("FetchSymbols failed: %v", err) - } + cmd := exec.Command(compileCmd[0], compileCmd[1:]...) + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Failed to compile test library: %v\nOutput: %s", err, output) + } - if len(symbols) == 0 { - t.Fatal("No symbols found") - } + if _, err := os.Stat(libPath); os.IsNotExist(err) { + t.Fatalf("%s library was not created", tc.name) + } - expectedSymbols := []string{"test_function_1", "test_function_2", "test_function_3"} - foundSymbols := make(map[string]bool) + libDir := tempDir + libFlag := fmt.Sprintf("-L%s -ltest", libDir) - for _, sym := range symbols { - // On Darwin, symbols have '_' prefix, so trim it - symName := sym.Name - if runtime.GOOS == "darwin" { - symName = strings.TrimPrefix(symName, "_") - } - foundSymbols[symName] = true - } + symbols, err := symg.FetchSymbols(libFlag, tc.mode) + if err != nil { + t.Fatalf("FetchSymbols failed: %v", err) + } - for _, expected := range expectedSymbols { - if !foundSymbols[expected] { - t.Errorf("Expected symbol %s not found in library symbols", expected) - } + if len(symbols) == 0 { + t.Fatal("No symbols found") + } + + expectedSymbols := []string{"test_function_1", "test_function_2", "test_function_3"} + foundSymbols := make(map[string]bool) + + for _, sym := range symbols { + // On Darwin, symbols have '_' prefix, so trim it + symName := sym.Name + if runtime.GOOS == "darwin" { + symName = strings.TrimPrefix(symName, "_") + } + foundSymbols[symName] = true + } + + for _, expected := range expectedSymbols { + if !foundSymbols[expected] { + t.Errorf("Expected symbol %s not found in library symbols", expected) + } + } + + fmt.Printf("Successfully found %d symbols including expected test functions\n", len(symbols)) + }) } +} - t.Logf("Successfully found %d symbols including expected test functions", len(symbols)) +func getDynamicLibExt() string { + if runtime.GOOS == "darwin" { + return ".dylib" + } + return ".so" }