
ср, 16 апр. 2025 г. в 14:14, Peter Dimov via Boost <boost@lists.boost.org>:
Listing dependencies in project requirements is a cheat and generally not what one wants in any non-trivial Jamfile (same goes for build.jam). In CMake parlance, which is what more people speak today than b2, this corresponds to using link_libraries instead of target_link_libraries.
I think that it may be useful to explain what the "modular changes" actually do. First, why build.jam? That file is a project jamfile that can act as both the root of the project tree and not the root. It in principle allows the project to be built both as part of the Boost superproject and without it. In addition, Boost superproject checks if that file exists to determine if that particular library has been modularised or not. Inside that file we can see something like this: constant boost_dependencies : /boost/assert//boost_assert /boost/config//boost_config /boost/core//boost_core /boost/static_assert//boost_static_assert /boost/system//boost_system ; This constant is not actually necessary, but it is very helpful to **third party tools* that attempt to determine interdependencies between Boost libraries. For that reason it is better to keep each dependency on a separate line. These dependencies should be the direct dependencies of the **libraries** from the project, including header-only libraries. If you need extra dependencies for tests, examples, benchmarks, etc. put them somewhere else. Next we have the declaration of the project and "public" targets, which are intended for other projects to depend on. E.g. project /boost/mp11 ; The project declaration should be self-explanatory. Note that it explicitly positions itself as /boost/mp11, because otherwise it would have become /boost/libs/mp11 as that's the path from the Boost superproject root. alias boost_mp11 : : : : <include>include <library>$(boost_dependencies) ; This is a target for a header-only library. We used to not need those, because effectively **every library implicitly depends on every other library's headers via /boost/headers target**. But in a modularised setup there is no superproject, so targets should be explicit about their dependencies, including header-only dependencies. The actual utility that the target provides is having <include>include in its usage requirements and also in forwarding its dependencies to its consumer (target that depends on it). I would actually amend this to be alias boost_mp11 : : : : <include>include <library>$(boost_dependencies)//<warnings-as-errors>off ; This makes sure that warnings emitted when building dependencies do not fail your builds. Some projects had a problem when they had something akin to lib A : $(srcs) : <library>B/<warnings-as-errors>off <library>B ; Such a setup may or may not cause the build to fail depending on whether b2 will first update B/<warnings-as-errors>off or B. I recommend to simply always add /<warnings-as-errors>off to targets from other projects. Let's look now at a target for a compiled library. We usually declare those in a build subproject. Hence in build.jam we put an alias to that target: alias boost_json : build//boost_json ; And in the build subproject we add things similarly to the header-only library. Here's a (simplified) declaration from Boost.JSON: lib boost_json : src.cpp : <include>../include <use>$(boost_dependencies)/<warnings-as-errors>off <link>shared:<define>BOOST_JSON_DYN_LINK=1 <link>static:<define>BOOST_JSON_STATIC_LINK=1 : : <use>$(boost_dependencies)/<warnings-as-errors>off <library>/boost/container//boost_container/<warnings-as-errors>off ; The target puts its dependencies both into requirements and usage requirements. I used <use> feature, because most of the dependencies are actually header-only, and they only add usage requirements. The one link dependency is repeated with <library>. Finally call-if : boost-library json : install boost_json ; calls boost-install boost_json if part of the superproject.