Repository: conan-io/conan-center-index

Issue:
[package] zlib/1.2.12; Packaging fails when running discrete Conan commands
### Description

An issue with the way the zlib CMakeLists.txt file is structured prevents correct operation when running discrete Conan operations because it prevents the cmake --install "--prefx" command that Conan leverages from operating as intended. More specifically, the issue relates to the declarations of the form:

> set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")

The CMAKE_INSTALL_PREFIX variables get replaced with absolute paths when Conan runs cmake.configure, which has the side effect of preventing the --prefix from having its expected effect (see https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html#module:GNUInstallDirs for insights on relative vs. absolute paths).

This issue can be resolved by simply removing the "${CMAKE_INSTALL_PREFIX}/" resulting in:

> set(INSTALL_LIB_DIR "lib" CACHE PATH "Installation directory for libraries")


### Package and Environment Details

* Package Name/Version: **zlib/1.2.12**
* Operating System+version: **Debian 10.3**
* Compiler+version: **GCC 8**
* Conan version: **conan 1.53 and 2.0.0-beta4**
* Python version: **Python 3.7.3**


### Conan profile

[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=8
compiler.libcxx=libstdc++11
build_type=Release
[options]
[build_requires]
[tool_requires]
[env]

### Steps to reproduce

In a directory with the zlib CCI conanfile.py recipe and related patches:
For Conan 1.x:

> conan install . zlib/1.2.12@
> conan source .
> conan build .
> conan export-pkg . zlib/1.2.12@ -f

For Conan 2.0

> conan-2.0 source . --name zlib --version 1.2.12
> conan-2.0 build . --name zlib --version 1.2.12
> conan-2.0 export-pkg . --name zlib --version 1.2.12


### Logs

Note: The failure mode is slightly different between Conan v1.x and Conan v2.0 although both ignore the --prefix option passed to cmake --install. In v1.x, we get a hard error, because CMake tries to install the files in /usr/local where permission is lacking. In Conan v2.0, CMake silently installs the files in the wrong location

<details><summary>Click to v1.x expand log</summary>

```
conan -v
Conan version 1.53.0
conan install . zlib/1.2.12@
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.libcxx=libstdc++11
compiler.version=8
os=Linux
os_build=Linux
[options]
[build_requires]
[env]

conanfile.py (zlib/1.2.12): Installing package
Requirements
Packages

Installing (downloading, building) binaries...
conanfile.py (zlib/1.2.12): Generator txt created conanbuildinfo.txt
conanfile.py (zlib/1.2.12): Calling generate()
conanfile.py (zlib/1.2.12): WARN: Using the new toolchains and generators without specifying a build profile (e.g: -pr:b=default) is discouraged and might cause failures and unexpected behavior
conanfile.py (zlib/1.2.12): Preset 'release' added to CMakePresets.json. Invoke it manually using 'cmake --preset release'
conanfile.py (zlib/1.2.12): If your CMake version is not compatible with CMakePresets (<3.19) call cmake like: 'cmake <path> -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=/local/test/zlib/all/build/generators/conan_toolchain.cmake -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release'
conanfile.py (zlib/1.2.12): Aggregating env generators
conanfile.py (zlib/1.2.12): Generated conaninfo.txt
conanfile.py (zlib/1.2.12): Generated graphinfo
conan source .
Using lockfile: '/local/test/zlib/all/conan.lock'
Using cached profile from lockfile
WARN: Hook 'conan-center.py' not found in /home/marc/.conan/hooks folder. Please remove hook from conan.conf or include it inside the hooks folder.
conanfile.py (zlib/1.2.12): Configuring sources in /local/test/zlib/all/src
conanfile.py (zlib/1.2.12): Executing exports to: /local/test/zlib/all/src
Downloading zlib-1.2.12.tar.gz:  89%|########9 | 1.27M/1.42M [00:00<00:00, 2.18MB/s]conanfile.py (zlib/1.2.12): conanfilDownloading zlib-1.2.12.tar.gz completed [1455.15k]                                      conanfile.py (zlib/1.2.12):
conanfile.py (zlib/1.2.12):
conan build .
Using lockfile: '/local/test/zlib/all/conan.lock'
Using cached profile from lockfile
WARN: Hook 'conan-center.py' not found in /home/marc/.conan/hooks folder. Please remove hook from conan.conf or include it inside the hooks folder.
conanfile.py (zlib/1.2.12): Calling build()
conanfile.py (zlib/1.2.12): Apply patch (vulnerability): CVE-2022-37434: Fix a bug when getting a gzip header extra field with inflate()
conanfile.py (zlib/1.2.12): Apply patch (vulnerability): CVE-2022-37434: Fix extra field processing bug that dereferences NULL state->head
conanfile.py (zlib/1.2.12): CMake command: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="/local/test/zlib/all/build/generators/conan_toolchain.cmake" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="Release" "/local/test/zlib/all/src"
-- Using Conan toolchain: /local/test/zlib/all/build/generators/conan_toolchain.cmake
-- Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE=ON (options.fPIC)
-- Conan toolchain: Setting BUILD_SHARED_LIBS = OFF
-- The C compiler identification is GNU 8.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - 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
--     /local/test/zlib/all/src/zconf.h
-- to 'zconf.h.included' because this file is included with zlib
-- but CMake generates it automatically in the build directory.
-- Configuring done
-- Generating done
-- Build files have been written to: /local/test/zlib/all/build/Release
conanfile.py (zlib/1.2.12): CMake command: cmake --build "/local/test/zlib/all/build/Release" '--' '-j8'
Scanning dependencies of target zlib
[  6%] Building C object CMakeFiles/zlib.dir/adler32.c.o
[ 18%] Building C object CMakeFiles/zlib.dir/gzclose.c.o
[ 25%] Building C object CMakeFiles/zlib.dir/crc32.c.o
[ 25%] Building C object CMakeFiles/zlib.dir/deflate.c.o
[ 37%] Building C object CMakeFiles/zlib.dir/gzread.c.o
[ 37%] Building C object CMakeFiles/zlib.dir/compress.c.o
[ 43%] Building C object CMakeFiles/zlib.dir/gzlib.c.o
[ 50%] Building C object CMakeFiles/zlib.dir/gzwrite.c.o
[ 56%] Building C object CMakeFiles/zlib.dir/inflate.c.o
[ 62%] Building C object CMakeFiles/zlib.dir/infback.c.o
[ 68%] Building C object CMakeFiles/zlib.dir/inftrees.c.o
[ 75%] Building C object CMakeFiles/zlib.dir/inffast.c.o
[ 81%] Building C object CMakeFiles/zlib.dir/trees.c.o
[ 87%] Building C object CMakeFiles/zlib.dir/uncompr.c.o
[ 93%] Building C object CMakeFiles/zlib.dir/zutil.c.o
[100%] Linking C static library libz.a
[100%] Built target zlib
conan export-pkg . zlib/1.2.12@ -f
Exporting package recipe
zlib/1.2.12 exports: File 'conandata.yml' found. Exporting it...
zlib/1.2.12 exports: Copied 1 '.yml' file: conandata.yml
zlib/1.2.12: Calling export_sources()
zlib/1.2.12: The stored package has not changed
zlib/1.2.12: Exported revision: bb959a1d68d4c35d0fba4cc66f5bb25f
zlib/1.2.12: Forced build from source
Packaging to 1d877a3df840030e6a8abb74c5ffb9088d08b47a
zlib/1.2.12: Generating the package
zlib/1.2.12: Package folder /home/marc/.conan/data/zlib/1.2.12/_/_/package/1d877a3df840030e6a8abb74c5ffb9088d08b47a
zlib/1.2.12: Calling package()
zlib/1.2.12: CMake command: cmake --install "/local/test/zlib/all/build/Release" --prefix "/home/marc/.conan/data/zlib/1.2.12/_/_/package/1d877a3df840030e6a8abb74c5ffb9088d08b47a"
-- Install configuration: "Release"
-- Installing: /usr/local/lib/libz.a
CMake Error at cmake_install.cmake:54 (file):
  file INSTALL cannot copy file "/local/test/zlib/all/build/Release/libz.a"
  to "/usr/local/lib/libz.a": Permission denied.


ERROR: zlib/1.2.12: Error in package() method, line 100
        cmake.install()
        ConanException: Error 1 while executing cmake --install "/local/test/zlib/all/build/Release" --prefix "/home/marc/.conan/data/zlib/1.2.12/_/_/package/1d877a3df840030e6a8abb74c5ffb9088d08b47a"

```

</details>
<details><summary>Click to v2.0 expand log</summary>

```
conan-2.0 -v
]Conan version 2.0.0-beta4
conan-2.0 source . --name zlib --version 1.2.12
conanfile.py (zlib/1.2.12): Calling source() in /local/test/zlib/all/src
Downloading zlib-1.2.12.tar.gz

conan-2.0 build . --name zlib --version 1.2.12

-------- Input profiles --------
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=8
os=Linux

Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=8
os=Linux


-------- Computing dependency graph --------
Graph root
    conanfile.py (zlib/1.2.12): /local/test/zlib/all/conanfile.py

-------- Computing necessary packages --------

-------- Installing packages --------

-------- Installing (downloading, building) binaries... --------

-------- Finalizing install (deploy, generators) --------
conanfile.py (zlib/1.2.12): Calling generate()
conanfile.py (zlib/1.2.12): Preset 'release' added to CMakePresets.json. Invoke it manually using 'cmake --preset release'
conanfile.py (zlib/1.2.12): If your CMake version is not compatible with CMakePresets (<3.19) call cmake like: 'cmake <path> -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=/local/test/zlib/all/build/generators/conan_toolchain.cmake -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release'
conanfile.py (zlib/1.2.12): Aggregating env generators
conanfile.py (zlib/1.2.12): Calling build()
conanfile.py (zlib/1.2.12): Apply patch (vulnerability): CVE-2022-37434: Fix a bug when getting a gzip header extra field with inflate()
conanfile.py (zlib/1.2.12): Apply patch (vulnerability): CVE-2022-37434: Fix extra field processing bug that dereferences NULL state->head
conanfile.py (zlib/1.2.12): CMake command: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="/local/test/zlib/all/build/generators/conan_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="/local/test/zlib/all" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="Release" "/local/test/zlib/all/src"
conanfile.py (zlib/1.2.12): RUN: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="/local/test/zlib/all/build/generators/conan_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="/local/test/zlib/all" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="Release" "/local/test/zlib/all/src"
-- Using Conan toolchain: /local/test/zlib/all/build/generators/conan_toolchain.cmake
-- Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE=ON (options.fPIC)
-- Conan toolchain: Setting BUILD_SHARED_LIBS = OFF
-- The C compiler identification is GNU 8.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - 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
--     /local/test/zlib/all/src/zconf.h
-- to 'zconf.h.included' because this file is included with zlib
-- but CMake generates it automatically in the build directory.
-- Configuring done
-- Generating done
-- Build files have been written to: /local/test/zlib/all/build/Release
conanfile.py (zlib/1.2.12): CMake command: cmake --build "/local/test/zlib/all/build/Release" -- -j8
conanfile.py (zlib/1.2.12): RUN: cmake --build "/local/test/zlib/all/build/Release" -- -j8
Scanning dependencies of target zlib
[  6%] Building C object CMakeFiles/zlib.dir/adler32.c.o
[ 18%] Building C object CMakeFiles/zlib.dir/crc32.c.o
[ 18%] Building C object CMakeFiles/zlib.dir/compress.c.o
[ 25%] Building C object CMakeFiles/zlib.dir/deflate.c.o
[ 31%] Building C object CMakeFiles/zlib.dir/gzlib.c.o
[ 37%] Building C object CMakeFiles/zlib.dir/gzread.c.o
[ 43%] Building C object CMakeFiles/zlib.dir/gzclose.c.o
[ 50%] Building C object CMakeFiles/zlib.dir/gzwrite.c.o
[ 56%] Building C object CMakeFiles/zlib.dir/inflate.c.o
[ 62%] Building C object CMakeFiles/zlib.dir/infback.c.o
[ 68%] Building C object CMakeFiles/zlib.dir/inftrees.c.o
[ 75%] Building C object CMakeFiles/zlib.dir/inffast.c.o
[ 81%] Building C object CMakeFiles/zlib.dir/trees.c.o
[ 87%] Building C object CMakeFiles/zlib.dir/uncompr.c.o
[ 93%] Building C object CMakeFiles/zlib.dir/zutil.c.o
[100%] Linking C static library libz.a
[100%] Built target zlib
conan-2.0 export-pkg . --name zlib --version 1.2.12
zlib/1.2.12: Exporting package recipe
zlib/1.2.12 exports: File 'conandata.yml' found. Exporting it...
zlib/1.2.12: Copied 1 '.yml' file: conandata.yml
zlib/1.2.12 exports: Copied 1 '.yml' file: conandata.yml
zlib/1.2.12: Calling export_sources()
zlib/1.2.12: Using the exported files summary hash as the recipe revision: bb959a1d68d4c35d0fba4cc66f5bb25f
zlib/1.2.12: A new conanfile.py version was exported
zlib/1.2.12: Folder: /home/marc/.conan2/p/3c9d9cc767e8fef5/e
zlib/1.2.12: Exported revision: bb959a1d68d4c35d0fba4cc66f5bb25f
Packaging to 897e6fde718e72637d92b0b8ed929893a1976238
zlib/1.2.12: Generating the package
zlib/1.2.12: Temporary package folder /home/marc/.conan2/p/tmp/200a40ef421078e1/p
zlib/1.2.12: Calling package()
zlib/1.2.12: CMake command: cmake --install "/local/test/zlib/all/build/Release" --prefix "/home/marc/.conan2/p/tmp/200a40ef421078e1/p"
zlib/1.2.12: RUN: cmake --install "/local/test/zlib/all/build/Release" --prefix "/home/marc/.conan2/p/tmp/200a40ef421078e1/p"
-- Install configuration: "Release"
-- Installing: /local/test/zlib/all/lib/libz.a
-- Installing: /local/test/zlib/all/include/zconf.h
-- Installing: /local/test/zlib/all/include/zlib.h
zlib/1.2.12 package(): Packaged 1 file: LICENSE
zlib/1.2.12: Package '897e6fde718e72637d92b0b8ed929893a1976238' created
zlib/1.2.12: Created package revision 6d2d29fc8fb4e57e3f8d5ba009faf9c9
zlib/1.2.12: Full package reference: zlib/1.2.12#bb959a1d68d4c35d0fba4cc66f5bb25f:897e6fde718e72637d92b0b8ed929893a1976238#6d2d29fc8fb4e57e3f8d5ba009faf9c9
```

</details>


Discussion:
I have a simple change to the conanfile.py recipe that overcomes this issue. I will submit it shortly.

Resolving patch:
diff --git a/recipes/zlib/all/conanfile.py b/recipes/zlib/all/conanfile.py
--- a/recipes/zlib/all/conanfile.py
+++ b/recipes/zlib/all/conanfile.py
@@ -4,11 +4,12 @@
 from conan.tools.scm import Version
 import os
 
-required_conan_version = ">=1.52.0"
+required_conan_version = ">=1.53.0"
 
 
 class ZlibConan(ConanFile):
     name = "zlib"
+    package_type = "library"
     url = "https://github.com/conan-io/conan-center-index"
     homepage = "https://zlib.net"
     license = "Zlib"
@@ -39,18 +40,9 @@ def config_options(self):
 
     def configure(self):
         if self.options.shared:
-            try:
-                del self.options.fPIC
-            except Exception:
-                pass
-        try:
-            del self.settings.compiler.libcxx
-        except Exception:
-            pass
-        try:
-            del self.settings.compiler.cppstd
-        except Exception:
-            pass
+            self.options.rm_safe("fPIC")
+        self.settings.rm_safe("compiler.libcxx")
+        self.settings.rm_safe("compiler.cppstd")
 
     def layout(self):
         cmake_layout(self, src_folder="src")
@@ -65,6 +57,9 @@ def generate(self):
         tc.variables["SKIP_INSTALL_LIBRARIES"] = False
         tc.variables["SKIP_INSTALL_HEADERS"] = False
         tc.variables["SKIP_INSTALL_FILES"] = True
+        # Correct for misuse of "${CMAKE_INSTALL_PREFIX}/" in CMakeLists.txt
+        tc.variables["INSTALL_LIB_DIR"] = "lib"
+        tc.variables["INSTALL_INC_DIR"] = "include"
         tc.generate()
 
     def _patch_sources(self):


Test patch: