Top
Best
New

Posted by randerson_112 5 hours ago

Show HN: I built a Cargo-like build tool for C/C++(github.com)
I love C and C++, but setting up projects can sometimes be a pain.

Every time I wanted to start something new I'd spend the first hour writing CMakeLists.txt, figuring out find_package, copying boilerplate from my last project, and googling why my library isn't linking. By the time the project was actually set up I'd lost all momentum.

So, I built Craft - a lightweight build and workflow tool for C and C++. Instead of writing CMake, your project configuration goes in a simple craft.toml:

  [project]
  name = "my_app"
  version = "0.1.0"
  language = "c"
  c_standard = 99

  [build]
  type = "executable"
Run craft build and Craft generates the CMakeLists.txt automatically and builds your project. Want to add dependencies? That's just a simple command:

  craft add --git https://github.com/raysan5/raylib --links raylib
  craft add --path ../my_library
  craft add sfml
Craft will clone the dependency, regenerate the CMake, and rebuild your project for you.

Other Craft features: craft init - adopt an existing C/C++ project into Craft or initialize an empty directory. craft template - save any project structure as a template to be initialized later. craft gen - generate header and source files with starter boilerplate code. craft upgrade - keeps itself up to date.

CMakeLists.extra.cmake for anything that Craft does not yet handle.

Cross platform - macOS, Linux, Windows.

It is still early (I just got it to v1.0.0) but I am excited to be able to share it and keep improving it.

Would love feedback. Please also feel free to make pull requests if you want to help with development!

77 points | 74 commentspage 2
nesarkvechnep 3 hours ago|
As long as it's for C/C++ and not C or C++, I'm skeptical.
randerson_112 2 hours ago|
Why do you say this? I respect it, I'm just curious.
flohofwoe 4 hours ago||
Heh, looks like cmake-code-generators are all the rage these days ;)

Here's my feeble attempt using Deno as base (it's extremely opinionated though and mostly for personal use in my hobby projects):

https://github.com/floooh/fibs

One interesting chicken-egg-problem I couldn't solve is how to figure out the C/C++ toolchain that's going to be used without running cmake on a 'dummy project file' first. For some toolchain/IDE combos (most notably Xcode and VStudio) cmake's toolchain detection takes a lot of time unfortunately.

apparatur 2 hours ago|
I'm intrigued by the idea of writing one's own custom build system in the same language as the target app/game; it's probably not super portable or general but cool and easy to maintain for smaller projects: https://mastodon.gamedev.place/@pjako/115782569754684469
tombert 4 hours ago||
This certainly seems less awful than the typical C building process.

What I've been doing to manage dependencies in a way that doesn't depress me much has been Nix flakes, which allows me a pretty straightforward `nix build` with the correct dependencies built in.

I'm just a bit curious though; a lot of C libraries are system-wide, and usually require the system package manager (e.g. libsdl2-dev) does this have an elegant way to handle those?

randerson_112 2 hours ago|
Yes, many libraries are system wide that is true. This is something I had on the list of features to add. System dependencies. Thank you for the feedback!
Surac 4 hours ago||
Uses CMAKE, Sorry not for me. Call me old but i prefere good old make or batch. Maybe it's because i can understand those tools. Debugging CMAKE build problems made me hate it. Also i code for embedded CPU and most of the time CMAKE is just overkill and does not play well the compiler/binutils provided. The Platform independency is just not happening in those environments.
vnorilo 2 hours ago||
When you need a configuration step, cmake will actually save you a lot of time, especially if you work cross platform or even cross compile. I love to hate cmake as much as the next guy, and it would be hard to design a worse scripting language, but I'll take it any time over autoconf. Some of the newer tools may well be more convenient - I tried Bazel, and it sure wasn't (for me).

If you're happy to bake one config in a makefile, then cmake will do very little for you.

Night_Thastus 2 hours ago|||
For toy projects good old Make is fine...but at some point a project gets large enough that you need something more powerful. If you need something that can deal with multiple layers of nested sub-repositories, third-party and first-party dependencies, remote and local projects, multiple build configurations, dealing with non-code assets like documentation, etc, etc, etc - Make just isn't enough.
delta_p_delta_x 4 hours ago|||
> most of the time CMAKE is just overkill and does not play well the compiler/binutils provided

You need to define a CMake toolchain[1] and pass it to CMake with --toolchain /path/to/file in the command-line, or in a preset file with the key `toolchainFile` in a CMake preset. I've compiled for QNX and ARM32 boards with CMake, no issues, but this needs to be done.

[1]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains....

