目錄

廣告 AD

zlib 壓縮庫:編譯安裝指南與步驟教學

到底要怎麼使用 C/C++ 壓縮或解壓縮檔案呢?

那就來看看 zlib 吧 ~

廣告 AD

在 Linux 中常常看到不同的壓縮格式,常見的像是 zip 和 gz,這些到底有甚麼差別?

大部分的 zip 和 gz 都是底層採用 deflate 演算法 (RFC1951) 壓縮,外面再加上不同的封裝

zip 可以將多的檔案放在一起壓縮,副檔名通常為 .zip

但 gz 只能針對單一檔案壓縮,因此 gz 通常都搭配 tar 一起使用,副檔名為 .tar.gz


Zlib 就是支援 deflate 演算法的 library,可以透過他來壓縮和解壓縮

其實 zlib 也是一個壓縮格式,底層也是基於 deflate,因此常常與 Zlib library 搞混

Zlib library 由 Jean-loup Gailly and Mark Adler 開發

本身除了支援 deflate 之外,也支援 zlib 格式和 gzip 格式

下面我們就來介紹如何編譯 Zlib library 吧 ~


在開始之前,我們會用到 git 和 cmake,沒有的可以先安裝一下。


  1. 下載 zlib libary 的 source code

    使用 git 來下載檔案

    cmd

    git clone https://github.com/madler/zlib

    cmd

    $ git clone https://github.com/madler/zlib
    Cloning into 'zlib'...
    remote: Enumerating objects: 6117, done.
    remote: Counting objects: 100% (330/330), done.
    remote: Compressing objects: 100% (140/140), done.
    remote: Total 6117 (delta 193), reused 266 (delta 187), pack-reused 5787
    Receiving objects: 100% (6117/6117), 4.24 MiB | 1002.00 KiB/s, done.
    Resolving deltas: 100% (4279/4279), done.

  1. cmake configure

    在編譯之前要先產生 Makefile,先進去 zlib 資料夾內,並下指令讓 cmake 產生必要的檔案

    我們設定將編譯過程產生的檔案放在 build,另外設定最後安裝的位置為 build/install

    這邊使用 MinGW 做示範,因此使用 MinGW Makefiles,如果不是用 MinGW 的可以使用其他的 Cmake Generator

    cmd

    cd zlib
    cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=build/install

    cmd

    $ cmake -S . -B build -G "MinGW Makefiles"
    -- The C compiler identification is GNU 13.1.0
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working C compiler: C:/MinGW/mingw64/bin/gcc.exe - skipped
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Looking for sys/types.h
    -- Looking for sys/types.h - found
    -- Looking for stdint.h
    -- Looking for stdint.h - found
    -- Looking for stddef.h
    -- Looking for stddef.h - found
    -- Check size of off64_t
    -- Check size of off64_t - done
    -- Looking for fseeko
    -- Looking for fseeko - found
    -- Looking for unistd.h
    -- Looking for unistd.h - found
    -- Renaming
    --     D:/zlib/zlib/zconf.h
    -- to 'zconf.h.included' because this file is included with zlib
    -- but CMake generates it automatically in the build directory.
    -- Configuring done (7.6s)
    -- Generating done (0.2s)
    -- Build files have been written to: D:/zlib/zlib/build

  1. cmake build

    接著就可以開始編譯了,我們設定將編譯產生的檔案放在 build

    cmd

    cmake --build build

    cmd

    $ cmake --build build
    [  2%] Generating zlib1rc.obj
    [  4%] Building C object CMakeFiles/zlib.dir/adler32.c.obj
    [  7%] Building C object CMakeFiles/zlib.dir/compress.c.obj
    [  9%] Building C object CMakeFiles/zlib.dir/crc32.c.obj
    [ 12%] Building C object CMakeFiles/zlib.dir/deflate.c.obj
    [ 14%] Building C object CMakeFiles/zlib.dir/gzclose.c.obj
    [ 17%] Building C object CMakeFiles/zlib.dir/gzlib.c.obj
    [ 19%] Building C object CMakeFiles/zlib.dir/gzread.c.obj
    [ 21%] Building C object CMakeFiles/zlib.dir/gzwrite.c.obj
    [ 24%] Building C object CMakeFiles/zlib.dir/inflate.c.obj
    [ 26%] Building C object CMakeFiles/zlib.dir/infback.c.obj
    [ 29%] Building C object CMakeFiles/zlib.dir/inftrees.c.obj
    [ 31%] Building C object CMakeFiles/zlib.dir/inffast.c.obj
    [ 34%] Building C object CMakeFiles/zlib.dir/trees.c.obj
    [ 36%] Building C object CMakeFiles/zlib.dir/uncompr.c.obj
    [ 39%] Building C object CMakeFiles/zlib.dir/zutil.c.obj
    [ 41%] Linking C shared library libzlib.dll
    [ 41%] Built target zlib
    [ 43%] Building C object CMakeFiles/zlibstatic.dir/adler32.c.obj
    [ 46%] Building C object CMakeFiles/zlibstatic.dir/compress.c.obj
    [ 48%] Building C object CMakeFiles/zlibstatic.dir/crc32.c.obj
    [ 51%] Building C object CMakeFiles/zlibstatic.dir/deflate.c.obj
    [ 53%] Building C object CMakeFiles/zlibstatic.dir/gzclose.c.obj
    [ 56%] Building C object CMakeFiles/zlibstatic.dir/gzlib.c.obj
    [ 58%] Building C object CMakeFiles/zlibstatic.dir/gzread.c.obj
    [ 60%] Building C object CMakeFiles/zlibstatic.dir/gzwrite.c.obj
    [ 63%] Building C object CMakeFiles/zlibstatic.dir/inflate.c.obj
    [ 65%] Building C object CMakeFiles/zlibstatic.dir/infback.c.obj
    [ 68%] Building C object CMakeFiles/zlibstatic.dir/inftrees.c.obj
    [ 70%] Building C object CMakeFiles/zlibstatic.dir/inffast.c.obj
    [ 73%] Building C object CMakeFiles/zlibstatic.dir/trees.c.obj
    [ 75%] Building C object CMakeFiles/zlibstatic.dir/uncompr.c.obj
    [ 78%] Building C object CMakeFiles/zlibstatic.dir/zutil.c.obj
    [ 80%] Linking C static library libzlibstatic.a
    [ 80%] Built target zlibstatic
    [ 82%] Building C object CMakeFiles/example.dir/test/example.c.obj
    [ 85%] Linking C executable example.exe
    [ 85%] Built target example
    [ 87%] Building C object CMakeFiles/minigzip.dir/test/minigzip.c.obj
    [ 90%] Linking C executable minigzip.exe
    [ 90%] Built target minigzip
    [ 92%] Building C object CMakeFiles/example64.dir/test/example.c.obj
    [ 95%] Linking C executable example64.exe
    [ 95%] Built target example64
    [ 97%] Building C object CMakeFiles/minigzip64.dir/test/minigzip.c.obj
    [100%] Linking C executable minigzip64.exe
    [100%] Built target minigzip64

  1. 安裝

    最後下指令安裝即可,安裝的位置在先前設定的 build/install

    cmd

    cmake --install build

    cmd

    $ cmake --install build
    -- Install configuration: ""
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/lib/libzlib.dll.a
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/bin/libzlib.dll
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/lib/libzlibstatic.a
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/include/zconf.h
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/include/zlib.h
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/share/man/man3/zlib.3
    -- Installing: D:/C/endgame_verify/3dparty/zlib/zlib/build/install/share/pkgconfig/zlib.pc

