Use the FindZLIB CMake function with find_package to find zlib.
This is a builtin module provided by CMake which allows overriding
the zlib location through standard mechanisms.
Details
- Reviewers
beanz delcypher vitalybuka
Diff Detail
- Repository
- rL LLVM
Event Timeline
The idea behind this change is fine. The main problem in the implementation is not considering the scenario where LLVM_ENABLE_ZLIB is initially TRUE but is then changed at a later date. The current implementation would ignore the value of LLVM_ENABLE_ZLIB because the HAVE_LIBZ cache variable is still present from a previous configure run.
llvm/cmake/config-ix.cmake | ||
---|---|---|
112 | If LLVM_ENABLE_ZLIB but ZLIB_FOUND is FALSE we should emit an error telling the user that Zlib couldn't be found and that should either tell CMake how to find it or set LLVM_ENABLE_ZLIB to FALSE. You also use the REQUIRED argument to find_package() as an alternative. | |
113 | We need to handle the case that Zlib was found previously but LLVM_ENABLE_ZLIB is now FALSE. You can either do it here so that HAVE_LIBZ is set to FALSE or you can update all uses of HAVE_LIBZ to also check if LLVM_ENABLE_ZLIB is set to TRUE. | |
llvm/lib/Support/CMakeLists.txt | ||
2 | You shouldn't drop LLVM_ENABLE_ZLIB in the condition here, at least in the current implementation anyway. AFAIK both LLVM_ENABLE_ZLIB and HAVE_LIBZ are cache variables. What could happen is that the user configures with LLVM_ENABLE_ZLIB and ZLIB is found and used. | |
llvm/lib/Support/Compression.cpp | ||
21 | Shouldn't this be HAVE_LIBZ? | |
27 | Shouldn't this be HAVE_LIBZ? |
llvm/cmake/config-ix.cmake | ||
---|---|---|
113 | Oh wait. HAVE_LIBZ is a regular variable and not a cache variable. Sorry I was confusing it with ZLIB_FOUND. In that case I think your implementation should work fine in the scenario I mentioned. |
llvm/lib/Support/CMakeLists.txt | ||
---|---|---|
2 | Again. I think I confused HAVE_LIBZ with ZLIB_FOUND so your implementation is probably fine in the scenario I mentioned. |
llvm/cmake/config-ix.cmake | ||
---|---|---|
112 | I'm fine doing that, but it'd would be a different behavior from the current one where we silently ignore the missing library? |
llvm/cmake/config-ix.cmake | ||
---|---|---|
112 | Yes that is different behaviour. I'm pretty convinced that the current behaviour is wrong. In KLEE we use a slightly different pattern. We initialize the default option for enabling ZLIB depending on whether or not the library is available. See https://github.com/klee/klee/blob/843e9be8fc10c6ffb30218c5a826aab192a31955/CMakeLists.txt#L344 The advantage of this approach is that if the system has the library we use it by default, but if the user explicitly sets the option to use zlib and its not available then we emit an error. Given that it appears the existing behaviour of LLVM right now is to silently ignore missing libraries, you don't have to fix this right now if you don't want to. This could be addressed in a separate patch. Although I'd personally like a warning at the very least instead of LLVM's build system silently ignoring the request to use zlib. |
llvm/cmake/config-ix.cmake | ||
---|---|---|
112 | I agree that the approach you're following in KLEE is better, but in that case we'll probably have to change all the code to check LLVM_ENABLE_ZLIB rather than HAVE_LIBZ because even if HAVE_LIBZ is set to TRUE and we use it to se the default value of LLVM_ENABLE_ZLIB, user may still override that and set LLVM_ENABLE_ZLIB to FALSE. Does that sound fine to you? |
llvm/lib/Support/CMakeLists.txt | ||
---|---|---|
3 | What would be the new value of ZLIB_LIBRARIES here? One of my previous attempts to refactor this failed because we have code which assumes system_libs is a list bare library names z dl ... that can then be prefixed with -l and passed to the linker. This fails horribly if you specify a full path to a library (which cmake likes to to). |
llvm/cmake/config-ix.cmake | ||
---|---|---|
112 | Sounds good to me. You may have to refactor the code a bit more because it looks like the declaration for LLVM_ENABLE_ZLIB is nowhere near where it's used. In fact it's not even in the same file. | |
llvm/lib/Support/CMakeLists.txt | ||
3 | Sounds like we should have a better test case then. It looks like test/tools/llvm-config/system-libs.test is too weak to check what you asking for. |
llvm/lib/Support/CMakeLists.txt | ||
---|---|---|
3 | Yes, a better test case would be useful certainly (but don't worry you will get test failures, they will just be in compiler-rt, or other projects which use llvm-config to invoke the linker :)). Anyway, I am not asking for anything. I don't have a horse in this game; as long as the main cmake project builds I am happy. I'm just giving you a heads up that you are likely to run into issues down this road. |
llvm/lib/Support/CMakeLists.txt | ||
---|---|---|
3 | Isn't this actually more correct? In our case, I'd like to use our own version of zlib and libxml2 rather than the system ones using the CMAKE_FIND_ROOT_PATH option. If llvm-config --system-libs prints -lz -lxml2, it's ambiguous which zlib and libxml2 it's referring to. Furthermore, in our case we want to link zlib and libxml2 statically, so presumably llvm-config --system-libs shouldn't print -lz -lxml2 at all but that's not currently the case. |
llvm/lib/Support/CMakeLists.txt | ||
---|---|---|
3 |
You could argue it's more correct if you also fixed --system-libs to output the library as /usr/lib/libz.so or something else that the linker can consume. As it stands now it will print -l/usr/lib/libz.so which will just blow up. I don't know much about the scenarios in which llvm-config is used (I just know that when I tried something like this I found a dozen angry emails waiting for me the next day), but this change might actually be enough to appease people relying on it.
The intended audience of llvm-config is people who want to link against llvm. For that the modality (shared/static) of libz doesn't matter. What matters is the modality of llvm. If you built llvm as a bunch of static libraries, when using them, you will need to pass libz to the linker (static or otherwise). If you built llvm as a single shared library, then you don't need to pass anything as shared libraries can track their dependencies (and I believe in this case the output of --system-libs will already be empty). |
If LLVM_ENABLE_ZLIB but ZLIB_FOUND is FALSE we should emit an error telling the user that Zlib couldn't be found and that should either tell CMake how to find it or set LLVM_ENABLE_ZLIB to FALSE. You also use the REQUIRED argument to find_package() as an alternative.