bluGill 4 hours ago||
For simple projects. Make is easier for simple things I will grant. However when your projects gets complex at all make becomes a real pain and cmake becomes much easier.

Cmake has a lot of warts, but they have also put a lot of effort into finding and fixing all those weird special cases. If your project uses CMake odds are high it will build anywhere.

tosti 4 hours ago||
Odds are high the distro maintainer will lose hair trying to package it
bluGill 4 hours ago||
Anyone can make a tool that solves a tiny part of the problem. however the reason no such tool has caught on is because of all the weird special cases you need to handle before it can be useful. Even if you limit your support to desktop: OS/X and Windows that problem will be hard, adding various linux flavors is even more difficult, not to mention BSD. The above is the common/mainstream choices, there Haiku is going to be very different, and I've seen dozens of others over the years, some of them have a following in their niche. Then there are people building for embedded - QNX, vxworks, or even no OS just bare metal - each adding weirdness (and implying cross compiling which makes everything harder because your assumptions are always wrong).

I'm sorry I have to be a downer, but the fact is if you can use the word "I" your package manager is obviously not powerful enough for the real world.

the__alchemist 4 hours ago|
I will categorize this as a pattern I've seen which leads to stagnation, or is at least aiming for it. Usually these are built on one or more assumption which doesn't hold. The flow of this pattern:

  - Problem exists
  - Proposals of solutions, (varying quality), or not
  - "You can't just solve this. It's complicated! This problem must exist". (The post I'm replying to
  - Problem gets solved, hopefully.
Anecdotes I'm choosing based on proximity to this particular problem: uv and cargo. uv because people said the same thing about python packaging, and cargo because its adjacent to C and C++ in terms of being a low-level compiled language used for systems programming, embedded/bare-metal etc.

The world is rich in complexity, subtlety, and exceptions to categorization. I don't think this should block us from solving problems.

bluGill 2 hours ago||
I didn't say the problem couldn't be solved. I said the problem can't be solved by one person. There is a difference. (maybe it can be solved by one person over a few decades)
randerson_112 2 hours ago|||
This is true. There is no way I could solve a problem of this scale by myself. That is why this is an open source project and open to everyone to make changes on. There is still much more to improve, this is only day 1 of release to the public.
tekne 2 hours ago|||
I mean -- if I'm going to join a team to solve the hard 20%, I'd like to see the idea validated against the easy 80% first.

If it's really bad, at least the easy 20%.

wg0 5 hours ago||
Yesterday I had to wrestle with CMake.

But how this tool figures out where the header files and build instructions for the libraries are that are included? Any expected layout or industry wide consensus?

integricho 4 hours ago||
I believe it supports only projects having a working cmake setup, no extra magic
flohofwoe 4 hours ago|||
I suspect it depends on a specific directory structure, e.g. look at this generated cmake file:

https://github.com/randerson112/craft/blob/main/CMakeLists.t...

...and for custom requirements a manually created CMakeLists.extras.txt as escape hatch.

Unclear to me how more interesting scenarios like compiler- and platform-specific build options (enable/disable warnings, defines, etc...), cross-compilation via cmake toolchain files (e.g. via Emscripten SDK, WASI SDK or Android SDK/NDK) would be handled. E.g. just trivial things like "when compiling for Emscripten, include these source files, but not those others".

eliemichel 4 hours ago||
CMakes piles up various generations of idioms so there are multiple ways of doing it, but personally I’ve learned to steer away from find_package() and other magical functions. Get all your dependencies as subdirectories (whichever way you prefer) and use add_subdirectory(). Use find_package() only in so-called "config" mode where you explicitly instruct cmake where to find the config for large precompiled dependencies only
delduca 4 hours ago||
Compared to Conan, what are the advantages?
randerson_112 52 minutes ago|
Craft has project management and generates starter project structure. You can generate header and source files with boilerplate starter code. Craft manages the building of the project so you don’t need to write much CMake. You can also save project structures as templates and instantiate those templates in new projects ready to go.
mutkach 4 hours ago||
Please consider adding `cargo watch` - that would be a killer feature!
randerson_112 2 hours ago|
Yes! This is definitely on the list of features to add. Thank you for the feedback!
einpoklum 2 hours ago|
Impression before actually trying this:

CMake is a combination of a warthog of a specification language, and mechanisms for handling a zillion idiosyncracies and corners cases of everything.

I doubt than < 10,000 lines of C code can cover much of that.

I am also doubtful that developers are able to express the exact relations and semantic nuances they want to, as opposed to some default that may make sense for many projects, but not all.

Still - if it helps people get started on simpler or more straightforward projects - that's neat :-)

More comments...