CMake: "add_library IMPORTED" check if the lib exists - android-ndk

I am importing a static lib in CMAKE using add_library.
The lib imports fine.But I also want to verify that.So I do this:
add_library(MYLIB STATIC IMPORTED)
set_target_properties(MYLIB PROPERTIES IMPORTED_LOCATION path/to/mylib.a)
#if(NOT MYLIB)
# message(FATAL_ERROR "MYLIB library not found")
#endif()
It always returns false, even when the path is correct and the lib is imported ok.How can I check that the lib is imported?
Using Cmake 3.4.1

Command add_library() creates a target, not a variable.
Target existence can be checked with TARGET keyword:
add_library(MYLIB STATIC IMPORTED)
#...
if(NOT TARGET MYLIB)
# Target is not exist
endif()
Note, that existence of the library target doesn't mean existence of the library file. Existence of the file should use EXISTS keyword:
if(EXISTS <path>)

Since you are failing/stopping processing anyway, then you could check it is imported by trying to use the library!
If you actually want to check before you import, then something like this may be appropriate:
find_library(MYLIB
NAMES mylib
PATHS
path/to/mylib.a
DOC "Find library mylib"
NO_DEFAULT_PATH)
if(NOT MYLIB)
message(FATAL_ERROR "MYLIB library not found")
endif()
You can remove NO_DEFAULT_PATH if you don't mind CMake looking in all the many default locations first before searching your stated PATHS.

Related

CXX1405 cmake exception while building android project

Got error when I build the project like in the below. I tried so many things but never succeeded. I'm using m1 MacBook. Is this related with this error ?
[CXX1405] exception while building Json A problem occurred starting process 'command '/Users/serhat/Library/Android/sdk/cmake/3.18.1/bin/cmake''
in build.gradle:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
and this is CmakeList.txt :
# For more information about using CMake with Android Studio,read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
I fixed this issue :
softwareupdate --install-rosetta

CMake: How to use an imported .so.1.2.3 in transitive dependencies

I have to import a libft4222.so.1.2.3 into a CMake project on Linux. There are no symlinks without version information like a plain libmyimportedlibrary.so. I am writing a FindLibFT4222.cmake to make the library usable in my project.
In my project, a shared library uses libft4222 like this:
if (LIBFT4222_FOUND)
if (NOT TARGET LibFT4222::LibFT4222)
add_library(LibFT4222::LibFT4222 UNKNOWN IMPORTED)
set_target_properties(LibFT4222::LibFT4222
PROPERTIES IMPORTED_LOCATION ${LibFT4222_LIBS})
target_include_directories(LibFT4222::LibFT4222
INTERFACE
${LibFT4222_INCLUDE_DIR})
endif()
endif()
LibFT4222_LIBS points to the imported location of the libft4222.so.1.2.3:
/path/to/libft4222.so.1.2.3
I am adding this library as a dependency to a shared library A in my project.
Finally, I have an executable depending on A.
When I link the executable, the linker reports an error that it cannot find libft4222.so
When I add libft4222 directly to the executable, it works.
The error message I get:
/usr/lib/gcc-cross/arm-linux-gnueabihf/9/../../../../arm-linux-gnueabihf/bin/ld: warning: libft4222.so, needed by libSomeOtherLib.so, not found (try using -rpath or -rpath-link)
How do I tell CMake to correctly handle libft4222.so.1.2.3 and not to omit .1.2.3?
Update 1: I looked at the SONAME property of libft4222.so.1.2.3:
$ arm-linux-gnueabihf-objdump -p libft4222.so.1.4.4.44 | grep SONAME
SONAME libft4222.so
So I guess creating the symlinks is unavoidable.

CMake Precompiled Headers not including correctly for Visual Studio

So I've recently started using the "new" target_precompile_headers command for CMake to generate and include my precompiled headers.
But for some reason it doesn't seem to work at all the way I want it.
I do understand that the usage of this command is to provide the list of headers to include in your pch and that CMake itself generates the actual pch. This seem to work just fine as I can see the pchs generated for each config & project in my solution.
However looking at the project properties, and more specifically looking at the .cpp properties the /FI command is always empty, which means no files are force included.
This also means that none of my cpp catches that I am using pch at all and my compile fails.
Does anyone have any suggestions on what could be wrong?
// Example of a CMakeLists.txt which defines a static lib using PCH
file(GLOB ALL_SOURCE_FILES "*.cpp" "*.h")
add_library(MyLib STATIC ${ALL_SOURCE_FILES})
target_precompile_headers(MyLib PRIVATE MyHeader.h)
Below you see my own lib created with the snippet above. As you can see, no Forced Include file is added, thus no cpp files gets the PCH included.
I found this workaround: Adding the compiler option manually...
if(MSVC)
target_compile_options(YourProject PRIVATE "/FI${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir/$<CONFIG>/cmake_pch.hxx")
endif()
(Currently using Cmake 3.24.1 with cmake_minimum_required(VERSION 3.18) in the file)

How do I write the cmake script for clion to include glfw?

