Earlier quoted context omitted.
Repeatability definitely does not mean some long time frame, it's over any time frame. Short time frames have the largest impact, because it allows you to use a shared cache for build products. One big chroot around your whole build system isn't enough, you can run into nondeterminism problems due to relative ordering of different build steps during execution. This is why it's nice that the new build systems make eac…
Cool, didn't know that. I like the idea of breaking things up into steps. So you're saying this takes care of race conditions in the build where things may happen out of order even if you have a fixed environment?
Everything You Never Wanted to Know About CMake
81–90 of 91 posts
Re: Everything You Never Wanted to Know About CMake
#82CMake is awful, and the fact that the C++ community seems to be settling around it will be a massive disadvantage in the long run. Why do you think so many WASM examples use Rust? It's because Cargo is a sane build system that makes cross-compilation easy. Issues with CMake: - The DSL is not very good. It needs proper functions, for one. - Non-hermetic builds (also mentioned in this thread) - No ability to easily que…
Cargo (and Rust tooling in general) still have an annoying design flaw in my mind -> they all pretend that system package managers don’t exist. Admittedly with rust not having an ABI you’d still have to rebuild all the packages whenever the compiler was updated, but I’d like to see rustup support toolchains installed to the system.
Re: Everything You Never Wanted to Know About CMake
#83CMake is awful, and the fact that the C++ community seems to be settling around it will be a massive disadvantage in the long run. Why do you think so many WASM examples use Rust? It's because Cargo is a sane build system that makes cross-compilation easy. Issues with CMake: - The DSL is not very good. It needs proper functions, for one. - Non-hermetic builds (also mentioned in this thread) - No ability to easily que…
What do you mean by this exactly? Perhaps you are thinking of the old include_directories() function rather than the now-recommended target_include_directories()? This attaches one or more include directories to each target rather than having a single global list of all include directories. You can indeed have a target for each directory of your source files (this is also recommended practice).
This even works for imported targets. These are targets that represent existing prebuilt libraries on your system, and they are increasing returned by find_package in place of the old pair of ${FOO_LIBRARIES} and ${FOO_INCLUDE_DIRS}. Internally they call target_include_directories() with PUBLIC (or INTERFACE) modifier that means that those directories will be inherited by other targets that link against this one.
Re: Everything You Never Wanted to Know About CMake
#84Earlier quoted context omitted.
Cargo (and Rust tooling in general) still have an annoying design flaw in my mind -> they all pretend that system package managers don’t exist. Admittedly with rust not having an ABI you’d still have to rebuild all the packages whenever the compiler was updated, but I’d like to see rustup support toolchains installed to the system.
This is a rustup issue, not a Cargo issue. You can use a system-installed Cargo/rustc just fine.
Re: Everything You Never Wanted to Know About CMake
#85CMake is awful, and the fact that the C++ community seems to be settling around it will be a massive disadvantage in the long run. Why do you think so many WASM examples use Rust? It's because Cargo is a sane build system that makes cross-compilation easy. Issues with CMake: - The DSL is not very good. It needs proper functions, for one. - Non-hermetic builds (also mentioned in this thread) - No ability to easily que…
- Headers are not modelled properly (they should be a dictionary of paths -> paths, not a list of include directories) What do you mean by this exactly? Perhaps you are thinking of the old include_directories() function rather than the now-recommended target_include_directories()? This attaches one or more include directories to each target rather than having a single global list of all include directories. You can i…
So your code might look like this:
#include
The project folder structure might look like this: .
└── src
└── include
└── foo
└── bar.hpp
And the mapping might look like this: {
"foo/bar.hpp": "./src/include/foo/bar.hpp"
}
This enables the build system to know exactly which headers are meant to be exposed by a library to its dependees. The build system can then tell you:(1) Exactly where a header comes from
(2) Exactly which headers a library exports
(3) If two libraries will collide in terms of headers
(4) If someone is trying to use a header that is not explicitly exported by a library.
(5) If some is accessing a header in the wrong way (e.g. abusing the layout of source-files and not using the correct include-path)
This approach scales very well. Constructing the mapping can be done via globs (globs work properly in Buck), so most projects just do:
exported_headers = subdir_glob([
('include', '**/*.hpp'),
])
Additionally, the RHS of the mapping might be another build rule, thus supporting generated headers in hermetic builds.Re: Everything You Never Wanted to Know About CMake
#86CMake is awful, and the fact that the C++ community seems to be settling around it will be a massive disadvantage in the long run. Why do you think so many WASM examples use Rust? It's because Cargo is a sane build system that makes cross-compilation easy. Issues with CMake: - The DSL is not very good. It needs proper functions, for one. - Non-hermetic builds (also mentioned in this thread) - No ability to easily que…
Re: Everything You Never Wanted to Know About CMake
#87Is there a good way to debug CMake build rules (especially in the presence of add_custom_command and friends)? I've got a case which builds differently in Make vs Visual Studio---in VS, dependencies get messed up and some files don't even get built at all (and then the build fails later on because those files are missing). I can't for the life of me figure out how to debug this, it's absolutely infuriating.
- message(STATUS ...) or message(FATAL_ERROR ...) for printing stuff out at configure time, e.g.
message(STATUS "libcurl found: ${HAVE_LIBCURL}")
- cmake -E echo for printing stuff out at build time, e.g. add_custom_command(TARGET lorenz POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "lorenz command line:"
COMMAND ${CMAKE_COMMAND} -E echo '$' ${LORENZ_ARGS}
VERBATIM)
- diagnostic-level MSBuild output for dependency issues - you can configure this in Visual Studio, Tools, Options, Projects and Solutions, I think (it's around there somewhere). You might not expect much from MSBuild debug output, considering how annoying the rest of it is, but it's actually extremely comprehensive, and I've found it useful for figuring out even rather weird stuff. There's quite a lot of it, though, so get a cup of teaA passing familiarity with the MSBuild syntax might be helpful, but I've managed to do mostly without.
Re: Everything You Never Wanted to Know About CMake
#88Earlier quoted context omitted.
This idea of having a "front-end" build system and a "back-end" build system is a bit of a throw-back. It is better to integrate the two for better optimization and configuration management.
Better integrate may be, but not merge into one. Since super optimized build systems also increase complexity of their usage. So the idea is to have user friendly front end, which produces complex input for very fast backend. Ninja view their build idea as "assembly like". While assembly surely allows you producing very fast results, it's not easy to use at all, if you are using it directly.
That's not correct. Complexity arises from the inability of expressing what you want and lack of abstractions over platform details.
Ninja for instance is to primitive to be productive and does not have any understanding of C++.
Buildsystems like buck allow you to express things in a declarative manner eg.:
cxx_library(
name = 'foo',
srcs = glob(['src/**/*.c']),
exported_headers = glob(['*.h'])
)
cxx_binary(
name = 'app',
srcs = ['main.c'],
deps = [':foo', ':bar']
)
buck implements sophisticated (disk & network) caching, optimization and scheduling strategies to make things fast.Furthermore it will use services like watchman (if available) to precompute what things need building if you change some files for fast incremental builds.
Lastly it will strip and sort symbols in your binary to make sure the hash of your binary is always the same for the same set of inputs.
All this complexity is handled for you and all you need to do to run your executable is
buck run :appRe: Everything You Never Wanted to Know About CMake
#89Earlier quoted context omitted.
Better integrate may be, but not merge into one. Since super optimized build systems also increase complexity of their usage. So the idea is to have user friendly front end, which produces complex input for very fast backend. Ninja view their build idea as "assembly like". While assembly surely allows you producing very fast results, it's not easy to use at all, if you are using it directly.
> Since super optimized build systems also increase complexity of their usage. That's not correct. Complexity arises from the inability of expressing what you want and lack of abstractions over platform details. Ninja for instance is to primitive to be productive and does not have any understanding of C++. Buildsystems like buck allow you to express things in a declarative manner eg.: cxx_library( name = 'foo', srcs…
So not sure what you argument is about. It's like saying that assembly has no high end abstractions. Sure, it doesn't. It in itself is not an argument against splitting the build into several passes.
That said, Buck looks like an interesting build system.
In general, to have proper handling of librarires and etc. the language itself should support the notion of modules, like Rust does. Then you can implement sane tools (cargo). C++ is still crippled in this regard. Though there are some ideas how to improve it:
https://medium.com/@dmitrygz/brief-article-on-c-modules-f582...
Re: Everything You Never Wanted to Know About CMake
#90Earlier quoted context omitted.
- Headers are not modelled properly (they should be a dictionary of paths -> paths, not a list of include directories) What do you mean by this exactly? Perhaps you are thinking of the old include_directories() function rather than the now-recommended target_include_directories()? This attaches one or more include directories to each target rather than having a single global list of all include directories. You can i…
The idea (only implemented in Buck AFAIK) is to model not a list of include directories, but a mapping from the path specified in your "#include" to the actual file on disk. So your code might look like this: #include The project folder structure might look like this: . └── src └── include └── foo └── bar.hpp And the mapping might look like this: { "foo/bar.hpp": "./src/include/foo/bar.hpp" } This enables the build s…
I've used generated header files (protobuf) with CMake and they work fine. Although I prefer to create them at configure time rather than build time, even though that's philosophically incorrect, just because that way I can see them in the generated IDE projects and they don't break autocomplete.