in-tree include directory with bazel custom toolchain - c++

Is it possible to configure a Bazel custom toolchain to include directories in the repository?
Assume that I have following in the root of my repository:
sysroots/armhf/include/myheader.h
sysroots/amd64/include/myheader.h
myproject1/component.cpp
myproject2/component.cpp
I'd like to configure toolchain such that when I run bazel build --config armhf, component.cpp files including myheader.h would get the header from sysroot/armhf/include directory, and when I run bazel build --config amd64, file from corresponding sysroot/amd64 directory were used.
This needs to work without having to modify projects containing component.cpp files.
Essentially I would like to check in platform specific headers and binaries in the source repository along with the code.

If you haven't found it yet, you need to write C++ toolchains. The Configure C++ Toolchains Tutorial is a good place to start, if you have more specific questions they'll get better answers as separate questions. I'm going to answer specifically about the paths here.
Most of the paths are just normal paths relative to the execution root. That typically means external/<repo_name>/<package>/<name> for paths in external repositories, or just <package>/<name> for paths in the main repository. bazel-toolchain's pkg_path_from_label function implements this logic, for example. In your case, that's sysroots/armhf/include for the first path.
cxx_builtin_include_directories is special. Paths there have unique syntaxes to generate absolute paths. The relevant one looks like "%package(#your_toolchain//relative/clang/include)%", with #your_toolchain replaced with your repository's name. In your case that means something like "%package(#//sysroots/armhf)%/include/myheader.h". Depending on where the package boundary is (deepest folder with a BUILD file) more or less of that might need to be in the %package() part.
Those directives get expanded when generating compiler command lines. I'm not aware of any documentation besides the source.

Related

How to make Eclipse CDT Autotools use off source directory autogen.sh

I'm trying to configure Eclipse CDT 2019-12 to build an old project that uses autotools. There is an autogen.sh script, but it is not included in the directory which holds configure.ac and the other source files. Looking at the Eclipse Autotools user guide, that might be the reason why running 'Reconfigure project' does not use autogen.sh. but runs autoreconf.
I redefined Autotools > Configure Settings > autogen > Command to use a relative path, but that didn't help. Redefining Autotools > General > Tools Settings > autoreconf leads to an internal error (NullPointerException).
What can I do to help Eclipse find and execute the off source directory autogen.sh?
The directory containing configure.ac, and therefore where the configure script also resides and / or is created, is the root of the project's source tree by definition. In a well-formed Autotools project, there should not be any build system artifacts outside the source tree because the contents of the source tree define what gets packaged and distributed.
Moreover, it is my understanding and recollection that Eclipse relies on that in defining its logical view of an Autotools project. Eclipse goes to some trouble to try to prevent project building from accessing files outside the spaces specified in the project configuration. It does not particularly surprise me that it does not recognize an autogen.sh file outside the source tree, no matter how you try to specify its location.
First off, it would be worthwhile examining the autogen script to determine whether it's actually doing anything needful that autoreconf does not do, or if it may be intentionally omitting anything that autoreconf does. It may be that letting Eclipse use autoreconf instead of autogen.sh will work just fine.
If in fact you need Eclipse to use autogen.sh, then your best bet is probably to copy it into the source directory and update the copy appropriately for its new location.

correctly set CMake variables when adding yaml-cpp to existing project

I've added the yaml-cpp git repository as a submodule and add it to my CMake project using add_subdirectory.
Everything's fine but I have to set YAML_CPP_INCLUDE_DIR and YAML_CPP_LIBRARIES manually to use them for my own targets.
Because there is a file yaml-cpp-config.cmake (generated in the build folder) setting these variables I tried to just include it:
include("${CMAKE_BINARY_DIR}/yaml-cpp/yaml-cpp-config.cmake")
but then I get:
CMake Error at /bla/bla/build/yaml-cpp/yaml-cpp-config.cmake:11 (include):
The file
/bla/bla/aml-cpp/yaml-cpp-targets.cmake
was generated by the export() command. It may not be used as the argument
to the include() command. Use ALIAS targets instead to refer to targets by
alternative names.
I really don't understand this message. How would I provide my targets with the yaml-cpp include directories and libraries without having to set a hard coded variable?
I'm not searching for a way to correctly include() the file in case it doesn't have to be done. I'm just interested in how I should provide the desired information to my targets.
Unfortunately yaml-cpp seems to not make use of target_include_directories() which would set the include directories automatically where needed.
From description of export command:
Create a file <filename> that may be included by outside projects to import targets from the current project’s build tree.
Note to "outside" word: this is why you get the error message while trying to include the file from the same project, which issues export command.
Correct way to use yaml-cpp-config.cmake file would be building yaml-cpp outside of your project. For example, you may use ExternalProject_Add in conjunction with execute_process for build yaml-cpp as part of configuration stage of your project, see more about this approach here.
Then you may include given file to your project with find_package:
find_package(yaml-cpp PATHS <yaml-cpp-build-dir>)
Note, that yaml-cpp-config.cmake in binary directory describes build state of yaml-cpp project.
If you want to install libraries/executables from your project, you are better to install yaml-cpp, and include corresponded file from its installation directory:
find_package(yaml-cpp PATHS <yaml-cpp-install-dir>)

CMake: target_include_directories() prints an error when I try to add the source directory itself, or one of its subdirectories