這邊稍微用 C++ 寫一下 gzip 格式的壓縮和解壓縮

Cpp

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

#include "zlib/zlib.h"

decompress(const std::string &inFileName, const std::string &outFileName)
{
  gzFile infile = gzopen(inFileName.data(), "rb");
  std::ofstream outfile(outFileName, std::ios::binary | std::ios::out);
  if (!infile || !outfile)
  {
    return -1;
  }

  char buf[128];
  int num_read = 0;
  while ((num_read = gzread(infile, buf, sizeof(buf))) > 0)
  {
    outfile.write(buf, num_read);
  }
  gzclose(infile);
  outfile.close();
  return 0;
}

int compress(const std::string &inFileName, const std::string &outFileName)
{
  std::ifstream infile(inFileName, std::ios::binary | std::ios::in);
  gzFile outfile = gzopen(outFileName.data(), "wb");
  if (!infile || !outfile)
  {
    return -1;
  }

  char buf[128];
  while (true)
  {
    infile.read(buf, sizeof(buf));
    int num_read = infile.gcount();
    if (num_read == 0)
    {
      break;
    }
    gzwrite(outfile, buf, num_read);
  }
  infile.close();
  gzclose(outfile);
  return 0;
}

int main(int argc, char **argv)
{
  if (argc < 3)
  {
    std::cerr << argv[0] << " <C/D> <source> <output>" << std::endl;
    exit(EXIT_FAILURE);
  }

  if (argv[1][0] == 'C')
  {
    if (compress(std::string(argv[2]), std::string(argv[3])) == -1)
    {
      std::cerr << "Error" << std::endl;
      exit(EXIT_FAILURE);
    }
  }
  else if (argv[1][0] == 'D')
  {
    if (decompress(std::string(argv[2]), std::string(argv[3])) == -1)
    {
      std::cerr << "Error" << std::endl;
      exit(EXIT_FAILURE);
    }
  }

  std::cout << "Done" << std::endl;
}

編譯時候記得設定 link 和 header 的路徑,然後 link zlib

因為是用 shared library,記得把 dll 複製過來

dll 位置在 build/install/bin/libzlib.dll

cmd

g++ test.cpp -o test.exe -l zlib -L zlib/build/install/lib -I zlib/build/install/include

附上用 static 的編譯指令:

cmd

g++ -static test.cpp -o test.exe -l zlibstatic -L zlib/build/install/lib -I zlib/build/install/include

廣告 AD