cmake_minimum_required(VERSION 3.15)
project(hello)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello main.cpp)
INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(hello ${GLFW_STATIC_LIBRARIES})
It tells me
CMake Error at /home/user/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/193.5233.144/bin/cmake/linux/share/cmake-3.15/Modules/FindPkgConfig.cmake:696 (message):
None of the required 'glfw3' found
when I try to build it. My glfw folder is located at /usr/local/include/GLFW.
AFAIK, glfw3 is using CMake as the build system,
(src: packages.debian.org/fr/sid/amd64/libglfw3-dev/filelist)
which uses modern CMake, so you don't need GLFW_INCLUDE_DIRS etc...
Inside this file /usr/lib/cmake/glfw3/glfw3Targets.cmake (loaded by /usr/lib/cmake/glfw3/glfw3Config.cmake), you'll see:
...
# Create imported target glfw
add_library(glfw SHARED IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "GLFW_DLL"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include"
)
...
So you can simply use:
find_package(glfw3 REQUIRED)
...
target_link_libraries(Foo glfw)
ps: same as my previous comment

"undefined reference" error from static lib of external parquet project

I want to link expernal 'parquet' project ( https://github.com/apache/arrow/tree/master/cpp ) as part of my current project on Linux.
For this purposes I ran cmake of parquet with such parameters
cd build_parquet
cmake -DCMAKE_BUILD_TYPE=Release -DARROW_PARQUET=ON \
-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_ROOT=${BOOST_BUILD_DIR}/include -DBOOST_LIBRARYDIR=${BOOST_BUILD_DIR}/lib/boost -DARROW_BOOST_USE_SHARED=OFF -DBOOST_INCLUDEDIR=${BOOST_BUILD_DIR}/include/boost ..
cmake --build . --config Release
// There are a lot of dependencies except boost, but only boost required to be installed on system, since other could be downloaded and installed by cmake script
Project successfully compiled. I got executable which could launch, generated static libs libarrow.a, libparquet.a, shared libraries libarrow.so, libparquet.so
In my main project I want to use such libraries and I use such commands in cmake to find them
find_path(PARQUET_INCLUDE_DIR NAMES arrow/api.h PATHS ${PARQUET_DIR}/src)
find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.a
PATHS build_parquet/release/Release/ )
find_library(ARROW_LIBRARY_RELEASE NAMES arrow.a
PATHS build_parquet/release/Release/ )
set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Parquet DEFAULT_MSG PARQUET_INCLUDE_DIR
${PARQUET_LIBRARIES_RELEASE } )
That's work okay, libraries and includes are found.
Then I link this libraries to my project
target_link_libraries(${myExe} ${PARQUET_LIBRARIES_RELEASE} ${mySomeOtherLibraries} )
after this I got enormous amount of linker errors such that
libparquet.a(column_writer.cc.o): In function `apache::thrift::transport::TMemoryBuffer::~TMemoryBuffer()':
column_writer.cc:(.text._ZN6apache6thrift9transport13TMemoryBufferD0Ev[_ZN6apache6thrift9transport13TMemoryBufferD5Ev]+0x3): undefined reference to `vtable for apache::thrift::transport::TMemoryBuffer'
.....
so that's what I don't understand much, why lib compiled well in parquet project itself but has a lot of unresolved now, when I use it to link in my own project? Moreover I compiled project for windows and when I did the same things, but with arrow.lib and parquet.lib (instead of libparquet.a and libarrow.a ) things worked fine! I was needed only to put arrow.dll, parquet.dll to executables to run project. But in Linux I've already crashed my head
So, why it doesn't work, what I should do to finally link the project with library ?
Update
I found the problem, I had to link libraries with adding .so files (not only .a files) like this
find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.so parquet.a
PATHS build_parquet/release/Release/ )
find_library(ARROW_LIBRARY_RELEASE NAMES arrow.so arrow.a
PATHS build_parquet/release/Release/ )
set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )
Project is builded. So now the question is, why I need to add .so files to linker (in Windows only static .lib are enough), is it always a case when I build project in Linux ? Is order of linkage important ( .so files first and .a files next ? )
As Uwe wrote in a comment, the https://github.com/apache/parquet-cpp repository is deprecated, and the Parquet C++ library is being developed as part of the Apache Arrow C++ codebase https://github.com/apache/arrow/tree/master/cpp. Can you try building based on that, and if you have trouble can you post on the dev#arrow.apache.org mailing list?
You have succeed to build the project when link with the shared (.so) libraries instead of the static (.a) ones.
(The command find_library actually looks for one library, which name is listed in NAMES option. In your case it found .so library because its name comes before the .a one).
Actually, both shared and static parquet libraries contain the same set of symbols, and both sets are insufficient for link. The difference is that the shared library contains information, where to find remaining symbols (in the thrift library in your case), but the static library doesn't.
For correctly link with the static libraries, you need to list dependent libraries manually.
On Windows .lib file may mean either a static library, or a import file for the shared (.dll) one. It seems that you link with the dynamic one (it has no lib prefix), which succeed like on Linux.

Resources