Making a static lib target with variable dependencies with CMake - 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

Related

Proper use of target_include_directories() in CMake

I`m refactoring a CMake project. I wanted to include pre-compiled third-party .dll library into custom shared library, but have difficulties with populating headers files.
Project structure:
CMakeListst.txt
app
CMakeLists.txt
modules
my-library
include
CMakeLists.txt
...
third-party // precompiled, non-CMake
third-party.dll
include
build
modules
my-library
my-library.dll
include
app
app.exe
I have a third-party library ("third-party"), which I want to include into "my-library". So CMakeLists for "my-library" looks like this:
cmake_minimum_required(VERSION 3.15)
project("my-library" VERSION 0.0.0 LANGUAGES CXX)
set(PUBLIC_HEADERS
include/my-library.h
)
set(SOURCES
my-library.cpp
)
add_library("my-library" SHARED ${PUBLIC_HEADERS} ${SOURCES})
target_link_libraries("my-library" PUBLIC "${CMAKE_SOURCE_DIR}/third-party/third-party.dll")
target_include_directories("my-library" PUBLIC "${CMAKE_SOURCE_DIR}/third-party/include")
target_include_directories("my-library" PUBLIC include)
And then add "my-library" to the app like this:
target_include_directories("app" PRIVATE "${CMAKE_SOURCE_DIR}/modules/my-library/include")
target_link_libraries("app" PRIVATE "${CMAKE_BINARY_DIR}/modules/my-library/my-library.dll")
But I get 'No such file or directory #include "third-party.h"'. In other words, app has no access to third-party inlcude directory.
Though it can be fixed by copying "include" of third-party to "include" of my-library,
is doesn`t look like a correct method. Or is it how includes supposed to be used? What am I missing here? I had a perception, that unlike include_directories() target_include_directories() should export included path.

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.

CMake interface dependency

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

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

How to set BUILD_SHARED_LIBS for included directory

I have a very basic CMake project that uses Google Test. I want to build it as a dll, and the CMakeLists.txt file in gtest indicates that BUILD_SHARED_LIBS needs to be set in order for gtest to be built as a shared library.
My problem is that I cannot figure out how to set BUILD_SHARED_LIBS so that it shows up. If I use cmake-gui an set the value in the cache, then I do indeed see the generated build attempt to create a dll.
Below is my CMakeLists.txt. I would appreciate any suggestions on how to make it set BUILD_SHARED_LIBS.
CMAKE_MINIMUM_REQUIRED(VERSION 3.0 FATAL_ERROR)
PROJECT(MyProj)
SET(BUILD_SHARED_LIBS ON)
ADD_EXECUTABLE(MyProj main.cpp)
ADD_LIBRARY(MyLib STATIC mylib.cpp)
TARGET_LINK_LIBRARIES(MyProj MyLib)
ADD_SUBDIRECTORY(gtest-1.7.0)
Google Test will only build as a shared library (DLL) if BUILD_SHARED_LIBS is set. Hence I want to set that in this CmakeLists.txt file. I know how to make my own library shared, but I can't figure out how to set that variable in a way that the gtest CMakeLists.txt file sees it.
In your code
ADD_LIBRARY(MyLib STATIC mylib.cpp) // Your code STATIC lib
Change above line to this
ADD_LIBRARY(MyLib SHARED mylib.cpp) // Shared Lib is added