(...cut...)
> Thanks for your explanation! > > I'd add a few points from myself. > > When a library is linked into another target through > target_link_libraries(), it can be either PUBLIC, PRIVATE, or INTERFACE: > > - PRIVATE means that the dependency will be entirely used in the following > target (both include directories and link flags are copied to the new > target). For example, when APR is linked into libsvn_something as a PRIVATE > dependency, this library gains access to APR functions and headers. > However, it doesn't spread to the target depending on our libsvn_something > (like our main svn.exe). Actually, there is an exception that copies link > flags in a static build, but it's a different story. I mean it's not the > main point. > > As for another, more real world example, libsvn_fs_fs is a completely > internal library without any public APIs. I mean those used in our > programs. They usually only link against let's say libsvn_fs (in the most > abstract scenario). libsvn_fs does link libsvn_fs_fs, but doesn't use it in > its public api. This all means that if it's linked as a PRIVATE dependency, > no includes of libsvn_fs_fs will be available for libsvn_fs. (let's imagine > they would be in different directories for clarity) > > Also, answering Branko's question, optimising include directories might be > helpful to explicitly control whether the dependency is used or not. For > example, our libsvn_diff doesn't use apr util. So if someone would call apr > util api on accident, we will notice this because the build would no longer > be passing. > > > Yup. And libsvn_diff doesn't link apr-util, build.conf says so and all > our generated target dependencies derive from that. However: > > trunk/subversion/libsvn_diff$ grep svn_utf.h *.c > deprecated.c:#include "svn_utf.h" > diff_file.c:#include "svn_utf.h" > diff_memory.c:#include "svn_utf.h" > parse-diff.c:#include "svn_utf.h" > util.c:#include "svn_utf.h" > > > So it needs -I/some/path/to/apr-util/include/apr-1 but it doesn't need > libaprutil.so (or .a or .lib or .dylib etc.). This is exactly why I > didn't want to change the dependency lists in build.conf. > > > - INTERFACE linkage only affects the targets dependent on the library. It > does literally nothing on the target itself, but spreads onto dependent > libraries. > > - PUBLIC dependencies are a sort of combination of those both types. For > example, apr is the best example of a PUBLIC dependency, because it is used > in the library itself and required in the public header files (for example > libsvn_client exports svn_client.h, which includes apr.h. Meaning that > apr.h is a part of libsvn_client public api). > > Right now libsvn_subr has the following dependencies: > > target_link_libraries(libsvn_subr PRIVATE > external-aprutil > external-apr > external-xml > external-zlib > external-sqlite > external-intl > external-lz4 > external-utf8proc > ) > > I think it should be like: > > target_link_libraries(libsvn_subr PUBLIC > external-aprutil > external-apr > ) > target_link_libraries(libsvn_subr PRIVATE > external-xml > external-zlib > external-sqlite > external-intl > external-lz4 > external-utf8proc > ) > > Initially, I thought that all dependencies are explicitly listed in the > build.conf, so I didn't take the effort that time. Should I rework the > generator to produce such targets? > > > The link dependencies are in build.conf. The public/private distinction > isn't (since that doesn't affect linking a target). The autotools build, > based on build.conf, and also the generated Visual Studio files, make all > include paths available to all targets. I'd have to double-check, but I > think the exceptions to this rule are the (Swig) bindings, which get some > extra help. > > > This would be the cmake-ish way to fix this problem. And just an > improvement. > > > Well, I'd hate to add an explicit flag in build.conf just to distinguish > between public and private dependencies. Having said that, we only have > issues with external-aprutil (and, to some degree, external-apr, since they > should be treated in the same way). So how about adding this knowledge > directly into build/generator/gen_cmake.py? It is, after all, its job is > to generate correct dependencies for cmake. It already adds the "external-" > prefix to some of the library names; it may as well put apr and apr-util > into the PUBLIC space. > > The attached patch appears to work for me. > +1, except for several minor notices. 1. What is the actual purpose of a frozenset PUBLIC_LIB_DEPENDS? I mean just above we are performing exactly the same check, but using an '[...]' construction and I think it's not worthed to optimise performance of a build script and we use it just once. So why not do this instead?: @@ -170,9 +175,14 @@ # TODO: pass else: - libs.append("external-" + dep.name) + dep_name = "external-" + dep.name + if (dep_name in ["external-apr", "external-aprutil"] + and not isinstance(target, gen_base.TargetExe)): + public_libs.append(dep_name) + else: + private_libs.append(dep_name) else: - libs.append(dep.name) + private_libs.append(dep.name) elif isinstance(dep, gen_base.ObjectFile): for source in self.graph.get_sources(gen_base.DT_OBJECT, dep, gen_base.SourceFile): 2. It's maybe just an enhancement for the future, if we decide to, for example, export a cmake config, but it might be better to treat some libsvn dependencies as PUBLIC. For example, I'm sure most of our headers include something from libsvn_subr, so technically it's a public dependency for them. This most probably would not change anything since they have the same include directory, but still, in theory it could. -- Timofei Zhakov