I'm trying to figure out how to switch to CMake to build and test my libraries. I have some experience with this as I've made such files on sort of an experimental/prototype basis. However it's been some time since I messed with this so a forgot a lot. Now I'm getting serious so I have some questions. I've looked over the official CMake documentation. It seems complete but some stuff is not well explained. I've spent some time studying https://github.com/boostorg/cmake at I'm beginning to see what I have to do. Never-the-less, I still have a few questions: 1) The first lines show mkdir __build cd __build cmake .. cmake --build . Does this presume that one starts from the library directory? Does this syntax work for out of source tree builds? That is, would the following work? mkdir /temp/__build cd /temp/__build cmake .. cmake --build . (very confusing usage of leading __) ahhhh - I see a problem. I'm thinking of starting from within the directory of a particular library. I'm presuming "modular boost". Is this supported? 2) BOOST_INCLUDE_LIBRARY I would like my CMakeLists.txt file to explicitly list the direct antecedent libraries (dependencies - bad word usage). So I'd expect to see something like add_directory(../filesystem) add_directory(../regex) ... So I could just cd to .../libs/serialization cmake --build and have it build the antecedent if and only if required. 3) CMAKE_INSTALL_INCLUDEDIR I would prefer not to "install" (copy) the include files but just use the ones from their original locations. 4) BUILD_TESTING I would prefer to have my library source to look like: ... libs/serialization CMakeLists.txt // includes add_directory for subdirectorys build, test, example, profile and ... // includes add_directory for antecedent libraries like add_directory(../libs/filesystem) include // directory with include files for users of serialization library build(or src) // source files for library build CMakeLists.txt // to build library test CMakeLists.txt example CMakeLists.txt profile CMakeLists.txt Maybe the add_directory would be conditioned on a CMAKE variable. So if I invoke CMake --build test_polymorphic_binary_archive It would recursively (re)build everything necessary and nothing not necessary If I didn't specify a list of targets, it would recursively (re)build everything that needs (re)building. This seems totally reasonable and natural to me - it work like make - but better. It would dovetail with efforts to "modularize" boost. Users would only have to download libraries they actually use - if that's what they want. I realized I've glossed over a couple of details, in particular recursive inclusion of header files and likely some other stuff. I've also experimented with CMake enough to have a feeling that what I want to do is not possible. And this is the short version of what I'd like to do. Any thoughts on this?
> mkdir __build > cd __build > cmake .. > cmake --build . > > Does this presume that one starts from the library directory? This assumes to start from inside the top-level boost folder. > Does this syntax work for out of source tree builds? That is, would > the following work? > > mkdir /temp/__build > cd /temp/__build > cmake .. > cmake --build . Almost. The first CMake invocation needs the path to the Boost root, then this works. > (very confusing usage of leading __) The name "build" is already taken for the library folder as it contains e.g. the Jamfiles. Using a (very likely) new folder allows to do `rm -r __build` to start clean > ahhhh - I see a problem. I'm thinking of starting from within the > directory of a particular library. I'm presuming "modular boost". Is > this supported? This does not work out of the box but needs a CMakeLists.txt especially tailored for that which is a bit more involved. "Modular boost" refers to B2 IIRC so this is orthogonal. > 2) BOOST_INCLUDE_LIBRARY > > I would like my CMakeLists.txt file to explicitly list the direct > antecedent libraries (dependencies - bad word usage). So I'd expect > to see something like No, in CMake you specify your direct dependencies with `target_link_libraries`. The top-level Boost build (the CMake machinery added by Peter) has logic to add the required subdirectories. You only need to list each `Boost::foo` target on a separate line. See e.g.: https://github.com/boostorg/variant2/blob/develop/CMakeLists.txt#L15C1-L20 > add_directory(../filesystem) > add_directory(../regex) This can and needs to be done to test whether you can use your library itself with `add_subdirecory` which is an extra test, see e.g. https://github.com/boostorg/variant2/blob/develop/test/cmake_subdir_test/CMakeLists.txt > So I could just > cd to .../libs/serialization > cmake --build > > and have it build the antecedent if and only if required. A bit different: - cd to new build folder - cmake-DBOOST_INCLUDE_LIBRARY=serialization - cmake --build BOOST_INCLUDE_LIBRARY is basically the/our CMake way of "b2 --with-foo" > 3) CMAKE_INSTALL_INCLUDEDIR > > I would prefer not to "install" (copy) the include files but just use > the ones from their original locations. That variable is only used for installation. Nothing is copied for the build > > 4) BUILD_TESTING > > I would prefer to have my library source to look like: > > ... libs/serialization > CMakeLists.txt > // includes add_directory for subdirectorys build, test, example, > profile and ... > // includes add_directory for antecedent libraries like > add_directory(../libs/filesystem) > include // directory with include files for users of serialization > library > build(or src) // source files for library build > CMakeLists.txt // to build library > test > CMakeLists.txt > example > CMakeLists.txt > profile > CMakeLists.txt > > Maybe the add_directory would be conditioned on a CMAKE variable. You can: See https://github.com/boostorg/variant2/blob/f9bdafd3ca0f5025012f60a405b559888513a9be/CMakeLists.txt#L33-L37 Also already done for your root CML > So if I invoke > > CMake --build test_polymorphic_binary_archive > > It would recursively (re)build everything necessary and nothing not > necessary This requires `-DBUILD_TESTING=ON` but otherwise it will work. However your targets should be prefixed like "boost_serialization_test_polymorphic_binary_archive" > > If I didn't specify a list of targets, it would recursively (re)build > everything that needs (re)building. Yes > in particular recursive inclusion of header files and likely some > other stuff. Yes this is done > I've also experimented with CMake enough to have a feeling that what I > want to do is not possible. And this is the short version of what I'd > like to do. See above: With a bit care it is possible. Take some of Peters libraries as a starting point. From what I can only the CMLt in your test folder is missing. boost_test_jamfile can convert most tests in the jamfile to CMake. It requires some restrictions though like plain "run foo.cpp ;" and "compile bar.cpp ;" lines.
On 6/11/24 1:20 AM, Alexander Grund via Boost wrote: > "Modular boost" refers > to B2 IIRC so this is orthogonal. A mistake in my view. CMake for boost should support "modularization". > >> 2) BOOST_INCLUDE_LIBRARY >> >> I would like my CMakeLists.txt file to explicitly list the direct >> antecedent libraries (dependencies - bad word usage). So I'd expect >> to see something like > No, in CMake you specify your direct dependencies with > `target_link_libraries`. The CMakeLists.txt in each The top-level Boost build (the CMake machinery > added by Peter) has logic to add the required subdirectories. > You only need to list each `Boost::foo` target on a separate line. See > e.g.: > https://github.com/boostorg/variant2/blob/develop/CMakeLists.txt#L15C1-L20 > >> add_(sub?)directory(../filesystem) >> add_(sub?)directory(../regex) The CMakeLists.txt in each (sub?)directory would contain the "target_link_libraries" if required. It's possible that some library might might be dependent on something besides another library - e.g. a test data generator executable. So using add_subdirectory would be more general. > > This can and needs to be done to test whether you can use your library > itself with `add_subdirecory` which is an extra test, see e.g. > https://github.com/boostorg/variant2/blob/develop/test/cmake_subdir_test/CMakeLists.txt > > >> So I could just >> cd to .../libs/serialization >> cmake --build >> >> and have it build the antecedent if and only if required. > A bit different: > - cd to new build folder > - cmake-DBOOST_INCLUDE_LIBRARY=serialization > - cmake --build > > BOOST_INCLUDE_LIBRARY is basically the/our CMake way of "b2 --with-foo" Right. and it's only required because we're presuming that the invocation is from boost rather than from within the library directory itself. Again - use this project to support the "modularization" of Boost. > >> 3) CMAKE_INSTALL_INCLUDEDIR >> >> I would prefer not to "install" (copy) the include files but just use >> the ones from their original locations. > That variable is only used for installation. Nothing is copied for the > build >> >> 4) BUILD_TESTING >> >> I would prefer to have my library source tree to look like: >> >> ... libs/serialization >> CMakeLists.txt >> // includes add_directory for subdirectorys build, test, example, >> profile and ... >> // includes add_directory for antecedent libraries like >> add_directory(../libs/filesystem) >> include // directory with include files for users of serialization >> library >> build(or src) // source files for library build >> CMakeLists.txt // to build library >> test >> CMakeLists.txt >> example >> CMakeLists.txt >> profile >> CMakeLists.txt >> >> Maybe the add_directory would be conditioned on a CMAKE variable. > You can: > See > https://github.com/boostorg/variant2/blob/f9bdafd3ca0f5025012f60a405b559888513a9be/CMakeLists.txt#L33-L37 > Also already done for your root CML >> So if I invoke >> >> CMake --build test_polymorphic_binary_archive >> >> It would recursively (re)build everything necessary and nothing not >> necessary > This requires `-DBUILD_TESTING=ON` but otherwise it will work. Good> However your targets should be prefixed like > "boost_serialization_test_polymorphic_binary_archive" why? >> >> If I didn't specify a list of targets, it would recursively (re)build >> everything that needs (re)building. > Yes >> in particular recursive inclusion of header files and likely some >> other stuff. > Yes this is done >> I've also experimented with CMake enough to have a feeling that what I >> want to do is not possible. And this is the short version of what I'd >> like to do. > See above: With a bit care it is possible. Take some of Peters libraries > as a starting point. > From what I can only the CMLt in your test folder is missing. A long time ago I put CMake stuff into the directory libs/serialization/cmake in order to avoid crossing swords with the eventual developers of the Boost CMake implementation - which has turned out be peter. It's worked out OK. Its not hard to move the stuff in that directory into the future test/CMakeLists.txt when it seems advantageous. > > _______________________________________________ > Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On Tue, Jun 11, 2024 at 1:36 PM Robert Ramey via Boost
On 6/11/24 1:20 AM, Alexander Grund via Boost wrote:
"Modular boost" refers to B2 IIRC so this is orthogonal.
A mistake in my view. CMake for boost should support "modularization".
It was my expectation that it would apply to cmake, or any other build system that may come in the future. Although I wouldn't be doing that work. But I know of some people who want to contribute such changes. -- -- René Ferdinand Rivera Morell -- Don't Assume Anything -- No Supone Nada -- Robot Dreams - http://robot-dreams.net
A mistake in my view. CMake for boost should support "modularization". It does. As long as your library doesn't (transitively) depend on a specific boost library you don't need to have it present. Or what do you refer to as "modularization"? The CMakeLists.txt in each (sub?)directory would contain the "target_link_libraries" if required. It's possible that some library might might be dependent on something besides another library - e.g. a test data generator executable. So using add_subdirectory would be more general. The top-level CML uses `add_subdirectory` for each Boost library required. Individual Library can use `add_subdirectory` for each of its own subfolders such as tests and examples. This call alone does not declare a dependency of any kind. It only brings the contents/targets of the subdirectory "into view". You still need to `target_link_libraries(your_lib PRIVATE|PUBLIC your_dependency)` to declare the dependency relationship. `add_subdirectory` does not do that so it is not "more general" If you provide a specific example we can help you there. E.g. if you need some generated input data for a test you do in CMake:
- Add the generator as an (executable) target - Declare a rule how to transform input to output data using the target - Declare a dependency of your test onto the output data (`add_dependencies`) Note that this is the same for Boost or any other CMake project.
Right. and it's only required because we're presuming that the invocation is from boost rather than from within the library directory itself. Again - use this project to support the "modularization" of Boost.
Again what is "modularization" in this context? Coming back to your question of how to invoke CMake with your library directory as the source: `if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)` can be used to detect this case You are then responsible for `add_subdirectory` all your dependencies (even transitive ones) manually. If they change you need to update your code. A nifty variant used by other libraries to add all dependencies using the existing logic in Boost.CMake is: set(BOOST_INCLUDE_LIBRARIES serialization) set(BOOST_EXCLUDE_LIBRARIES serialization) add_subdirectory(../.. _deps/boost EXCLUDE_FROM_ALL) or if(NOT BOOST_SUPERPROJECT_VERSION) set(BOOST_INCLUDE_LIBRARIES serialization) add_subdirectory(../.. _deps/boost EXCLUDE_FROM_ALL) return() endif() Or similar to basically redirect to the Boost super-project This basically calls the root CML. Untested though
Robert Ramey wrote:
1) The first lines show
mkdir __build cd __build cmake .. cmake --build .
Does this presume that one starts from the library directory? Does this syntax work for out of source tree builds? That is, would the following work?
mkdir /temp/__build cd /temp/__build cmake .. cmake --build .
You can put your binary directory wherever you like, but then you need to pass the correct source directory at the `cmake ..` point, because `..` is no longer the source directory.
2) BOOST_INCLUDE_LIBRARY
I would like my CMakeLists.txt file to explicitly list the direct antecedent libraries (dependencies - bad word usage). So I'd expect to see something like
add_directory(../filesystem) add_directory(../regex)
This can only work if your library is the root project. If it's not, you can't just add_subdirectory your dependencies, because the root project may use more than one Boost library. If each of these tries to add_subdirectory other Boost libraries, there will be duplication and things are not going to work. In fact things are not going to work even in your case (if all libraries did what you're trying to do) because `filesystem` may perform `add_subdirectory(regex)` and then your own `add_subdirectory(regex)` will fail. As a general rule, subprojects should never use add_subdirectory for their dependencies. The intended use of BOOST_INCLUDE_LIBRARIES is from the Boost root: mkdir __build__ && cd __build__ cmake -DBOOST_INCLUDE_LIBRARIES=serialization .. This tells the superproject to perform the necessary add_subdirectory calls for Serialization and its dependencies.
participants (4)
-
Alexander Grund
-
Peter Dimov
-
René Ferdinand Rivera Morell
-
Robert Ramey