I am writing a C++ library (header-only) and am using CMake to generate my (Visual Studio) project and solution files. I'm also writing a test suite, which is part of the same CMake project.
My problem occurs when I call target_include_directories() on the target that represents my header-only library, so that consumers of my library may find its header files. I get the following error message (even though generation is NOT aborted).
CMake Error in CMakeLists.txt:
Target "Fonts" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"D:/Projects/GPC/fonts/include"
which is prefixed in the source directory.
(D:/Projects/GPC/Fonts being the top-level directory of my library project. Btw the problem remains if I move my header files to the top directory.)
The offending line in my CMakeLists.txt is this (adapted for simplicity):
target_include_directories(Fonts INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
I do not understand what I'm doing wrong. Without target_include_directories(), code of consumer projects simply can't include my header files (unless in installed form, but I haven't gotten to that yet, and in any case I want to be able to use my library from its build tree, without installation.)
I feel like I'm missing something basic here; yet I've searched for hours without finding a solution or explanation.
The origin of the problem is not the target_include_directories command itself, but the attempt to install a target that has a public or interface include directory prefixed in the source path (i.e. the include directory is a subdirectory of your ${PROJECT_SOURCE_DIR}.)
While it is perfectly fine and desirable to use absolute paths when building the library from scratch, a third party library that pulls in a prebuilt version of that library will probably want to use a different include path. After all, you do not want all of your users to mirror the directory structure of your build machine, just to end up in the right include path.
CMake's packaging mechanism provides support for both of these use cases: You may pull in a library directly from the build tree (that is, check out the source, build it, and point find_package() to the directory), or from an install directory (run make INSTALL to copy built stuff to the install directory and point find_package() to that directory). The latter approach needs to be relocatable (that is, I build and install on my machine, send you the resulting directory and you will be able to use it on your machine from a different directory structure), while the former is not.
This is a very neat feature, but you have to account for it when setting up the include directories. Quoting the manual for target_include_directories:
Include directories usage requirements commonly differ between the
build-tree and the install-tree. The BUILD_INTERFACE and
INSTALL_INTERFACE generator expressions can be used to describe
separate usage requirements based on the usage location. Relative
paths are allowed within the INSTALL_INTERFACE expression and are
interpreted relative to the installation prefix. For example:
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib>
$<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib
)
The BUILD_INTERFACE and INSTALL_INTERFACE generator expressions do all the magic:
$<INSTALL_INTERFACE:...>
Content of ... when the property is exported using install(EXPORT), and empty otherwise.
$<BUILD_INTERFACE:...>
Content of ... when the property is exported using export(), or when the target is used by another target in the same buildsystem.
Expands to the empty string otherwise.

Generate Find Cmake automatically and install it for importing

Is there any way to create a FindXXX.cmake automatically where XXX is my Cmake project? I see many projects that they created their FindXXX.cmake manually but I believe it's possible to create it automatically.
And, where I should install my project on Linux?
Thanks!
Take a look at CMake's project config file mechanism (along with the CMakePackageConfigHelper module; you might also want to take a look at this wiki page).
Find scripts are most useful for locating dependencies that are not aware of CMake themselves. If on the other hand the dependency was also built using CMake, you can let CMake auto-generate a project config file for you as part of that project's build process. This config file will allow you to refer to the targets of that project from an enclosing project as if they were being built as part of the enclosing project's CMake run. This is even more powerful than using find scripts, as it allows for example distinct handling of configurations beyond the debug/optimized options available to traditional find scripts.
On Windows, projects generating config files this way will register themselves with CMake, so that depending projects building on the same machine can find them automatically without any additional configuration. If you are building on non-Windows platforms (or you are building the two libraries on different machines) you will have to place the config file in a default directory (the docs for find_package describe which directories are searched) or explicitly point CMake to the location using CMAKE_MODULE_PATH.
Modern CMake-aware libraries should always prefer this approach over traditional find scripts. A prominent example of a library that does this already is Qt5.
CMake supports templating with configure_file() command.
Standard dirs where CMake searches for FindXXX.cmake modules are listed in the documentation of find_package() command.

Add only specific subdirectory of an include path to includes

I have a project which is built using cmake.
This project is uses avr-gcc to compile the binaries and I use boost mpl for some parts of it.
As avr-gcc does not have /usr/include as a default include path but boost is installed there, I need to add it as an include path such that boost is found.
Unfortunately, adding -I/usr/include to the command line pulls in all other files and directories in /usr/include which seems to introduce collisions with the avr includes and thereby compiler errors.
My initial solution involved a softlink to /usr/include/boost in one of my user defined include directories to resolve the
#include <boost/mpl/*>
However, I thought this to be not very platform independent and decided for cmake to add the include path for boost. This again led to "-I/usr/include" being present on the compiler command.
How do I solve this in a platform agnostic manner?
A solution would be to let cmake create the link for me to get the right include directory.
However, I consider the whole symbolic link solution ugly.
Is there something better that I can do?
For example: Is there some option that adds an include path under an alias like:
-I/usr/include/boost:boost
Which would add only the boost subfolder under the name boost to be includable by the #include <boost/...> directive?
I see at least two options for you:
Where does avr-gcc include files from by default? Let's say it is /opt/avr-gcc/include for concreteness. Then what may work for you is -I/opt/avr-gcc/include -I/usr/include.
Another option is to install Boost in a different directory and use that instead of the Boost in /usr/include. For example, you might create /opt/boost and then use -I/opt/boost (or a sub-directory under that) on the command line.