I'm having a rather strange issue while building a C++ project on OSX using CMake, while pulling in libpng as a dependency. I have libpng 1.6.21 installed via homebrew and the following CMake rules:
FIND_PACKAGE(PNG REQUIRED)
INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIRS})
LINK_DIRECTORIES(${PNG_LIBRARY_DIRS})
ADD_DEFINITIONS(${PNG_DEFINITIONS})
When CMake starts to build and finds the dependencies, it outputs:
-- Found PNG: /usr/local/lib/libpng.dylib (found version "1.4.12")
Investigating further, /usr/local/lib/libpng.dylib is a symlink to brew's 1.6 version:
$ ls -l /usr/local/lib/libpng.dylib
lrwxr-xr-x 1 fluffy admin 40 Apr 9 16:06 /usr/local/lib/libpng.dylib -> ../Cellar/libpng/1.6.21/lib/libpng.dylib
However, it appears that it is the incorrect png.h that is being included, as printing out PNG_LIBPNG_VER_STRING at startup outputs 1.4.12. And, of course, when I try running my program, I get a version mismatch and the library fails to work:
libpng warning: Application built with libpng-1.4.12 but running with 1.6.21
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: [write_png_file] png_create_write_struct failed
Using FIND_PACKAGE(PNG), the -I declarations never appear in my build line when I build with VERBOSE=1. However, if I use the PkgConfig approach:
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(LIBPNG libpng16 REQUIRED)
INCLUDE_DIRECTORIES(${LIBPNG_INCLUDE_DIRS})
LINK_DIRECTORIES(${LIBPNG_LIBRARY_DIRS})
LINK_LIBRARIES(${LIBPNG_LIBRARIES})
ADD_DEFINITIONS(${LIBPNG_DEFINITIONS})
the correct -I flag does appear, and yet it's still using the system png.h instead of Homebrew's.
Is there any way to force the compiler to use homebrew's png.h? I can't simply uninstall the homebrew libpng since some of my other packages depend on it, including other libraries that this program makes use of.
EDIT: As a temporary workaround I've just added /usr/local/include to my INCLUDE_DIRS() and included libpng16/png.h instead, but this is a fragile hack.
Have stumbled on this infuriating bug today and spent some time to get to the end of it.
The problem is that classical cmake-style Find*.cmake search for the headers and libraries separately - and the results MAY and WILL mismatch in some cases.
MacOS exaggerates the problem by having special case of frameworks, being searched BEFORE other locations by default.
In my case cmake finds headers from /Library/Frameworks/Mono.framework, which of course are outdated and doesn't have the libraries at all.
You have the options of:
set(CMAKE_FIND_FRAMEWORK LAST)
This fixes the issue with the rogue frameworks like this(in my case)
This is the fast dirty fix.
Use PackageConfig as you originally did - This is the recommended long-term solution.
Using PackageConfig prevents lib/headers/flags mismatch.
The only thing you should do is ensure the include path is passed to the compiler right before the system ones.
remove the offending framework/path/library (e.g. zlib sometimes packages libpng too!)
include a copy of libpng in your repo and use it
Requirements
the header version matches the version used to build the libpng library
also it is mentioned in bounty description, that solution shouldn't involve PkgConfig
Since PkgConfig is usually the preferred solution, two solutions are presented - one with and one without using PkgConfig.
The first requirement can be represented in some C code like this:
#include <stdio.h>
#include <png.h>
int main(void) {
printf("libpng version of lib (%u):%s",
png_access_version_number(),
png_get_header_version(NULL));
printf("used libpng version in app (%d):%s",
PNG_LIBPNG_VER,
PNG_HEADER_VERSION_STRING);
return 0;
}
Build
To get some debug output, you could use a small script that creates the application:
#!/bin/zsh
rm -rf build
cmake -B build
cmake --build build -v
build/png_app
Solution with PkgConfig
cmake_minimum_required(VERSION 3.17)
project(png_app C)
set(CMAKE_C_STANDARD 99)
find_package(PkgConfig REQUIRED)
pkg_check_modules(PNG libpng16 REQUIRED)
add_executable(png_app main.c)
target_include_directories(png_app PRIVATE ${PNG_INCLUDE_DIRS})
target_link_directories(png_app PRIVATE ${PNG_LIBRARY_DIRS})
target_link_libraries(png_app ${PNG_LIBRARIES})
Test Solution 1
libpng was installed with homebrew like this:
brew install libpng
The output is of the program run is:
libpng version of lib (10637): libpng version 1.6.37 - April 14, 2019
used libpng version in app (10637): libpng version 1.6.37 - April 14, 2019
So we can see that it works like intended! Header version and used library version match.
Note: in the debug output we can see, that cc is called with
.../cc -I/usr/local/Cellar/libpng/1.6.37/include/libpng16 ...
and linking happens like this:
.../cc ... main.c.o -o png_app -L/usr/local/Cellar/libpng/1.6.37/lib -Wl,-rpath,/usr/local/Cellar/libpng/1.6.37/lib -lpng16 -lz
Note: if you get an error during building:
Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
then install it also with brew:
brew install PkgConfig
Solution 2
The second solution is without PkgConfig by using hard coded paths. If a new version of the library is installed, the PNG_BASEPATH must be adapted.
cmake_minimum_required(VERSION 3.17)
project(png_app C)
set(CMAKE_C_STANDARD 99)
set(PNG_BASEPATH /usr/local/Cellar/libpng/1.6.37)
set(PNG_LIBRARIES png16)
add_executable(png_app main.c)
target_include_directories(png_app PRIVATE ${PNG_BASEPATH}/include)
target_link_directories(png_app PRIVATE ${PNG_BASEPATH}/lib)
target_link_libraries(png_app ${PNG_LIBRARIES})
Why does find_package not work?
When I try to use the find_package variant from the OP question: You can see what the problem is with the output of the verbose build command :
The compile command looks like:
.../cc -I/Library/Frameworks/Mono.framework/Headers ... -o .../main.c.o -c .../main.c
So it tries to use libpng14.14 from /Library/Frameworks/Mono.framework instead of the version installed by homebrew.
I met the same issues while setting up the CI on github Actions.
At the end, again, Mono was conflicting. After a few hours trying to work around this conflict using various flags, I still got differences between build and runtime. For those without local MacOs to debug and test, here is a quick solution:
https://gist.github.com/nicerobot/1515915
It removes mono. It does not touch anything else, problem solved. Please do not do that for anything else, this is the most ugliest way to fix things. :)
Related
I have a Windows 7 64bit system with the latest MinGW (32bit) installed along with the Qt 5.5 SDK (again 32bit) which also ships with its own MinGW. Due to the fact that I'm not the only one using the system I can't remove the standalone MinGW.
My project is using qmake and is a plain C project (not C++). Everything builds fine but when I try to execute my binary in the command line I get that the application was unable to start due to a missing libgcc_s_dw2-1.dll on the system.
After looking into the issue I found that both the standalone MinGW and the one shipped alongside the Qt SDK have the mentioned DLL.
Standalone MinGW - libgcc_s_dw2-1.dll is located inside the bin subdirectory of the MinGW installation where the binaries are located (gcc, g++, gdb etc.)
Qt MinGW - libgcc_s_dw2-1.dll is located inside C:\Qt\Tools\mingw492_32\i686-w64-mingw32\lib subdirectory while the MinGW components' binaries are inside C:\Qt\Tools\mingw492_32\i686-w64-mingw32\bin.
I would like to know how to properly set my PATH variable so that:
The application starts properly
No conflicts with the standalone MinGW installation occur
Just a side-note: I've already checked other posts here on SO but was unable to find a solution (perhaps I've missed it). I have also tried LIBS += -static but the result is the same.
You just need to copy this dll with your executable, i.e.:
cp <path-to-qt-install-dir>\qt5.7.0\5.7\mingw53_32\bin\libgcc_s_dw2-1.dll <path-to-dest-dir>
You mat find that you have other dependencies, to see which other deps you have you can use: ldd <your-executable>. You only need to copy the qt specific dlls you can see these by:
ldd <executable> | grep -i qt
note
You can statically link it with:
linker commands like -static-libgcc or -static, but I think you start to hit LGPL issues and also you may need to statically compile qt from source - can't recall for this particular file.
note2
Sorry ldd is for linux, just realized you have windows, in which case you can use one or both of:
dependency walker: from here
<path-to-qt-bin-folder>\windeployqt.exe <path-to-your-executable>
I have mixed results with windeployqt, but if you have any plugins its quiet good for getting that part sorted.
There is a dynamic-linking-conflict between different libjpeg dynamic libraries on OSX. First there is a standard native libJPEG.dylib (in /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/). But if you are using MacPorts, you can also have a port-related libjpeg.dylib in (in /opt/local/lib). The latter may for example have been installed as a dependency for some other port.
This creates a problem when you link against your system libJPEG (which is preferred).
Then if /opt/local/lib is in DYLD_LIBRARY_PATH, that path will be prioritised when searching for a dynamic lib, resulting in a runtime error when loading symbols:
dyld: Symbol not found: __cg_jpeg_resync_to_restart
Referenced from:
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
Expected in: /opt/local/lib/libJPEG.dylib
in /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
Trace/BPT trap: 5
So I have two questions (likely related):
What is a good way of solving the actual problem (removing /opt/local/lib from DYLD_LIBRARY_PATH obviously solves it but creates problems for other dependencies)?
What other paths are searched for dynamic libs (I.e. Where is the "/System/Library" path specified) and why does DYLD_LIBRARY_PATH rank higher priority-wise?
I experienced similar problem while using OpenCV in MacOS El Capitan. Solved the problem using the solution in the link
Solution is to delete some dlylibs in the /usr/local/lib directory and create symbolic links to related files /System/Library/Frameworks/ImageIO.framework/Resources/
cd /usr/local/lib
rm libgif.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libGIF.dylib libGIF.dylib
rm libjpeg.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libJPEG.dylib libJPEG.dylib
rm libtiff.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libTIFF.dylib libTIFF.dylib
rm libpng.dylib
ln -s /System/Library/Frameworks/ImageIO.framework/Resources/libPng.dylib libPng.dylib
You should not set library paths using DYLD_LIBRARY_PATH. As you've discovered, that tends to explode. Executables and libraries should have their library requirements built into them at link time. Use otool -L to find out what the file is looking for:
$ otool -L /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO:
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.0)
...
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
For an example of one of my homebrew-built programs:
$ otool -L /usr/local/bin/gifcolor
/usr/local/bin/gifcolor:
/usr/local/Cellar/giflib/4.1.6/lib/libgif.4.dylib (compatibility version 6.0.0, current version 6.6.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
Note that it references /usr/local. If you've built it in such a way that it references the wrong library, I recommend rebuilding and pointing it to the correctly library.
If that's impossible, it is possible to edit what path is used using install_name_tool, but there are cases where this doesn't work, such as if the new path is longer than the old path and you didn't link it with -header_pad_max_install_names. Rebuilding with the correct path is preferred.
Note that there are a few "special" paths available that allow libraries to be found relative to their loader. See #executable_path/ and its kin in the dyld(1) man page.
If using Qt Creator, you have to uncheck the Add build library search path to DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH option from the Run section in the Projects tab:
I had a similar error when trying to run Apache Celix on macOS Sierra
If you use Homebrew to install libjpeg, libtiff, libpng which may confuse the linker to use macOS imageIO library. Simple fix is unlink those libs:
brew unlink libpng
brew unlink libtiff
brew unlink libjpeg
Re-link those libs whenever we need to:
brew link libpng
brew link libtiff
brew link libjpeg
I had a similar error, and i solved putting the following variable in my bash_profile:
export DYLD_LIBRARY_PATH=/usr/lib/:$DYLD_LIBRARY_PATH
I followed the instructions mdemirst suggested and it fixed my issue. I am using OS X Sierra.
I created a gist just in case someone else runs into the same issue.
Gist to fix Spidermonkey errors
I installed liblapack-dev and its dependencies using Synaptic, and I included <lapack.h> in my code.
If I try to compile my program like this...
mpicc program.c -llapack -o output
...I get the following error:
program.c:4:20: fatal error: lapack.h: No such file or directory
compilation terminated.
How can I fix this? I've already spent hours googling for a solution but nothing helped.
I'm using Linux Mint, but I tried the same thing on the latest version of Ubuntu and it still wouldn't work. Same thing when I try "eliminating" MPI from my program and compiling with gcc.
I experienced a similar issue on Debian. I noticed that
dpkg -L liblapack-dev
did not return a single header file. So I did some searching with apt-cache and found what appears to be C headers. After installing via
sudo apt-get install liblapacke-dev
(note the extra e!), I was able to compile a minimal working example, found here. Modifying the include at the top to read
#include <lapacke.h>
and compiling with
gcc -llapack lapack_example.c
successfully runs on my system. Hope this helps someone.
Answering because it doesn't fit in a comment:
The manual says:
Standard C language APIs for LAPACK
collaboration LAPACK and INTEL Math Kernel Library Team
LAPACK C INTERFACE is now included in the LAPACK package (in the lapacke directory)
LAPACKE User Guide
Updated: April 20, 2012
header files: lapacke.h, lapacke_config.h, lapacke_mangling.h, lapacke_utils.h
so perhaps you need to
#include <lapacke.h>
This is kind of an ugly one, but I am stuck so here it goes:
I am writing a dynamic library (henceforth 'mylib.dylib') that uses opencv (highgui and other parts) and is ultimately loaded by ffmpeg (libavfilter). The library compiles just fine. But when I try to dlopen() the dylib from within ffmpeg, I get the following error:
mylib.dylib: dlopen(mylib.dylib, 2): Library not loaded: /usr/local/lib/libpng15.15.dylib
Referenced from: /usr/local/lib/libopencv_highgui.2.3.dylib
Reason: Incompatible library version: libopencv_highgui.2.3.dylib requires version 17.0.0 or later, but libpng15.15.dylib provides version 16.0.0
However, when I run otool -L /usr/local/lib/libpng15.15.dylib I get the following:
/usr/local/lib/libpng15.15.dylib:
/usr/local/lib/libpng15.15.dylib (compatibility version 20.0.0, current version 20.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)
Last time I checked, 20.0.0 is later than 17.0.0, which is what highgui said it requires.
I thought maybe it was an architecture problem (I am on a Mac running Lion, so I've encountered a lot of problems with i386/x86_64), but running 'file' on all of the libraries revealed that everything (highgui, libpng, mylib) is Mach-O 64-bit dynamically linked shared library x86_64
I thought perhaps there was some other version of libpng hiding on my system somewhere, but the dlopen error specifically points to /usr/local/lib/libpng15.15.dylib
There is obviously something that I am missing here -- admittedly I am no expert on how these dynamic libraries link. So if I forgot to include some pertinent info, please excuse me.
UPDATE
I forgot to mention -- the lib works fine when I run ffmpeg through XCode (no dlopen error) which leads me to believe that it might have something to do with a environment variable that XCode is setting that I am not.
Thanks!
SOLUTION
1. Don't be dumb
I was using MAMP and since I was calling ffmpeg through a php script, it was using its own set of dylibs, which (surprise surprise) included libpng 16.0.0
I had something similar recently after I uninstalled all my MacPorts and installed updated versions. The problem was the version of libpng (1.2 vs 1.4 vs 1.5), not just the compatibility version. I had built OpenCV against libpng 1.4 (which is libpng14). I thought I could just use install_name_tool to make it look at libpng 1.5 (libpng15) instead but that didn't work. I ended up rebuilding OpenCV against the current versions of the library. That worked fine (after I remembered sudo cmake install).
(Some version numbers above might be incorrect but the gist is accurate.)
So either you don't have the version of libpng you originally had when you built OpenCV or it built against a libpng other than the one in /usr/local/lib (like maybe the one in /opt/local/lib). If that's the case you'll need to make sure you're building against the version you want to use. How to do that depends on your build method (MacPorts or cmake). I use cmake for OpenCV and MacPorts for other libraries which is why the two got out of sync on my system.
Just for those who need the code:
cd /Applications/MAMP/Library/lib
mv libpng15.15.dylib libpng15.15.dylib_old
ln -s /usr/X11/lib/libpng15.15.dylib .
I'm a complete beginner to Apple's Xcode, but I have followed the Xcode documentation and the advice of a few related questions without success.
I installed GMP to /usr/local/bin, wrote a short program using the library, and compiled with gcc main.c -lgmp. It compiled with no warnings or errors, and the executable worked flawlessly.
I started a new Xcode project (Command Line Tool; Type: C), copied the code to the newly created main.c, and opened the project build settings. From there I set Linking > Other Linker Flags to -lgmp and Search Paths > Library Search Paths to /usr/local/bin. However, the build fails with the preprocessor error "Gmp.h: No such file or directory".
I have tried almost every header imaginable:
#include "gmp.h"
#include <gmp.h>
#include "gmp"
#include "libgmp.a" . . .
This has been my main obstacle over the last three months which has prevented me from learning C. Any help leading me to an eventual solution would be greatly appreciated.
There's a few things you have to set up in your Xcode project. For example, I have gmp installed in /opt/gmp/5.0.2 and I will use that as an example. The actual library is installed into /opt/gmp/5.0.2/lib and the header files into /opt/gmp/5.0.2/include. When installing the library setting the --PREFIX flag to /opt/gmp/5.0.2 would handle this automatically. If you don't set this flag the prefix is usually set to /usr/local by default.
The Other Linker Flags looks right, it should be the name of the library.
Set the Header Search Path to the include directory, in my case /opt/gmp/5.0.2/include.
Set the Library Search Path to the lib directory, in my case /opt/gmp/5.0.2/lib.
Since the header search path has been set, you should now be able to include the header file like this:
#include <gmp.h>
Of course, replace /opt/gmp/5.0.2 with the PREFIX path you used when you installed gmp.
Lastly, you typically don't install libraries to /usr/local/bin, you would install to /usr/localand let any binaries be installed into bin while libraries like these would be installed into lib. Of course any path scheme would work, I usually recommend /opt/<project-name>/<version-number> since it allows me to keep better track of what I have installed and have multiple versions of the same libraries and tools without having to deal with collisions.
I have updated my system from snow leopard to mountain lion and had to install gmp.
First of all I have installed Xcode CommandLineTools set.
Secondly, installed Homebrew. Then with it I have done steps in this topic: https://apple.stackexchange.com/questions/38222/how-do-i-install-gcc-via-homebrew
In my last step, made changes to an xcode project as colleague Marcus Karlsson told.
It's finally working! Very big Thank You :)