How to include library and header files from another one of my Meson projects? - meson-build

I have two projects on the go, one is a library, and the other wants to use some of that library.
My directory structure is:
Work/
ProjectA/
src/
include/
build/
ProjectB/
src/
build/
Assume both projects are built with meson-build, and projectA is the library.
1- How do I get ProjectB to see the include files of ProjectA?
2- How do I link the .lib file of projectA? (which is currently in the build folder)
When I try to create a dependency using relative paths, I cant find the thing that gets the .lib file?
I am only able to get the header files using:
a_dep = declare_dependency(include_directories : include_directories('../../ProjectA/src/include'))
Note I am using windows, but also will be using linux.

You should make one of the projects a subproject and extract the dependency from it:
http://mesonbuild.com/Reference-manual.html#subproject
http://mesonbuild.com/Subprojects.html
It doesn't make sense to hardcode a path to a local project, that is broken by concept.

One way to access the includes from another project is to use subprojects() and get_variable():
Project B:
project('Project B', ...)
.
.
.
projectB_inc = [ 'inc', 'src/inc' ]
inc_dirs = include_directories(projectB_inc)
.
.
.
projecB_lib = static_library('projectB',...
Access Project B from Project A:
project('Project A', ...)
.
.
.
pB = subproject('projectB')
pB_inc_dirs = rp.get_variable('inc_dirs')
.
.
.
# Use the include dirs:
pA_inc_dirs = ...
exe = executable(
'projectA_exe',
'main.c',
...
include_directories: [pA_inc_dirs, pB_inc_dirs])

Related

How to specify CMake Preset for subdirectories?

I have a big library with a lot of options that I recently converted to CMake from make, with a lot of options. I use configuration presets to have multiple profiles. The library is developed by my team, while the applications building over it are developed by other teams. The library provides common functionalities and is a must to be consumed by the apps. We were seeking to provide sane default options via presets.
Right now, I want to build a toy app over it.
I have the following directory structure where a CMakePresets.json file is located in the subdirectory (my_lib/, which is actually a git submodule).
main.cpp
CMakeLists.txt // Top-Level CMakeLists
my_lib/
------> lib.c // simplified view of the functionalities here
------> lib.h
------> CMakeLists.txt
------> CMakePresets.json
# Top level CMakeLists.txt
project(toy_app)
add_subdirectory(my_complex_lib)
set(SOURCES main.cpp)
add_executable(toy_app ${SOURCES})
target_link_libraries(toy_app my_lib)
Running cmake --list-presets at the top level won't detect sub-directories presets.
The question is how to specify the preset from the top-level invocation or even provide a default one in the CMakelists inside the library?
Trial #1
I have found the idea of default preset was rejected ( https://gitlab.kitware.com/cmake/cmake/-/issues/21417 )
Trial #2
I tried to add CMakePresets.json at the top level and included the one inside my_lib and it worked.
Running cmake --list-presets on the top level can find presets right now.
I wonder if there are other solutions?
As you indicate in your question post "Trial #2", yes, you can include other json files following the CMakePresets.json schema into CMakePresets.json files. See the docs on includes for more info. Here's an example from the docs:
{
...
"include": [
"otherThings.json",
"moreThings.json"
],
...
}
So as you found out, you can keep your main CMakePresets.json file in the subdirectory and create another one in the project's root directory that includes the subdirectory one, or you can do it the other way around: Put your main one in the project's root directory and create one that just includes it in the subdirectory.
This could be useful if you wanted to generate buildsystems for both the root directory and the subdirectory. I.e. you want your subdirectory's CMake config to be able to be used as a standalone project. In that case you might be making it a git submodule of the root project, or using a monorepo structure for the users of various parts of your project.
If you're going with a git submodule, then you couldn't put a main CMakePresets.json file in the project's root directory and include it in the submodule because the submodule repo should stand alone without knowing about what uses it as a submodule. In that case, you could put the main CMakePresets.json in the repo that gets used as a submodule, or just make two "copies" of the same CMakePresets.json file- one for each repo.
If you wanted to have a utility CMakePreset.json file with comon things used by multiple repos, you could create a repo with just that utility file and include that repo as a submodule to all your other repos and then use the CMakePresets.json's "include" mechanism to pull in those utility preset configurations into the repo's own CMakePresets.json file.

Install add_subdirectory(A) header files before building add_subdirectory(B)

I am new to cmake and I am trying to build my code on UNIX and Windows platforms. I have add_subdirectory(A) and add_subdirectory(B). If I build only add_subdirectory(A), it installs headers files to some xyz location and next when I build add_subdirectory(B), it uses headers files from previously installed xyz location. But when I try to build both add_subdirectory(A) and add_subdirectory(B) together, it fails with missing header files from xyz location, as they are not installed. So my question is, is there a way that I can tell cmake to build and install add_subdirectory(A) and then start building add_subdirectory(B).
I tried to look online but no luck.
My master CMakeLists.txt:
add_subdirectory(TradeFlowCommonFrameworkLib/cpp/src)
add_subdirectory(TradeFlowCommonDataLib/cpp/src)
install(EXPORT Findfotmc DESTINATION ${INSTALL_FOTMC}/cmake)
----------------------------------------------------------------
Adding subdirectories does not specify dependancies between them. You have to explicitly link your second executable/library to your first library.
In the sub CMakeLists of your B project (TradeFlowCommonDataLib/cpp/src) you have to add something like this :
target_link_libraries(B A)

How can I include a header-only library with CMake?

How can I add a header-only library outside the directory?
Previously I was using add_subdirectory(HEADERLIBRARY) only when the directory HEADERLIBRARY was inside the project directory. However, now I want to use the library for multiple projects, so I made a directory like this:
OUT
|----HEADERLIBRARY // of course contains CMakeLists.txt
|
|----project1
|----project2
|...
Is there a way to get the same effect as when I use add_subdirectory?
EDIT : HEADERLIBRARY = https://github.com/taocpp/PEGTL/blob/master/doc/Installing-and-Using.md#add_subdirectory
Yes, you still just use add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]).
Because source_dir is not within the source directory tree of the top-level project you have to specify the [binary_dir] folder that is going to be used. By default binary_dir is the same as source_dir within the binary directory tree and it is handled automatically.

