CMake interface dependency - cmake

I recently saw the use of PUBLIC / PRIVATE in the CMake dependency. For what I have learned ,if I want to build a shared library which use another library then:
use PUBLIC- for including that library in both my cpp and header files.
use PRIVATE - for including that library only in my cpp files.
use INTERFACE - for including that library only in my header file.
What is the main idea ? How can I improve my CMake file with that feature?
can it be used in both static library and dynamic one?
Here is my CMake file:
cmake_minimum_required (VERSION 2.8)
set (CMAKE_CXX_FLAGS "-Weverything -std=c++11 -Wall -Wextra -g")
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_BUILD_TYPE Debug)
project (internal)
set (internal VERSION 0.2)
file (GLOB internal_src
"utils.cpp"
"inspection.cpp"
"ct_proxy_if.cpp"
"stats.cpp")
file (GLOB main_SRC
${internal_src}
"mainW.cpp")
add_library(${PROJECT_NAME} STATIC ${internal_src})
target_link_libraries(internal infrastructures pthread jsoncpp ssl crypto)
I am using static library named infrastructures ( a library which my colleague developed)
I read this post CMake target_link_libraries Interface Dependencies

Related

How does cmake set the file name of the dynamic library to be built?

I want to add a LuaJIT wrapper to libgit2 so that it can be used in neovim.
The cmake configuration is as follows:
cmake_minimum_required(VERSION 3.22.2)
project("git2-neovim")
message(STATUS "cmake binary directory: ${CMAKE_BINARY_DIR}")
# Compile commands are output to "compile_commands.json", so that tools such as "ccls" can provide assistance.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Set gcc compile options.
set(CMAKE_C_FLAGS_DEBUG "$ENV{CFLAGS} -Wall -g3 -ggdb")
set(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -O3 -Wall")
set(
SRC_FILES
src/libgit2.c
)
add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
find_package(PkgConfig REQUIRED)
if (PKG_CONFIG_FOUND)
pkg_check_modules(LIBGIT2 REQUIRED libgit2)
include_directories(${LIBGIT2_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${LIBGIT2_LIBRARIES})
endif(PKG_CONFIG_FOUND)
This generates a "libgit2-neovim.so" file, but I want to generate a "libgit2.so" file.
Since I only use it in neovim, there is no conflict with the real libgit2.
environmental information:
operating system: Archlinux
cmake version: 3.25.1
============================== replenish ============================
When LuaJIT is looking for a shared library, it will only automatically add the file of the shared library according to the operating system, and will not add a prefix. The example is as follows:
require("demo")
The lua code above loads the "demo.so" file but not the "libdemo.so" file.
Therefore, I want to set in cmake, compile in any operating system, the output shared library must have "lib" prefix.
How does cmake set the file name of the dynamic library to be built?
The output filename is controlled by target properties https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#library-output-artifacts , and the default is composed of https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LIBRARY_PREFIX.html followed by library name followed by https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LIBRARY_SUFFIX.html .
I want to generate a "libgit2.so" file
So name your library git2 not git2-neovim.
add_library(git2
or set LIBRARY_OUTPUT_NAME target property of the target.

find_package static library instead of shared library

When building my project with CMake, I would like it to link to libraries statically (if available). Right now, it finds .dll.a files, regardless of the existence of .a files.
For example, take linking to libpng in a small sample project:
cmake_minimum_required(VERSION 3.15)
project(Test)
add_executable(Test main.cpp)
find_package(PNG REQUIRED)
message(${PNG_LIBRARIES})
target_link_libraries(Test PRIVATE ${PNG_LIBRARIES})
For the message, it outputs
C:/msys64/mingw64/lib/libpng.dll.aC:/msys64/mingw64/lib/libz.dll.a
But the libpng.a and libz.a files are also available in the same directory. How can I tell CMake to link with .a files?
I am using MinGW-w64 with msys64 on Windows 10, but would prefer a solution that is cross-platform.

Setting path to Clang library in CMake

I build llvm from git and want to use the libraries in a project, especially the libclang.
The "makefiles" are generated by means of CMake and for the LLVM part I found the setting LLVM_DIR to reroute the path for the llvm libraries, but for Clang I cannot find such a variable and I still see in my link line (it is a Cygwin system):
/usr/lib/libclang.dll.a /usr/lib/libclangTooling.dll.a.
Question: which environment variable do I set to get the right build Clang libraries?
The variable is Clang_DIR.
Just in case, I attach a minimalistic example of CMakeLists.txt file as well.
cmake_minimum_required(VERSION 3.12)
# Find CMake file for Clang
find_package(Clang REQUIRED)
# Add path to LLVM modules
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${LLVM_CMAKE_DIR}"
)
# import LLVM CMake functions
include(AddLLVM)
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
add_definitions(${CLANG_DEFINITIONS})
add_llvm_executable(myTool main.cpp)
set_property(TARGET myTool PROPERTY CXX_STANDARD 11)
target_link_libraries(myTool PRIVATE clangTooling)

Using target_include_directories with object libraries

I have a CMake project that builds a static library which depends on another static library. I would like to turn this static library into an object libraries. When I do that I get a compiler error and I imagine that there is something I don't get about object libraries.
Here is an example of what I am trying to achieve. MyLib and MyLib2 are both static libraries and MyLib uses a function defined and declared in MyLib2.
MyLib
CMakeList.txt
MyLib.h
MyLib.cpp
MyLib2
CMakeList.txt
MyLib2.h
MyLib2.cpp
MyLib2/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project (MyLib2)
add_library(${PROJECT_NAME} OBJECT MyLib2.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
MyLib/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project (MyLib)
add_subdirectory(MyLib2)
add_library(${PROJECT_NAME} STATIC MyLib.cpp MyLib.h)
target_link_libraries(${PROJECT_NAME} MyLib2)
MyLib.h includes MyLib2.h to use the function it declares.
#ifndef MyLib
#define MyLib
#include "MyLib2.h"
#endif
When MyLib2 is built as a static library I can build the code without any problems (I am using make and clang on Mac). However when I turn MyLib2 into an object library I get a compile error saying that MyLib2.h cannot be found.
MyLib.h:4:10: fatal error: 'MyLib2.h'file not found
Here are the content of the CMake files when MyLib2 is an object library.
MyLib2/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project (MyLib2)
add_library(${PROJECT_NAME} OBJECT MyLib2.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
MyLib/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project (MyLib)
add_subdirectory(MyLib2)
add_library(${PROJECT_NAME} STATIC MyLib.cpp $<TARGET_OBJECTS:MyLib2>)
I do not understand why MyLib can no longer MyLib2.h when MyLib2 is an object library. Maybe there is something wrong with the way is use target_include_directories.
This was answered in the comments:
#Clem: When you link with libary target, you consume its INTERFACE_INCLUDE_LIBRARIES property, which contains include directory Mylib2. When you use object library via $, you don't use any target, so don't consume any property. – Tsyvarev

Making a static lib target with variable dependencies with CMake

So I have a static library A which can have a bunch of settings turned on, depending on the compiling configuration. I have these settings pushed out to an IMPORT file:
cmake_minimum_required (VERSION 2.8)
MESSAGE(STATUS "***Making A With FOO***")
add_definitions(-DFOO)
include_directories("$ENV{FOO_ROOT}/Includes")
link_directories("$ENV{FOO_ROOT}/Libraries")
called with
cmake_minimum_required (VERSION 2.8)
project(A)
if (FOO)
IMPORT(CMakeList.Foo.txt)
ADD_LIBRARY(A STATIC a.cpp)
Because the library is static, it appears that I have to populate these settings to any other project in the chain that exports them...is there a way to get the library to do its own linking to other static libraries, or is the only way around this to make the library shared?
Edit: I should add that I'm building this as part of a subdirs project