Search code examples
cmake

CMake ARCHIVE_CREATE with relative paths


I have a project where I use CMake's ARCHIVE_CREATE, it correctly generates the '.zip' file, here is the code:

file(ARCHIVE_CREATE
  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/bundle.zip"
  PATHS "${CMAKE_CURRENT_SOURCE_DIR}/assets/demo"
  FORMAT "zip"
  VERBOSE
)

Where ${CMAKE_CURRENT_SOURCE_DIR}/assets/demo dir has:

$ tree
.
├── blob
│   └── matrix.avif
└── scripts
    └── main.lua

However, the final directory structure is different, as shown in the image below:

My question is: how can I make sure the compressed file structure is exactly the same as the directory?


Solution

  • I give up and ended with a small go program:

    package main
    
    import (
        "archive/zip"
        "io"
        "os"
        "path/filepath"
    )
    
    func main() {
        baseDir := os.Args[1]
        file, err := os.Create("bundle.zip")
        if err != nil {
            panic(err)
        }
        defer file.Close()
    
        w := zip.NewWriter(file)
        defer w.Close()
    
        walker := func(baseDir, path string, info os.FileInfo, err error) error {
            if err != nil {
                return err
            }
            if info.IsDir() {
                return nil
            }
    
            relPath, err := filepath.Rel(baseDir, path)
            if err != nil {
                return err
            }
    
            file, err := os.Open(path)
            if err != nil {
                return err
            }
            defer file.Close()
    
            f, err := w.Create(relPath)
            if err != nil {
                return err
            }
    
            _, err = io.Copy(f, file)
            if err != nil {
                return err
            }
    
            return nil
        }
    
        err = filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
            return walker(baseDir, path, info, err)
        })
    
        if err != nil {
            panic(err)
        }
    }
    

    On CMake I run:

    execute_process(COMMAND go run ${CMAKE_SOURCE_DIR}/assets/pack.go ${CMAKE_SOURCE_DIR}/assets/demo)