cmake findPackage : compile package one after the other - cmake

I have a project with the actual structure, where Components are subdirectories :
CMakeList.txt
|
---Component1/CMakeList.txt
|
---Component2/CMakeList.txt
|
---Component3/CMakeList.txt
Component2 relies on many libraries from Component1.
Component3 relies on many libraries from Component1 and Component2.
In many months, my project want to separate Component1, Component2 and Component3 in 3 differents git repositories. So i created 2 packages : component1.cmake and component2.cmake.
But now, with the findPackage solution, my actual structure doesn't work anymore. During compilation, the configuration failed because Component1 and Component2 haven't been built. (It works if i compile the components manually one after the other).
My main CMakeLists.txt look like this :
project(my_project)
add_subdirectory(Component1)
add_subdirectory(Component2)
add_subdirectory(Component3)
And after i use findPackage in Component2 and Component3 to use the libraries.
Is there a solution for this issue by keeping the add_subdirectory rather than using include ? Maybe is there a solution to compile components (which are subdirectories and not targets) one after the other?

Related

CMake find function defined in sibling path in project

CMake project structure:
/project/CMakeLists.txt
/project/lib/CMakeLists.txt
/project/app/CMakeLists.txt
/project/lib/CMakeLists.txt defines a function
FUNCTION (LIB_MYFUNC ...)
...
ENDFUNCTION ()
The trouble is that /project/app/CMakeLists.txt can't see this function. It can see the function if the function lives in /project/CMakeLists.txt but that's not a sensible organization for my project because reasons.
For third party packages, functions are defined somewhere in the system installation and the project can FIND_PACKAGE. I do not want to have to define and install my library CMake stuff on the system, I want it all contained within the local project file tree.
How can I tell /project/app/CMakeLists.txt to search in sibling branches of the project for functions? (I don't want /project/app/CMakeLists.txt to have to know and name /project/lib explicitly, but for all sibling branches to be searched.)

CMake: circular dependency on different targets

My project has a CMakeLists in a libs/ directory like this:
add_subdirectory(foo)
add_subdirectory(bar)
With bar depending on foo.
I recently added new functionalities to foo, and appropriate tests. However those tests need functionalities from bar. This means I currently need to run CMake twice to be able to compile.
Is there a way to get around this issue or am I stuck with re-running cmake multiple times?
Is there a way to declare my dependencies in a specific way maybe? ie right now I do this:
add_library(${BAR} ${SRC_FILES} ${PUBLIC_HEADERS} ${PRIVATE_HEADERS})
which means that linking against ${BAR} in a test (located in the foo module) will expand the variable to an empty string. Can I tell CMake that this should be a target and not just a target name?

cmake function for using a modular library with multiple targets

I develop some library which is mainly some set of interfaces to third-party packages. In my library there are core routines which need to be compiled anyway and a set of optional ones which one need to compile in case of using it in the code.
Let me illustrate it on some example.
Library
|---interfaces
| |---first
| | |---CMakeLists.txt
| | |---...
| |---second
| |---CMakeLists.txt
| |---...
|---core_routines
| |---CMakeLists.txt
| |---...
|---dependencies.cmake
This is a tree of my project. My library is a header-only. I need to write cmake function which one can use to efficiently add required submodules in its project.
Currently I use my own quite ugly solution. Namely, below you can see how my dependencies.cmake file looks like
#first interface dependencies
if(first)
link_directories(...)
include_directories(...)
add_subdirectory(${SOME_PATH}/interfaces/first
"${CMAKE_CURRENT_BINARY_DIR}/first")
endif()
#second interface dependencies
if(second)
...
endif()
#core routines
add_subdirectory(${SOME_PATH}/core_routines/
"${CMAKE_CURRENT_BINARY_DIR}/core_routines")
#function for adding required libs to new target
function(add_new_target new_target)
target_link_libraries(
${new_target} core_lib
)
if(first)
target_link_libraries(
${new_target} first_lib
)
endif()
if(second)
target_link_libraries(
...
)
endif()
endfunction(add_new_target)
Now, when I use my library in some code, the corresponding CMakeLists.txt file looks like
set(first ON)
set(second ON)
include(dependencies.cmake)
add_executable(main.exe main.cpp)
add_new_target(main.exe)
I use this way to compile the example since, as far as I know, one needs to specify link_directories and include_directories before adding new executable and then specify required libraries with target_link_libraries after it. Correct me if I am wrong.
My question is whether it is possible to write something better in this case? I need to keep modular structure of my code because, first, some interfaces require of using libraries which can be not installed on user PC, and, second, the main usage of my library will be in projects with cmake file which includes a lot of different targets, so I need to have some function which can specify required libraries and interfaces depending on user request.
link_directories() and include_directories() are not the modern way. They are too broad. By default, almost everything in modern CMake is target_* based.
Each sub-directory target should already be using target_include_directories() and target_link_libraries() with "PUBLIC" or "INTERFACE" for transitive dependencies, i.e. to carry along what is needed to successfully include and link them.
If these libraries are third party and don't already bundle their transitive dependencies, then you can do it for them using set_target_properties() with the "INTERFACE_INCLUDE_DIRECTORIES" AND "INTERFACE_LINK_LIBRARIES" properties.
Supply a list of all the libraries that client programs need to link. This would be a great deal like the builtin FindBoost module, which takes in a list of components, then prepares variables for each component, plus BOOST_LIBRARIES which is a list of all of the components.
set(my_component_libraries core_lib)
if(first)
list(APPEND my_component_libraries first_lib)
endif()
# etc.
set(my_component_libraries ${my_component_libraries} PARENT_SCOPE)
This way you leave the actual linking up to the users.
If you write your CMake interface to be find_package compatible, you can actually use the COMPONENTS interface to find_package, just like Boost.

How to export a single header file for multiple shared libraries?

I got a top-level CMakeLists like this:
cmake_minimum_required(VERSION 3.6.2)
project(Template)
set(CMAKE_LINK_DEPENDS_NO_SHARED ON)
add_subdirectory(external/libA)
add_subdirectory(external/libB)
add_subdirectory(external/libC)
add_subdirectory(apps/app1)
add_subdirectory(apps/app2)
It's a simple project which has 3 shared libraries {libA, libB, libC} and a couple of executables {app1, app2} which use those libraries.
My question is next, I've seen CMake gives some helpers to avoid going through the hazzle of coding custom headers and messing up with .defs to export symbols with something like below:
include (GenerateExportHeader)
GENERATE_EXPORT_HEADER(libA
BASE_NAME libA
EXPORT_MACRO_NAME SHARED_EXPORT
EXPORT_FILE_NAME shared_EXPORTS.h
STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC)
My question is, can I use the above snippet for all my shared libraries? If so, how and where should I place it?
You can't parameter multiple libraries with only one call. You must use GenerateExportHeader for each of your shared libraries.
So you will have one call to GENERATE_EXPORT_HEADER for libA, one for libB, one for libC, each with their own parameters.

Gradle project structure organized different in IDEA

I pull a project from github, while the project use the gradle as the build tool, and it contain some sub-projects, then I tried to import the project to IDEA, this is the procedure:http://pbrd.co/1lMpmyj.
http://pasteboard.s3.amazonaws.com/images/10QfmWBp.png
As shown, the sub-project are imported as separated project, while I want to keep the fold structure, something like this:http://pbrd.co/1lMpyO6.
Is this possible?
update:
gdx/settings.gradle:
include ':gdx-core'
include ':gdx-android'
include ':gdx-web'
This is the only settings.gradle inside the project.