Skip to content

[Windows] zlib 1.3.2 introduced a breaking change that broke the build of lua-zlib through LuaRocks #80

@luau-project

Description

@luau-project

Description

Important

The discussion below only applies to Windows.

Warning

This is a long issue description.

Recently, zlib 1.3.2 was released.

On the one hand, among enhancements and bug fixes, zlib 1.3.2 had a completely rewrite on their CMake support.

Note

CMake is one of the main build systems used by Windows developers to build C/C++ software from source nowadays.

On the other hand, due these changes targeting CMake support, zlib's developers introduced a breaking change:

  • the DLL name changed (used to be zlib1.dll on MSVC or libzlib1.dll on MinGW/MinGW-w64, now it is z.dll on MSVC or libz.dll on MinGW/MinGW-w64);
  • the name of the import library also changed (used to zlib.lib on MSVC or libzlib.dll.a on MinGW/MinGW-w64, now it is z.lib on MSVC or libz.dll.a on MinGW/MinGW-w64);

Due these breaking changes explained above, whenever the user built zlib 1.3.2 from source with CMake, the build of lua-zlib through LuaRocks is going to fail.

Reproduction

I wrote a GitHub workflow to reproduce this issue comparing versions 1.3.1 and 1.3.2: log in to GitHub and inspect the runs https://github.com/luau-project/ci-tests/actions/runs/22404458107

Click here to toggle the workflow
name: lua-zlib test

on: push

jobs:
  zlib-comparison:
    runs-on: windows-latest

    defaults:
      run:
        shell: cmd

    strategy:
      fail-fast: false

      matrix:
        lua-version:
          - 5.5
          - luajit

        zlib-version:
          - 1.3.1
          - 1.3.2

        toolchain:
          - msvc
          - gcc

    env:

      # usual directory that LuaRocks
      # expects external dependencies
      # to be
      LUAROCKS_DEPS_DIR: C:\external

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          repository: brimworks/lua-zlib
          ref: v1.4

      - name: Restore zlib tarball from cache
        id: restore-zlib
        uses: actions/cache/restore@v5
        with:
          path: zlib-${{ matrix.zlib-version }}.tar.gz
          key: zlib-${{ matrix.zlib-version }}

      - name: Download zlib
        if: ${{ steps.restore-zlib.outputs.cache-hit != 'true' }}
        run: curl -L -O "https://zlib.net/fossils/zlib-${{ matrix.zlib-version }}.tar.gz"

      - name: Save zlib tarball on cache
        if: ${{ steps.restore-zlib.outputs.cache-hit != 'true' }}
        uses: actions/cache/save@v5
        with:
          path: zlib-${{ matrix.zlib-version }}.tar.gz
          key: zlib-${{ matrix.zlib-version }}

      - name: Extract zlib
        run: tar -xf "zlib-${{ matrix.zlib-version }}.tar.gz"

      - name: Setup MSVC developer prompt
        uses: ilammy/msvc-dev-cmd@v1
        if: ${{ matrix.toolchain == 'msvc' }}

      - name: Configure zlib through CMake
        run: |
          IF "${{ matrix.toolchain }}" EQU "msvc" (
            SET "CMAKE_GENERATOR=NMake Makefiles"
          ) ELSE (
            SET "CMAKE_GENERATOR=MinGW Makefiles"
          )

          IF "${{ matrix.zlib-version }}" EQU "1.3.2" (
            cmake -G "%CMAKE_GENERATOR%" ^
              -DCMAKE_BUILD_TYPE=Release ^
              -DZLIB_BUILD_SHARED=ON ^
              --install-prefix "${{ env.LUAROCKS_DEPS_DIR }}" ^
              -S "zlib-${{ matrix.zlib-version }}" ^
              -B "build-zlib"
          ) ELSE (
            cmake -G "%CMAKE_GENERATOR%" ^
              -DCMAKE_BUILD_TYPE=Release ^
              -DBUILD_SHARED_LIBS=ON ^
              --install-prefix "${{ env.LUAROCKS_DEPS_DIR }}" ^
              -S "zlib-${{ matrix.zlib-version }}" ^
              -B "build-zlib"
          )

      - name: Build zlib
        run: cmake --build "build-zlib" --config Release

      - name: Install zlib
        run: cmake --install "build-zlib" --config Release

      - name: Add the bin dir of LuaRocks external dependencies on PATH
        run: echo ${{ env.LUAROCKS_DEPS_DIR }}\bin>>${{ github.path }}

      - name: Show zlib installation directory
        run: tree /F "${{ env.LUAROCKS_DEPS_DIR }}"

      - name: Setup Lua and LuaRocks
        uses: luau-project/setup-lua@v1
        with:
          lua-version: ${{ matrix.lua-version }}

      - name: Show Lua version
        run: lua -v

      - name: Show LuaRocks version
        run: luarocks --version

      - name: Build and install lua-zlib
        run: luarocks make "lua-zlib-scm-0.rockspec"

Temporary and quick solutions to fix this build issue

  • The easiest solution, which is far from the best scenario, is to ask users to stick to zlib version 1.3.1 or older
  • The second solution, which is relatively easy to apply, is:
    • For MSVC users willing to use zlib 1.3.2, ask them to copy the new import library (z.lib) to the legacy import library (zlib.lib);
    • For MinGW/MinGW-w64 users with zlib 1.3.2, ask them to copy the new dll (libz.dll) to the legacy dll (libzlib1.dll);

The proper solution

The solution to handle both the legacy (1.3.1 and older) and current zlib versions through LuaRocks involve a comparison of versions to decide dynamically the correct import library to use.

There are ways to do that:

  • with Makefiles (one for nmake - the MSVC make, and another for mingw32-make - the MinGW/MinGW-w64 make). This tends to be quite portable, because nmake is always installed with MSVC, and the user often has mingw32-make in a MinGW/MinGW-w64 installation;
  • with CMake itself (would require CMake to be installed). Only C/C++ developers usually have this tool installed, so it is not too portable;
  • with a custom build command (this is a sophisticated approach). Other libraries did it in the past (luaposix, see https://luarocks.org/manifests/gvvaughan/luaposix-36.3-1.rockspec) through the tool https://github.com/gvvaughan/luke.

PS

In my view, ranking in portability order, the preferred methods to solve this issue would be: 1 - build command; 2 - Makefiles; 3 - CMake.

However, in a realistic scenario, Makefiles would provide the best balance between difficulty and time to market to solve this.

Note

Slowly, I'll investigate the build command and Makefiles solutions to this issue. However, I cannot guarantee anything.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions