1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
This file is part of MXE. See LICENSE.md for licensing information.
This patch was commited to OpenCV's 2.4 branch and we should be able to drop
it in the next point release.
commit eceada586bbf18fc267e437522ec4f1f23ddc656
Author: Samuel Martin <s.martin49@gmail.com>
Date: Fri Oct 3 00:32:40 2014 +0200
cmake/OpenCVGenPkgconfig.cmake: rework opencv.pc generation
Using absolute path to locate the components in the "Libs:" field of the
*.pc can badly break cross-compilation, especially when building
statically linked objects.
Indeed, pkg-config automatically replaces the '-I...' and '-L...' paths
when the PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_LIBDIR environment
variables are set [1]. This feature is very helpful and common in
cross-compilation framework like Buildroot [2,3].
When there are absolute paths in the *.pc files, pkg-config won't be
able to do the path substitions for these paths when the afromentioned
environment variables are set.
In such case, since the prefix is the target one, not the sysroot one,
these libraries' abolute paths will point to:
- in the best case: a non-existing file (i.e. these files do not exists
on the host system;
- at worst: the host system's libraries. This will make the linking
failed because these host system's libraries will most likely not be
build for the target architecture [4].
So, this patch replace the components' absolute paths by the form:
-L<libdir> -l<libname>
This way, the linker will be able to resolve each dependency path,
whatever the kind of objects/build (shared object or static build) it
is dealing with.
Note that for static link, the library order does matter [5]. The order
of the opencv components has been carefully chosen to comply with this
requirement.
Fixes #3931
[1] http://linux.die.net/man/1/pkg-config
[2] http://buildroot.org/
[3] http://git.buildroot.net/buildroot/tree/package/pkgconf/pkg-config.in
[4] http://autobuild.buildroot.net/results/e8a/e8a859276db34aff87ef181b0cce98916b0afc90/build-end.log
[5] http://stackoverflow.com/questions/45135/linker-order-gcc
Signed-off-by: Samuel Martin <s.martin49@gmail.com>
---
Note: this patch properly applies on top of the master branch, though it
has been written on top of the 2.4 branch.
diff --git a/cmake/OpenCVGenPkgconfig.cmake b/cmake/OpenCVGenPkgconfig.cmake
index fa57db9..183c56d 100644
--- a/cmake/OpenCVGenPkgconfig.cmake
+++ b/cmake/OpenCVGenPkgconfig.cmake
@@ -8,10 +8,6 @@
#
# ${BIN_DIR}/unix-install/opencv.pc -> For use *with* "make install"
# -------------------------------------------------------------------------------------------
-set(prefix "${CMAKE_INSTALL_PREFIX}")
-set(exec_prefix "\${prefix}")
-set(libdir "") #TODO: need link paths for OpenCV_EXTRA_COMPONENTS
-set(includedir "\${prefix}/${OPENCV_INCLUDE_INSTALL_PATH}")
if(CMAKE_BUILD_TYPE MATCHES "Release")
set(ocv_optkind OPT)
@@ -35,42 +31,66 @@ ocv_list_reverse(OpenCV_LIB_COMPONENTS)
ocv_list_reverse(OpenCV_EXTRA_COMPONENTS)
#build the list of components
-set(OpenCV_LIB_COMPONENTS_ "")
-foreach(CVLib ${OpenCV_LIB_COMPONENTS})
- get_target_property(libpath ${CVLib} LOCATION_${CMAKE_BUILD_TYPE})
- get_filename_component(libname "${libpath}" NAME)
- if(INSTALL_TO_MANGLED_PATHS)
- set(libname "${libname}.${OPENCV_VERSION}")
- endif()
+# Note:
+# when linking against static libraries, if libfoo depends on libbar, then
+# libfoo must come first in the linker flags.
+
+# world is a special target whose library should come first, especially for
+# static link.
+if(OpenCV_LIB_COMPONENTS MATCHES "opencv_world")
+ list(REMOVE_ITEM OpenCV_LIB_COMPONENTS "opencv_world")
+ list(INSERT OpenCV_LIB_COMPONENTS 0 "opencv_world")
+endif()
+
+set(OpenCV_LIB_COMPONENTS_)
+foreach(CVLib ${OpenCV_LIB_COMPONENTS})
- #need better solution....
- if(libpath MATCHES "3rdparty")
- set(installDir "share/OpenCV/3rdparty/${OPENCV_LIB_INSTALL_PATH}")
+ get_target_property(libloc ${CVLib} LOCATION_${CMAKE_BUILD_TYPE})
+ if(libloc MATCHES "3rdparty")
+ set(libpath "\${exec_prefix}/share/OpenCV/3rdparty/${OPENCV_LIB_INSTALL_PATH}")
else()
- set(installDir "${OPENCV_LIB_INSTALL_PATH}")
+ set(libpath "\${exec_prefix}/${OPENCV_LIB_INSTALL_PATH}")
endif()
+ list(APPEND OpenCV_LIB_COMPONENTS_ "-L${libpath}")
+
+ get_filename_component(libname ${CVLib} NAME_WE)
+ string(REGEX REPLACE "^lib" "" libname "${libname}")
+ list(APPEND OpenCV_LIB_COMPONENTS_ "-l${libname}")
- set(OpenCV_LIB_COMPONENTS_ "${OpenCV_LIB_COMPONENTS_} \${exec_prefix}/${installDir}/${libname}")
endforeach()
# add extra dependencies required for OpenCV
-set(OpenCV_LIB_COMPONENTS ${OpenCV_LIB_COMPONENTS_})
if(OpenCV_EXTRA_COMPONENTS)
foreach(extra_component ${OpenCV_EXTRA_COMPONENTS})
- if(extra_component MATCHES "^-[lL]" OR extra_component MATCHES "[\\/]")
- set(maybe_l_prefix "")
+ if(extra_component MATCHES "^-[lL]")
+ set(libprefix "")
+ set(libname "${extra_component}")
+ elseif(extra_component MATCHES "[\\/]")
+ get_filename_component(libdir "${extra_component}" PATH)
+ list(APPEND OpenCV_LIB_COMPONENTS_ "-L${libdir}")
+ get_filename_component(libname "${extra_component}" NAME_WE)
+ string(REGEX REPLACE "^lib" "" libname "${libname}")
+ set(libprefix "-l")
else()
- set(maybe_l_prefix "-l")
+ set(libprefix "-l")
+ set(libname "${extra_component}")
endif()
-
- set(OpenCV_LIB_COMPONENTS "${OpenCV_LIB_COMPONENTS} ${maybe_l_prefix}${extra_component}")
+ list(APPEND OpenCV_LIB_COMPONENTS_ "${libprefix}${libname}")
endforeach()
endif()
+list(REMOVE_DUPLICATES OpenCV_LIB_COMPONENTS_)
+string(REPLACE ";" " " OpenCV_LIB_COMPONENTS "${OpenCV_LIB_COMPONENTS_}")
+
#generate the .pc file
+set(prefix "${CMAKE_INSTALL_PREFIX}")
+set(exec_prefix "\${prefix}")
+set(libdir "\${exec_prefix}/${OPENCV_LIB_INSTALL_PATH}")
+set(includedir "\${prefix}/${OPENCV_INCLUDE_INSTALL_PATH}")
+
if(INSTALL_TO_MANGLED_PATHS)
set(OPENCV_PC_FILE_NAME "opencv-${OPENCV_VERSION}.pc")
else()
|