find_package for a static library instead of a shared library
Asked Answered
C

1

11

When building my project with CMake, I would like it to link to libraries statically (if available). Right now, it finds .dll.a files, regardless of the existence of .a files.

For example, take linking to libpng in a small sample project:

cmake_minimum_required(VERSION 3.15)
project(Test)

add_executable(Test main.cpp)

find_package(PNG REQUIRED)
message(${PNG_LIBRARIES})
target_link_libraries(Test PRIVATE ${PNG_LIBRARIES})

For the message, it outputs

C:/msys64/mingw64/lib/libpng.dll.aC:/msys64/mingw64/lib/libz.dll.a

But the libpng.a and libz.a files are also available in the same directory. How can I tell CMake to link with .a files?

I am using MinGW-w64 with msys64 on Windows 10, but would prefer a solution that is cross-platform.

Convexity answered 16/8, 2020 at 9:44 Comment(5)
It's quite incredible, and quite telling that nobody has answered this seemingly simple question. Especially considering how trivial it is to link against a static library if you have control over the linker call, or just the compiler frontend call.Aldous
Does this answer your question? How do I tell CMake to link in a static library in the source directory?Yeanling
@Yeanling unfortunately not. That only works if you're specifically linking with a static library of which you know the exact location beforehand. My question is the more general case, where CMake is the one looking up that location. For example: when this is part of an open-source project, the library archive might be in any location.Convexity
@AlexReinking - perhaps you might have an idea about this?Euell
It seems to me that the problem is in FindPNG: Looking at my cmake 3.26.3 installed modules: FindPNG.cmake searches with a find_library for any library with a NAME like png${v} libpng${v} libpng${v}_static. Apparently, it finds the dynamic one first and stops looking for the static one.Goodnatured
P
1

The sad reality is that static versus shared selection is done on a per package (or module) basis.

For packages that provide config files the most reliable approach is to simply not build the versions you don't want (e.g. don't build the static library if what you want is shared). Depressingly many projects insist on building both types. If they also have a documented way to select the library type, then you can just use that and you're in luck. Otherwise you will have to resort to hacks. A package manager like Conan or vcpkg will have those hacks built in.

For Find modules, again you must consult the documentation. In your case, you're using CMake's own FindPNG and FindZLIB (PNG dependency) modules. Prior to CMake 3.24 you were just out of luck, but since 3.24 you can hint to ZLIB that it should prefer static libraries like so:

option(ZLIB_USE_STATIC_LIBS "" ON)
find_package(PNG REQUIRED)

But what to do about PNG? Well, looking at the source code you're still out of luck. They have hard coded the search for static libraries to come after the search for shared. Maybe you can hack it with the PNG_NAMES variable that the module doesn't properly reset?

Otherwise you're setting PNG_LIBRARY{,_DEBUG,_RELEASE} from a toolchain file

Panther answered 27/12, 2023 at 18:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.