Prefix all sources with src/ in Meson

Relative to my project root where meson.build is located, all of my source files are under src/.
Is it possible to specify these source files in meson.build in a way that wouldn't force me to prefix them all with src/, given that that's somewhat redundant?
Prefixing source files shouldn't be needed because meson provides special function: files() which generates file array object that "remembers" subdirectory. For example, in the root meson.build you can have:
subdir('src')
subdir('src_more')
exe = executable('test', sources)
In src/meson.build:
sources = files('a1.c', 'a2.c')
And in src_more/meson.build:
sources += files('b1.c', 'b2.c')
You really should put a meson.build file in src/ and create the list there.
You can actually "build" an array of files using foreach statement:
raw_sources = [
'foo.cpp',
'foomanager.cpp',
'foofactory.cpp'
]
sources = []
foreach file : raw_sources
full_path = join_paths('src', file)
sources += files(full_path)
endforeach
And now sources contains files with the desired prefix.

catkin / ROS: How-to specify include path correctly when using submodules

I am building a project using ROS and thus, catkin_make to build my ROS nodes and libraries.
The problem I'm facing is:
I am using a git submodule in one package (package A) (and thus, I have a hierarchical include folder structure) and I have difficulties referencing a header file within that submodule.
In order to build the package B, which is dependent on package A, I have added the INCLUDE_DIRS statement to the catkin_package command in package A:
catkin_package(
INCLUDE_DIRS my-submodule/include
...
)
The content of that directory is:
my-submodule/my-header.h
(I have put the header files under a folder, named after the submodule, as many tutorials stated that within ROS you should use this convention).
The include statement in a file from package-B reads like this:
...
#include <my-submodule/my-header.h>
...
This works fine - package B is being built (as I am using one combined workspace to build this).
But: When I switch to the target system, where I only install package A, and then try to build package B (on that target system), it does not build because the include paths are not setup correctly.
The INSTALL statement for package A looks like this
install(DIRECTORY my-submodule/include
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
This is mainly, because the installed folder structure on the target system looks like this:
.../ros/include/my-package-A/include/my-submodule/my-header.h
So, the install process actually puts that submodule's include-path under the package-A-include path (which is a different path structure compared to when I build the packages directly in one combined workspace).
And the CFLAGS for compilation only set the include directory to the folder:
.../ros/include
And thus, breaking my include statement in my package-B file:
#include <my-submodule/my-header.h>
Do you have any idea how to solve this?
I am sure there are more people than me, trying to reference header files from a submodule within a package.
Assuming you have a file my-submodule/include/my-submodule/my-header.h inside your package A, then two small changes to your install() statement should fix this:
install(DIRECTORY my-submodule/include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
First, add a slash to the path (.../include/ instead of .../include), which causes the contents of the include folder to be installed instead of the include folder itself (Otherwise you'll end up with ../ros/install/include/include/my-submodule/my-header.h)
Secondly, use ${CATKIN_GLOBAL_INCLUDE_DESTINATION} (which points to .../ros/install/include/) instead of ${CATKIN_PACKAGE_INCLUDE_DESTINATION} (which points to .../ros/install/my-package-A/include/) as destination.
The alternative would be to fix catkin, as
catkin_package(
INCLUDE_DIRS my-submodule/include
...
)
should theoretically already export my-submodule/include, so you can pick it up in package B with
find_package(catkin REQUIRED DEPENDS my-package-A)
catkin_package(
CATKIN_DEPENDS my-package-A
)
include_directories(${catkin_INCLUDE_DIRS})
Unfortunately, for some reason this is explicitely not possible when using catkin config --install. See https://answers.ros.org/question/335846/install_dirs-not-working-as-expected-when-using-install/.