24

I have built opencv locally and installed it to a local directory (not the system default ). opencv.pc is present under a folder pkgconfig in this local folder. How can I find this opencv.pc from cmake, because I want to link and include opencv files from my program.

pkg_search_module(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*)

does not have any parameter in which I can force the command to use a specific path (similar to HINTS with find_package()) and not the system default.

So basically .cmake works:

find_package(OpenCV REQUIRED HINTS "my/path/to/share/OpenCVConfig.cmake") 

but I would like to use a opencv.pc located under my/path/to/pkgconfig/opencv.pc.

pevik
  • 4,523
  • 3
  • 33
  • 44
infoclogged
  • 3,641
  • 5
  • 32
  • 53

3 Answers3

36

After doing some research and a hint from the @OlivierM, I found the answer.

Here are the steps:

Method I :

CMAKE_PREFIX_PATH can be set to find the .pc files

set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/libs/opencv-install")

Method II A second method is to use the PKG_CONFIG_PATH, which is a system environment variable to look for .pc files.

set(ENV{PKG_CONFIG_PATH} "${CMAKE_SOURCE_DIR}/libs/opencv-install/lib/pkgconfig")

Irrespective of which method you use,

For old (traditional) CMake:

find_package(PkgConfig REQUIRED)
pkg_search_module(PKG_OPENCV REQUIRED opencv)  # this looks for opencv.pc file

Please note that the PKG_OPENCV variable can be named anything. Whatever it is is named, its used as a prefix. For example if you name ABCD, then include directories will be ABCD_INCLUDE_DIRS

The variable PKG_OPENCV_INCLUDE_DIRS and PKG_OPENCV_LIBRARIES contains the header files (compile stage) and libraries (link stage) respectively.

One very important thing I noticed was that the variable PKG_OPENCV_LIBRARIES just provides the libraries and not the library path during the link stage. In order to use the library path as well in one command, one has to use

PKG_OPENCV_LDFLAGS 

This variable contains the library path as well as all the libraries listed in the package config file.

for examaple:

include_directories(${PKG_OPENCV_INCLUDE_DIRS})
target_link_libraries (FINAL_BINARY ${PKG_OPENCV_LDFLAGS})

For modern CMake:

In modern CMake we don't want variables, we want targets.

find_package(PkgConfig REQUIRED)
# this looks for opencv.pc file and creates a new target
# IMPORTED_TARGET requires CMake >= 3.6.3
pkg_search_module(PKG_OPENCV REQUIRED IMPORTED_TARGET opencv)

All variables will still be created for backwards compatibility, but IMPORTED_TARGET will create a target you can use in your project which will automatically propagate all of its build and usage requirements:

target_link_libraries(my_proj PRIVATE PkgConfig::PKG_OPENCV) 
pevik
  • 4,523
  • 3
  • 33
  • 44
infoclogged
  • 3,641
  • 5
  • 32
  • 53
  • I don't know why it isn't using those variables to search... ` CMAKE_PREFIX_PATH, CMAKE_FRAMEWORK_PATH, and CMAKE_APPBUNDLE_PATH` – Gelldur Sep 21 '17 at 17:17
  • @DawidDrozd I dont understand your query / statement. Can you plz elaborate? – infoclogged Sep 26 '17 at 11:38
  • I set `CMAKE_PREFIX_PATH` etc and pkg_search_module do not check those paths – Gelldur Sep 26 '17 at 15:37
  • @DawidDrozd then try the envirionment variable. This will definetly find your .pc file. Please note that the first parameter n pkg_search_module can be any thing. I set it to PKG_OPENCV. You can set to ABCD for ex. Also, check with your command line first before going for CMake.. pkg-config --cflags yourpackageconfigfilename. – infoclogged Sep 27 '17 at 14:31
  • don't you mean target_include_directories? Also, can you please add the version of cmake you're talking about in your answer. – johnb003 Jun 19 '18 at 02:20
  • the different is just the scope of include_directories..you can use either of them. I tested with 2.6. But in the meanwhile I am using 3.8.2. What problems are you facing? – infoclogged Jun 19 '18 at 17:06
  • Method 1 is wrong. It is a pre-fix path so it would be something like `set(CMAKE_PREFIX_PATH /path/to/opencv/install/")`. Then FindPkgConfig.cmake appends to this as appropriate. – fdk1342 Aug 15 '19 at 21:39
  • Yes as @Fred comment, in Method 1 CMAKE_PREFIX_PATH should be set on folder which has share/pkgconfig inside eg. when some custom build is used by ./configure --prefix=SOME_FOLDER when pc files are generated in SOME_FOLDER/share/pkgconfig. – MariuszW Oct 07 '19 at 17:04
  • On Windows under Cygwin the Method 1 (CMAKE_PREFIX_PATH, CMAKE_FRAMEWORK_PATH, CMAKE_APPBUNDLE_PATH) does not work now, see https://gitlab.kitware.com/cmake/cmake/-/issues/21775. Another reason why Method 1 may not work for someone is wrong usage: PKG_CONFIG_PATH should include the prefix /lib/pkgconfig, while CMAKE_PREFIX_PATH should not (because FindPkgConfig.cmake appends it automatically). – Alexander Samoylov Feb 04 '21 at 00:55
10

You could set PKG_CONFIG_PATH with the CMake line:

set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/my/path/to/pkgconfig")

I did this workaround in this file

Interestingly, it seems CMake 3.1 extends PKG_CONFIG_PATH with some CMake variable see: https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3df51470

OlivierM
  • 2,820
  • 24
  • 41
  • I dont see any pkg_search_module in your code. how are you looking for the modules? – infoclogged Jun 11 '17 at 19:36
  • It is actually a common file I created to support cross-compilation. I used `find_package` in the top `CMakeLists.txt`. See [here](https://github.com/labapart/gattlib/blob/master/CMakeLists.txt#L30) – OlivierM Jun 11 '17 at 20:21
  • Should there be a directory called `pkgconfig` if you run the command `ls /my/path/to/pkgconfig` or should there just be the `*.pc` file in that location? – FreelanceConsultant Dec 04 '22 at 11:35
0

I would propose you to call cmake with custom PKG_CONFIG_PATH variable, like below:

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig cmake <some args>

Or can make PKG_CONFIG_PATH update to be permanent for whole bash session:

$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig
$ cmake <some args>