'cmake' command fails when Exiv2 built as static
SPlesskin opened this issue ยท 12 comments
I'm developing a Qt 5.7 application on Linux Debian 9 and which uses Exiv2 0.27.2. When I run the cmake
command to generate the makefile, I get the following error(s):
CMake Error at src/CMakeLists.txt:30 (add_library):
Target "simphoniz-api" links to target "Iconv::Iconv" but the target was
not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
When I successfully compiled Exiv2 as a static library, I get the following messages:
-- The CXX compiler identification is GNU 6.3.0
-- The C compiler identification is GNU 6.3.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Performing Test Iconv_IS_BUILT_IN
-- Performing Test Iconv_IS_BUILT_IN - Success
-- Found Iconv: /usr/lib/x86_64-linux-gnu/libc.so
-- ICONV_INCLUDE_DIR :
-- ICONV_LIBRARIES : /usr/lib/x86_64-linux-gnu/libc.so
-- Looking for gmtime_r
-- Looking for gmtime_r - found
-- Looking for mmap
-- Looking for mmap - found
-- Looking for munmap
-- Looking for munmap - found
-- Looking for strerror_r
-- Looking for strerror_r - found
-- Performing Test EXV_STRERROR_R_CHAR_P
-- Performing Test EXV_STRERROR_R_CHAR_P - Success
-- Looking for C++ include memory.h
-- Looking for C++ include memory.h - found
-- Looking for C++ include process.h
-- Looking for C++ include process.h - not found
-- Looking for C++ include stdbool.h
-- Looking for C++ include stdbool.h - found
-- Looking for C++ include stdint.h
-- Looking for C++ include stdint.h - found
-- Looking for C++ include strings.h
-- Looking for C++ include strings.h - found
-- Looking for C++ include sys/stat.h
-- Looking for C++ include sys/stat.h - found
-- Looking for C++ include sys/types.h
-- Looking for C++ include sys/types.h - found
-- Looking for C++ include inttypes.h
-- Looking for C++ include inttypes.h - found
-- Looking for C++ include unistd.h
-- Looking for C++ include unistd.h - found
-- Looking for C++ include sys/mman.h
-- Looking for C++ include sys/mman.h - found
-- Looking for C++ include regex.h
-- Looking for C++ include regex.h - found
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- Install prefix: /home/erwan/git/simphoniz/external/build/external
...
-- Compiler info: GNU (/usr/bin/c++) ; version: 6.3.0
-- Building shared library: NO
-- Building PNG support: NO
-- XMP metadata support: NO
-- Native language support: NO
-- Conversion of Windows XP tags: YES
-- Nikon lens database: YES
-- Building video support: NO
-- Building webready support: NO
-- Building exiv2 command: YES
-- Building samples: NO
-- Building PO files: NO
-- Building unit tests: NO
-- Building doc: NO
-- Building with coverage flags: NO
-- Using ccache: NO
It seems that the problem comes from the libiconv library but I don't see why... Please, can you tell me what can be wrong with my configuration ? Thank you very much for your help.
I'll look at this when I get up in the morning. From the transcript, it appears that libiconv is built into libc on your platform. Can you clarify if you are building a static or shared library?
I've loaded a nice new debian 9.3 VM on my MacMini and can build both static and shared with 0.27.2 with GCC 6.3.0
rmills@rmillsmm-debian:~/gnu/github/exiv2/exiv2/static_build$ uname -a
Linux rmillsmm-debian 4.9.0-4-amd64 #1 SMP Debian 4.9.65-3 (2017-12-03) x86_64 GNU/Linux
rmills@rmillsmm-debian:~/gnu/github/exiv2/exiv2/static_build$ gcc --version
gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
I installed all the dependencies as documented in README.md:
sudo apt install --yes build-essential git clang ccache python3 libxml2-utils cmake python3 libexpat1-dev libz-dev zlib1g-dev libssh-dev libcurl4-openssl-dev libgtest-dev google-mock
The reason I asked for clarification is because you said:
When I successfully compiled Exiv2 as a static library, I get the following messages:
Here's my history. Everything build normally. Nothing unusual.
39 git clone https://github.com/exiv2/exiv2 --branch 0.27-maintenance --depth 1 0.27-maintenance
40 cd 0.27-maintenance/
41 git pull --unshallow
42 git checkout v0.27.2
43 git status
44 mkdir build
45 cd build
46 cmake .. -DBUILD_SHARED_LIBS=Off
47 make
48 make tests
49 ls -l bin lib
Oh, something I forgot to ask:
CMake Error at src/CMakeLists.txt:30 (add_library):
Target "simphoniz-api" links to target "Iconv::Iconv" but the target was
not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
I think that's something in your src/CMakeLists.txt. Exiv2 has:
rmills@rmillsmm-debian:~$ cd ~/gnu/github/exiv2/0.27-maintenance/src
rmills@rmillsmm-debian:~/gnu/github/exiv2/0.27-maintenance/src$ nl -b a CMakeLists.txt
1 # CMakeLists.txt for exiv2 library and command-line program
2
3 # Note that this is a hack for testing the internals of the library. If EXIV2_BUILD_UNIT_TESTS==OFF
4 # Then we only export the symbols that are explicitly exported
5 if( EXIV2_BUILD_UNIT_TESTS )
6 set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) # Requires CMake 3.3.3
7 endif()
8
9 include(CMakePackageConfigHelpers)
10
11 include_directories(${CMAKE_CURRENT_BINARY_DIR})
12
13
14 add_library( exiv2lib_int OBJECT
15 canonmn_int.cpp canonmn_int.hpp
16 casiomn_int.cpp casiomn_int.hpp
17 cr2header_int.cpp cr2header_int.hpp
18 crwimage_int.cpp crwimage_int.hpp
19 fujimn_int.cpp fujimn_int.hpp
20 helper_functions.cpp helper_functions.hpp
21 image_int.cpp image_int.hpp
22 makernote_int.cpp makernote_int.hpp
23 minoltamn_int.cpp minoltamn_int.hpp
24 nikonmn_int.cpp nikonmn_int.hpp
25 olympusmn_int.cpp olympusmn_int.hpp
26 orfimage_int.cpp orfimage_int.hpp
27 panasonicmn_int.cpp panasonicmn_int.hpp
28 pentaxmn_int.cpp pentaxmn_int.hpp
29 rw2image_int.cpp rw2image_int.hpp
30 safe_op.hpp
31 samsungmn_int.cpp samsungmn_int.hpp
32 sigmamn_int.cpp sigmamn_int.hpp
33 sonymn_int.cpp sonymn_int.hpp
34 tags_int.cpp tags_int.hpp
35 tiffcomposite_int.cpp tiffcomposite_int.hpp
36 tiffimage_int.cpp tiffimage_int.hpp
37 tiffvisitor_int.cpp tiffvisitor_int.hpp
38 tifffwd_int.hpp
39 timegm.h
40 unused.h
41 )
My suspicion is that you have something in your src/CMakeLists.txt file that's linking Iconv and expecting it to be in an external package. On the debian platform, it's in libc. I'm not an expert on CMake, however we have the code:
if( ICONV_FOUND )
target_link_libraries( exiv2lib PRIVATE Iconv::Iconv )
endif()
Unless you are using Iconv directly in your code, you don't need to think about Iconv as it will be linked into libexiv2 on your behalf. In the case of the static library, it'll be 100% invisible inside libexiv2.a:
rmills@rmillsmm-debian:~/gnu/github/exiv2/0.27-maintenance/build/lib$ ls -lh
total 13M
-rw-r--r-- 1 rmills rmills 11M Jun 7 00:43 libexiv2.a
-rw-r--r-- 1 rmills rmills 1.9M Jun 7 00:42 libexiv2-xmp.a
rmills@rmillsmm-debian:~/gnu/github/exiv2/0.27-maintenance/build/lib$
Thank you for your help. FYI, I'm building a static library (i.e., libsimphoniz-api.a). The Exiv2 library is statically linked into it. And it seems to be a problem since Iconv is linked into Exiv2 as PRIVATE. I found this explanation here:
"If, however, A is a static library, the situation changes. Static libraries do not carry
information about other libraries they depend on. For this reason, when A
links in B as PRIVATE and another target C links in A, CMake will still add
B to the list of libraries to be linked for C because parts of B are needed
by A, but A itself doesn't have that dependency encoded into it. So even
though B is an internal implementation detail of A, C still needs B added
to the linker command, which CMake conveniently handles for you."
So, I should probably also link Iconv into my static library in addition to Exiv2.
Ok, so I called the command find_package(Iconv)
in my CMakeLists.txt file and I linked the target Iconv::Iconv
along with exiv2lib
and now, I've no problem generating the Makefile with CMake. I don't need to do that when Exiv2 is compiled as a shared library. Maybe something needs to be added to the Exiv2 project to solve this kind of issue... Whatever, this issue can be closed.
@SPlesskin Thank You for updating this issue. I'm pleased that this issue can be closed. I'm going to ask @piponazo to comment as he is the Team Exiv2 CMake Magician!
I personally don't like static libraries. DLLs/shared objects are a much more "democratic" as the libraries and executables dance together.
Hi @SPlesskin , and thanks for reporting this.
The link from where you extracted the explanation about static libraries is correct. I had to do the same thing (include the call to find_package()
) in other projects where I was using static libraries. But it is important to note that this is not needed when working with shared ones.
Luckily CMake identifies the situation and the warning which is throwing you is quite clear:
CMake Error at src/CMakeLists.txt:30 (add_library):
Target "simphoniz-api" links to target "Iconv::Iconv" but the target was
not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
If there is a clan way to prevent this situation I would be happy to include it in our CMake code. However, I think there is not such approach and it is something that needs to be handled by the projects consuming exvi2 statically.
Thanks for looking into this, @piponazo. If you think I should add something in README.md about this, could you reopen the issue and set the milestone to v0.27.3.
I think we'll need a new section in README.md. Currently, building shared and static is mentioned in 2.3 Build Options. I think we add a new section 2.18 Building Shared and Static Libraries. I might need a little help to explain this, however if we go down this road, you can review my PR with the changes to README.md
Sure @clanmills, You can create a branch a give the structure to the README.md you have in your mind and I can add the CMake details later there ;)
Yes. Thank You @piponazo. I will add submit a PR tomorrow. I'm happy for this to go into 0.27.3 GM as it's only a change to the documentation.
@SPlesskin Thanks for bring up this topic. We've updated README.md in branch 0.27-maintenance with a new section concerning static and shared libraries. This issue report is referenced in the modified documentation. #1232.
Exiv2 v0.27.3 is on-track to ship on 2020-06-30 and will include the modified README.md. I'm going to close this issue. If you wish further discussion about this matter, please update this issue and it'll be re-opened.
I also get errors with XMP and inih.
CMake Error at /usr/local/lib/cmake/exiv2/exiv2Config.cmake:61 (set_target_properties):
The link interface of target "exiv2-xmp" contains:
EXPAT::EXPAT
but the target was not found. Possible reasons include:
* There is a typo in the target name.
* A find_package call is missing for an IMPORTED target.
* An ALIAS target is missing.
CMake Error at /usr/local/lib/cmake/exiv2/exiv2Config.cmake:61 (set_target_properties):
The link interface of target "exiv2lib" contains:
inih::libinih
but the target was not found. Possible reasons include:
Should I file a new issue?