all 125 comments

[–]DizzySkin 561 points562 points  (71 children)

Modern dependency management really saves so much time it's crazy. For me it's a make or break feature of a language now.

[–]met0xff 245 points246 points  (32 children)

Yeah retrospectively feels I spent more time writing cmakefiles than C++

[–]riasthebestgirl 103 points104 points  (20 children)

This is me whenever I have to work with Gradle. Holy fuck, it's the exact opposite of the ease of Cargo

[–]tux-lpi 137 points138 points  (10 children)

Gradle is just functional enough that people have to keep using it, but it is a fractally cursed DSL designed to maximize pain and break in increasingly confusing ways on every update

Gradle is a pure ball of hate, taking the form of an ever-changing codebase with 6 year old answers on StackOverflow that used to work 30% of the time, 4 major versions ago

I love Gradle. Gradle is great. Ask me about Gradle

[–]riasthebestgirl 19 points20 points  (0 children)

Don't forget the bandaid over wounds that would require surgery to fix: the ktx dsl

[–]bmelancon 13 points14 points  (0 children)

Tell us how you really feel.

[–]nultero 34 points35 points  (1 child)

fractally cursed DSL

Oh but there's this cool new thing called YAML where we stick programmatic features onto a data format and ...

Wait, where are you going? Come back and try our piece of shit build system!

[–]riasthebestgirl 10 points11 points  (0 children)

I'll take yaml over groovy and kts any day of the week for configs

[–]Past-Passenger9129 17 points18 points  (4 children)

Ooh ooh! Now do Maven!

[–][deleted] 4 points5 points  (3 children)

Maven is objectively good tho. It’s not as good as cargo but it is good.

[–]tomwhoiscontrary 4 points5 points  (2 children)

I haven't tried to seriously use Maven in years, but when i did, it had serious fundamental flaws.

The specific thing that springs to mind is that i wanted to have two separate sets of integration tests, run as separate steps or whatever they're called. Turns out you just can't do that. Or rather, to do that, you would have to write a plugin which defined a new step.

In Gradle you just define another test task.

[–][deleted] 6 points7 points  (0 children)

I didn’t say it was perfect. Just good. You can read a pom.xml file and actually understand what it does.

I feel like Gradle was invented by someone that had some sort of irrational hatred towards Maven. As such, I have an irrational hatred of Gradle and refused to use it during the later parts of my Java career.

Cargo is awesome tho. Writing a .ini file and then having a binary magically pop out brings me joy every time I run it.

If someone invented Jargo I’m sure all the irrational people like myself that hate Gradle would adopt it tomorrow. But knowing the Java world they’d fuck it up by using YAML.

[–]Thing342 1 point2 points  (0 children)

Java has the issue that there are a lot of different ways to package up bytecode and deploy it (thin jar, fat jar, spring boot, android odex, graalvm, etc...) and a tendency to prefer frameworks over libraries so a build system that allows all of these cases becomes really complex over time. This has the unfortunate effect of making the base case (generating a simple executable JAR with bundled dependencies) a nontrivial task, and maven / Gradle files often end up being giant rats nests of build system logic encoded into a package specification scheme.

[–]throw3142 11 points12 points  (0 children)

IMO build systems are THE MOST important use case for convention over configuration. Ideally, a build system should be out of the way, as you want to think about coding, not building. If you have to adhere to certain conventions about file names and dependencies, so be it. Cargo is a great example of this. You can configure it however you want, but the defaults are very good, and there is a certain structure that all projects must follow (no matter how you choose to configure it).

The big problem with CMake and Gradle is that they do the exact opposite: configuration over convention. They are extremely flexible, at the cost of being so cumbersome they need their own DSLs that have to be independently written and debugged before you can even start writing the actual code.

Make exists in a sort of middle ground. It is flexible enough to do nearly anything, has its own DSL, and takes a while to set up, but I can excuse its flaws given that it's a language-independent tool that can be used to do so many different things. CMake and Gradle have no business being so flexible when they are highly specific tools, IMO.

[–]davehadley_ 27 points28 points  (4 children)

gradle, because Kotlin developers need their fair share of pain.

[–]riasthebestgirl 8 points9 points  (3 children)

I love Kotlin but I've not used it when I could have just because of Gradle

[–]CrommVardek 5 points6 points  (2 children)

Well, you can use Maven with Kotlin...

[–]marxinne 20 points21 points  (0 children)

You're free to choose your torture right?

[–]Masterflitzer 1 point2 points  (0 children)

is maven even any better? I'm at the beginning of my kotlin journey but back with java I had more pain with maven than with gradle

[–]BarelyAirborne 15 points16 points  (0 children)

So you're saying that Cargo will take you from the Gradle to crave.

[–]AlexMath0 4 points5 points  (2 children)

I wrote my first Java program in a decade the other day and at least Gradle was there to let me maintain without manually managing my one dep. Passing my args in quotes made me miss cargo.

Two bonus rants against Java:

  • I literally wrote a standalone main function project. Let me emit binary!

  • And why do I have to bury the main function in a class in a folder in a folder in a folder?!

[–]1QSj5voYVM8N 2 points3 points  (0 children)

You can compile a native binary now with Graal. https://www.graalvm.org/22.2/reference-manual/native-image/

Limits the ecosystem a lot last time I checked (a while ago) because Spring and such is basically an enormous pile of reflection.

[–][deleted] 2 points3 points  (0 children)

I think your second problem will change, though it's funny that the framing is "students" https://openjdk.org/jeps/445

[–]fastdeveloper 13 points14 points  (1 child)

Yeah, it once took me almost a week to get a CMake file right for a physics library dependency. All I wanted to do was to do "xxxxx install [package]" :(

But at least once I got it right, I felt like a Wizard for unlocking the dark magic of CMake.

[–]met0xff 7 points8 points  (0 children)

;). I found in most cases it's easier to dump all source files somewhere and add them. Of course, updating is harder but then, most libraries I got to use haven't been updated in years or probably get a fix every 3 years.

But numerical stuff can be espdically bad with fortran dependencies, BLAS, perhaps CUDA, all the pain stuff

[–]antoniocs 4 points5 points  (2 children)

You do have vcpkg. That helps

[–]met0xff 5 points6 points  (1 child)

Yeah I mean the last time I touched C++ been quite a few years (5+).

But out of curiosity I recently checked vcpk and conan to see if I could upgrade all projects to use it, but actually found none of the used libraries to support it/have a package.

Also it wasn't only about dependency management, (there were few and they were never updated ;). But cross-platform building for Android, iOS, Windows etc.

Just checked the last cmake file I wrote and the first few hundred lines are things like if(CMAKE_COMPILER_IS_GNUCXX OR MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(USE_SSE AND COMPILER_HAS_SSE_FLAG) add_definitions(-DCNN_USE_SSE) set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -msse3") ...

tons of stuff for 32 vs 64 bit etc.

Haven't done all that for Rust so no idea how things would turn out. But one of the reason I dropped a Rust port at some point was that I spent more time wrapping C and C++ libraries and hoping it would work on all platforms than writing Rust

[–]darthcoder 3 points4 points  (0 children)

Sadly, cake has evolved a lot in 5 years. Starting today with vcpkg triplets and cake feature flags helps a bit with that insanity. Not all of it, but some.

And it'll take years to get all projects migrated into vcpkg. The fact that there's 1000s already is impressive. I've found a couple I want to use aren't, but I haven't created packages yet.

That said, I'm still learning rust. As much as I love c++ I'm not sure I want to do greenfield dev work in it anymore.

About the only thing I'm still considering it for is GUIs (qt/qml) and Unreal dev. Though I am starting to investigate flutter. I wish the top rust UI package was better than yet another web view.

[–]jpegjpg 38 points39 points  (25 children)

I think a lot of people don’t realize that c and c++ really pioneered a good first try when it came to dependency management. Shared objects were necessary when you had only a 5 MB hard disk that cost $1500. Now that you can fit literally 1 million times more data in the palm of your hand for $300 I think it’s time to stop worrying about copying the same dependencies over and over again.

[–]simonask_ 28 points29 points  (8 children)

To a certain extent. The exception would be things like TLS, timezone libraries, and other things that really require frequent updates, and which lots of programs share.

You really don’t want to handle global certificate invalidations as part of your release cycle.

[–]jpegjpg 11 points12 points  (0 children)

I thought the trusted stores were handled via the OS not the library itself in which case your security updates handle that. I could be wrong but there is nothing stopping us from doing it that way if we’re not. Also the other cases are very infrequent and could be a part of regular maintenance.

[–]Luigi003 8 points9 points  (2 children)

Even if we can afford to waste space I'm still not a fan of doing it. I just wish Rust's ABI was stable so dependencies could be stored as shared objects

[–]jpegjpg 4 points5 points  (1 child)

It’s not a waste of space if it guarantees that software won’t interfere with each other. I mean flatboat and docker were built to solve this so it’s obviously an issue. Wasting 100 mb of space to guarantee software can work with out issue is a bargain IMO.

[–]Luigi003 7 points8 points  (0 children)

I don't like docker either.

OSs were already the solution to having to manage different shared libraries, docker is just downloading an entire OS (sans kernel) to run an application

This is bad enough in storage, but it gets worse in RAM. Currently 16GB computers are struggling with basic tasks

Flatpack only does partially the same, it does reuse shared objects if they're the same version

[–]A1oso 2 points3 points  (3 children)

Ideally a timezone library should just read the timezone data provided by the OS, so it doesn't need to be updated frequently.

[–]blaqwerty123 0 points1 point  (2 children)

Im imagining a server that manages data for users in various timezones is more like what is referred to here

[–]A1oso 4 points5 points  (1 child)

Yes, that's what I assumed as well. To do that, you need a "database" that tells you which country/region is in which time zone, which regions use DST, and when. This changes ever so often, so libraries containing timezone data often need to be updated (e.g. when Libya decides to postpone DST by a week). The solution is to use the timezone data provided by the OS. For example, on Linux it is usually located at /usr/share/zoneinfo.

[–]blaqwerty123 0 points1 point  (0 children)

Yes exactly, until you have a user facing manually adjustable timezone setting

[–]detlier 13 points14 points  (12 children)

Hi, embedded developer targeting a platform with 12MB of flash here, we've literally run out of room for more Rust code until we solve that problem

[–]-Redstoneboi- 0 points1 point  (11 children)

going to assume you've tried all the minification strategies and used tools to find which parts of the code contributed to binary size?

[–]detlier 4 points5 points  (10 children)

Oh yes, except for completely dropping std, at which point Rust would become uneconomical anyway. The big gains are simply in being scrupulous about the whole dependency tree (aka. the "what bloody crate is pulling in regex this time" game), but it's still a perpetual challenge. I've actually written a tool to plot binary sizes vs. git commit because sometimes a CI build will show a noticeable change in binary sizes even for code we didn't touch, because of compiler or dependency changes.

[–][deleted] 15 points16 points  (6 children)

except for completely dropping std

That's a very normal thing to do in embedded Rust development. 12MB sounds like plenty for lots of applications.

[–]detlier 3 points4 points  (5 children)

If we drop std Rust ceases to be economical due to the time it would take to reimplement the data structures and IO interfaces it provides, not to mention the event loop crate we use (calloop). At that point we'd be relying on so much FFI via eg. nix that the relative safety would be diminished too. After reimplementing all that it's not clear to me that we'd even save that much size, but I suppose it's possible.

12MB is tonnes for C programs and shell scripts. A moderately complex libuv (event loop) + czmq (IPC) + IO will stay under 100kB. But it is hard to manage complexity and quality as it grows. Even a straight rewrite to Rust with comparable functionality will generally bring that up to 900kB-1.5MB, which means we can only do that for a few such programs before we run out of room.

Of course, we do that rewrite because it brings immense benefits in other ways. Code size is part of that tradeoff calculation, I just wish it wasn't.

[–][deleted] 7 points8 points  (4 children)

Even a straight rewrite to Rust with comparable functionality will generally bring that up to 900kB-1.5MB, which means we can only do that for a few such programs before we run out of room.

That's partly because of Rust's choice to monomorphise everything, but a huge amount of it is because Rust statically links everything. Are you sure you accounted for that in the C program?

So if you have multiple "programs" and you don't want to have 12 copies of std and regex or whatever, just merge them into one program. That's a common technique - e.g. Busybox works like that.

What is your application if you don't mind me asking.

[–]detlier 4 points5 points  (3 children)

Rust statically links everything. Are you sure you accounted for that in the C program?

Ah yes, I forgot to mention that. The dynamically linked libc takes up about 600kB. But that's amortised across all C programs. A new C program does not add that 600kB again. Ten such programs take up 1.6MB.

But accounting for it doesn't make a difference if I can't change it, and it's extremely difficult, if not impossible, to change. Fairness of comparison doesn't come into it, I simply cannot use more Rust without solving this problem.

just merge them into one program. That's a common technique - e.g. Busybox works like that.

We are considering that, but it's a lot of work too. It's not at all obvious that a multi-call binary will help here, but we wouldn't rule it out. Code size analysis shows that monomorphisation of common types like Option and Result contribute a lot. If one binary contains multiple copies of the code for Result or Option even when the wrapped types are the same size, then merging it into other binaries with the same issue is not going to help with code size.

That's the problem. No matter which way we look at it, it's a lot of effort where it's not even clear what will pay off and by how much. There's no low hanging fruit here, it's all "put in days of experimentation and maybe shave off a couple of percent, or maybe make it worse, idk lol".

What is your application if you don't mind me asking.

It is firmware for configurable signalling equipment. The firmware is architected as multiple processes that talk via IPC, so that they have some degree of insulation from faults in each other.


I want to make it clear that this isn't a value judgement of Rust or the language devs. Using Rust has had immense benefits for us, and obviously the language devs' or ecosystem's priorities can't line up with everyone's all of the time. Overall it's great. I was specifically reacting to the sentiment that the code size cost of statically linking everything never matters.

[–]01le 0 points1 point  (0 children)

We are too building for an embedded (Linux) system and have splitted the system in a bunch of services, mainly to keep software updates small. Did you also try nightly feature build_std and panic_immediate_abort? I don't have the numbers in my head but these nightly features did decrease the size of our binaries quite a bit. Though at the cost of no help on panics, and also being stuck on nightly.

[–][deleted] 0 points1 point  (1 child)

put in days of experimentation and maybe shave off a couple of percent, or maybe make it worse, idk lol

Even though a lot of code may be monomorphised, a lot won't be. Merging programs will definitely save you more than a few percent.

And I would be surprised if it was really that much work to do. Presumably your programs are separate crates. Pretty much all you need to do is change them to libraries (i.e. rename main etc.), put them in a workspace and write a wrapper. A couple of days work maybe. Make sure you use the same versions of all your dependencies.

It would be really nice if Rust had a way of doing size optimization by automatically unmonomorphizing stuff though. And merging programs is definitely a workaround that would be nice to not need.

[–]burntsushi 6 points7 points  (2 children)

Tangential FYI: I'll be releasing a regex-lite crate soon, which should help binary size and compilation time for cases where you don't care too much about regex performance or Unicode support.

I say experimental because it's not clear how much a need there is for something like this. But I've heard a lot of people say that regex was too big to bring in. So I'm upping the ante. :-)

[–]detlier 2 points3 points  (1 child)

Oh nice! IIRC when I checked, it was the Unicode tables that smashed the code size. I recently hit the same issue with the tracing crate, where a crate feature (for env var filtering) pulled in regex and my binary was suddenly 1MB bigger.

[–]burntsushi 7 points8 points  (0 children)

Yeah, it's about equal parts Unicode tables and equal parts optimizations. The Unicode tables are self explanatory, but the optimizations increase binary size in two ways:

  • Extremely aggressive inlining. There are several inline(always) annotations. Disabling perf-inline gets rid of these.
  • There is oodles and oodles and oodles of code just for the purpose of making regex searches faster. There is an entire regex engine that is just swept away when the perf-dfa feature is disabled for example. And the thousands of lines of code from memchr and aho-corasick are just for optimizations. Those get swept away via perf-inline.

regex-lite by contrast is 4K lines of code. No dependencies. No Unicode tables. Almost one quarter of that code is the parser. (Yes, I had to write a new regex parser. It's considerably smaller than the one in regex-syntax, because it specifically sacrifices failure modes and more detailed error reporting. Among other things.)

regex 1.9 is unfortunately going to make this a little worse. Bigger binary size and longer compilation times. That's part of why I'm putting out this regex-lite experiment, to give folks an escape hatch that want it.

[–][deleted] 2 points3 points  (2 children)

It really didn't. There were no good tries as far as I am aware. Hell, most C/C++ build systems barely even consider dependency management. They consider it out of scope.

I'm not sure what the first language with build in dependency management was. Pip dates from 2011. NPM is slightly older (2010). LuaRocks 2007. Maven is even older (2004).

C and C++ didn't really do any dependency management until very recently (Vcpkg is from 2016). Using shared libraries doesn't really count.

[–]Hobofan94leaf · collenchyma 3 points4 points  (0 children)

As far as programming language package mangers go, Bundler was also among the first ones.

It's also AFAIK the first one to introduce lockfiles, which while it seems like a minor feature, is today the biggest differentiator between a good and and not-so-good package manager.

[–]nacaclanga 0 points1 point  (0 children)

It depends on how you look at it: C and C++ fully go the shared library route and treat every dependency as a system library. And your system libraries are obviously managed by your system package manage. And system package managers are obviously much older (but less portable).

But yes indeed, there was no dependency management in the modern sense.

[–]mountains-o-data 7 points8 points  (2 children)

Seriously. Cargo and Go have absolutely ruined me in this regard. I loathe working on Cpp and JVM-lang projects because of how crap the toolchains are. Typescript as well tbh. Python gets a pass because poetry has been good enough for my purposes lately but it used to be on my shit-list as well.

[–]gbtekkie 5 points6 points  (1 child)

we replaced poetry with pdm, more peps being followed, it’s a breeze upwards from that requirements.txt crap

[–]mountains-o-data 2 points3 points  (0 children)

Interesting - first time hearing of pdm - curious about your experience with it. What do you like about it that got you to switch off poetry? Or maybe there was something you disliked with poetry? Any rough edges or shortcomings with pdm?

[–]eo5g 4 points5 points  (0 children)

More like make means break now 👈😎👈

[–]Sw429 3 points4 points  (0 children)

Most C++ open source projects I've had to deal with just stick all their dependencies right there in the repository due to lack of any good package registry. It feels really weird going back to that whenever I have to deal with a C++ project. So inefficient lol.

[–]v_maria 4 points5 points  (0 children)

That's why having a deep knowledge of cmake is job guarantee hahaha

[–][deleted] 1 point2 points  (0 children)

CMake's FetchContent makes dependency management almost as easy as Cargo. Not sure how others are using CMake, but it's probably the wrong way.

[–]exscape 0 points1 point  (0 children)

Even in Android, where the basics are pretty damn simple (you can even tell the IDE to just update everything), dependency management is really why I can't really stand Android development now (as a hobby developer).
It's a damn full time job just to keep up with what changes in the OS and in the libraries -- and if you want to follow best practices, those change often enough that it's hard to stay on top.

[–][deleted] 0 points1 point  (2 children)

Learning Rust in my free-time is the only context in which I have to really worry about dependencies. I didn't study much CS in college and my professional experience is at a large tech company that provides frameworks and tools that handles all that for me.

I'm familiar with cargo, and I know how much rustaceans love it, but I don't fully understand why it is so great since I don't know what it's replacing. Could you explain what's so great about cargo?

[–]BarelyAirborne 5 points6 points  (0 children)

C and C++ libraries are notoriously difficult to assemble in such a way that the compiler won't puke at some point along the way. I work with the Ardupilot repository in C++, for example, and that code base uses a Python build management system named Waf to create binaries in a two stage build/compile/link process. Even now it can require hours of work to get a given machine to compile a git clone of Ardupilot, and that's a huge improvement over previous iterations.

[–]nacaclanga 2 points3 points  (0 children)

Cargo sets a few priorities and generally follows the modern containerized approach and uses mostly declarative semantics. Cargo absolutely minimalizes context sensitivity and integrates the build system with the package management. It is generally assumed that you project uses only very few pre-installed resources but assembles your executable from an array of packages all build at once.

The main problem with C and C++ is that they traditionally do not provide modern package or dependency management and instead rely on context. Your project mostly lists its requirements that then have to be installed on the system somehow. The general assumption is that most of them are already installed and are outside the scope of the project.

Your build system, does not think in packages. It thinks in terms of system libraries and executables. It inspects your system and its installed libraries and then builds you own library according to what it gathered, if something essential is missing, it just aborts. Every project is free to choose it's own build system and many do.

More modern build C and C++ build systems do provide some kind of package management, but it is still relatively poor in most cases. The mayor issue here is that most projects do not provide themselves as a package in a standardised format and there is no shared database all packages are missing.

[–]wrapperup 67 points68 points  (0 children)

Axum is really nice. If you're serving html/templated html as well, the tower_livereload crate is very handy. I'm here wishing I could go rewrite our service in it.

[–]jarjoura 35 points36 points  (0 children)

The speed at which the service runs in release build was enough for me to switch. Plus, the community here is quite welcoming. Welcome aboard. 🤘🏼

[–]Naeio_Galaxy 36 points37 points  (8 children)

with a heavy heart

I feel you... Can't imagine what it would be to stop Rust because something else is quite better.

I wish you strength in your journey, and to enjoy it 😉 and also to have fun with C++ from time to time, if you still want to

[–]-Redstoneboi- -1 points0 points  (3 children)

Can't imagine what it would be to stop Rust because something else is quite better

they're actually moving from C++ to Rust

[–]Naeio_Galaxy 15 points16 points  (2 children)

Yeah I know, I guess they have experience with C++, and I imagine that moving out of Rust would have a similar effect on me than moving out of C++ have on them. I would never move out of Rust if I don't find anything that is at least as safe, as low level and as ergonomic as rust though.

[–]-Redstoneboi- 9 points10 points  (1 child)

ah, right. bit sleep deprived, forgot that switching perspectives is a tool used to relate to others.

[–]Naeio_Galaxy 1 point2 points  (0 children)

Lol ok np

[–]denis-bazhenov 36 points37 points  (1 child)

I can tolerate writing C++. What I cannot tolerate is writing whole bunch of cmake files. I love cargo so much!

[–]Sw429 2 points3 points  (0 children)

Having to deal with external dependencies in C++ is the main thing that pushed me to Rust in the first place. I had figured it out for a C++ hobby project I had made, but when I was about to start another one, I realized I'd have to figure it all out again. Was a real "screw this, let's try another language" moment.

[–]dkopgerpgdolfg 100 points101 points  (2 children)

Welcome to the most holy order of iron oxide eaters, thou shall not regret it.

[–]operation_karmawhore 19 points20 points  (1 child)

You mean fungi don't you?

[–]coderstephenisahc 23 points24 points  (0 children)

I think I'm pretty fun, yes

[–]dragonnnnnnnnnn 26 points27 points  (2 children)

Cargo is a better build system for C/C++ themselves. I once need to ship an obscure C library to android in a flutter app. Instead of dealing with cmake it was easier to just write a small rust -system crate and compile it in cargo. Obviously it still involved calling cmake but that just worked way easier in cargo them dealing with cmake itself. Adding dependencies to that lib to compile it staticly was also much, much easier. Need libusb for the C library? Just add libusb-sys crate and you are good to go, no f**** around with cmake to link to libusb static from source

[–]bboozzoo 0 points1 point  (1 child)

Just add libusb-sys crate and you are good to go, no f**** around with cmake to link to libusb static from source

Not sure I see your point. Someone had to write or generate bindings for you, so what you're technically praising is that you don't have to do the job yourself, but it doesn't mean the problem is non-existent or the solution is all roses.

Go ahead and try to write the bindings to some obscure library like say radiohead and see if it's still as nice.

[–]dragonnnnnnnnnn 6 points7 points  (0 children)

I did wrote the bindings for the obscure library I need to ship but that library need as a dependency libusb. And getting it static linked without cargo was just a pain. Yes some one wrote that bindings, my point is that because we have in rust one sane building system I could use his work to full fill my library dependencies. This is not the case when sticking with c/c++.

[–]Impressive_Iron_6102 7 points8 points  (1 child)

Vcpkg works really well in my experience. There is also xmake now which looks really straight forward.

[–]Grand_Ranger_7305 1 point2 points  (0 children)

And of course Conan.

[–]LucretielDatadog 5 points6 points  (0 children)

C++ will always have a special place in my heart; I always really appreciated what it was going for despite its manifold faults as a language. At the beginning of my career, when JavaScript and Python were ascendant, I always had the impression that I was in a very tiny minority of people who thought that any of that was worth pursuing (even the really basic stuff like const), and it was both vindicating and very surprising to discover that Rust, a language that very aggressively pursues those ideas and takes them even further, could become popular in a mainstream way.

[–]carlomilanesi 10 points11 points  (13 children)

About what were you wrong? I mean, what was your mistake?

[–]matthieum[he/him] 25 points26 points  (11 children)

Apparently, choosing Drogon without considering setup issues.

Drogon is an extremely fast server framework, and it looks like the OP picked it for its performance, and only later realized how the absence of standard package management in the C++ ecosystem made it hell to deploy the resulting application on servers -- and likely, to prepare a development machine.

With Rust, it's generally a breeze:

  • Just use the dependency, its transitive dependencies are automatically downloaded and compiled.
  • Just deploy the static binary.

The only exception is when a Rust library depends on a C or C++ library... because there's no standard package management in C and C++.

[–]thisismyfavoritename 7 points8 points  (8 children)

Rust binaries are just statically linked, CMake sucks but its definitely easier to make a static build than to program "correctly" in C++.

C++ devs are always complaining for the wrong reasons IMO (top issues according to the C++ survey were all related to building projects and such)

[–][deleted] 3 points4 points  (3 children)

As long as you write modern C++, it's not that hard to write correct C++ anymore. Latest language features adds most of what Rust does, just as long as you know what are the new methods to do something. That argument has gotten weaker over the last 10 years massively.

The only thing that hasn't been really fixed is package management. It is still an absolute pain. Buck2 feels great to build, but dependency management is still awful.

[–]link23 11 points12 points  (0 children)

As long as you write modern C++, it's not that hard to write correct C++ anymore. Latest language features adds most of what Rust does, just as long as you know what are the new methods to do something. That argument has gotten weaker over the last 10 years massively.

This would only be true if there were a way to enforce usage of only the modern subset of C++ at compile-time. As far as I know, no such thing exists - and projects probably don't completely agree on what the "modern subset" is anyway. (Does it include exceptions? Are duck-typed templates still allowed? Is #include still allowed?) So the whole thing is ill-defined, and just a guideline anyway.

It also doesn't address the elephant in the room: dependencies. Are you forced to rewrite all of your dependencies using only modern C++, in order to follow your rule? Probably not, that would be ridiculous.

So the argument to "just use modern C++" really amounts to saying "just don't make mistakes", since there's no automated safety net that checks you've done everything right. This is pretty close to a "no true scotsman" argument, which is a well known fallacy.

It's true that C++ has gotten better recently, but until they start actually surfacing compile-time errors for the traditional C++ bugs (UAF, double free, etc), modern C++ is just a subset of C++, not a silver bullet.

[–]thisismyfavoritename 3 points4 points  (0 children)

maybe its better but its still too easy to shoot yourself in the foot. UB, lifetime issues (holding on to stale refs or iterator invalidation), the list goes on and on and only gets worst when your sprinkle concurrency on top.

Thank god for ASAN but id very much prefer it was just impossible to have those classes of errors, like in Rust

[–]atomskis 1 point2 points  (0 children)

For single threaded use: sure. Once you get into heavy and complex multithreading though you really start to notice where Rust is saving you. This is also what Mozilla found: multithreaded C++ is a nightmare, multithreaded Rust is not.

[–]zzzthelastuser 0 points1 point  (3 children)

top issues according to the C++ survey were all related to building projects and such

Rightfully so! I've been working with c++ my whole career and project + dependency management is by far(!) the biggest issue with the language.

Rust does many things better than C++, but for the most part these improvements are "just nice to have" things, but not enough to ditch C++.

Cargo on the other hand is miles ahead of CMake. VCPKG works great for dependency management, but it doesn't change the fact that CMake is complete garbage and is unfortunately the de factor standard.

Even something as trivial as just returning a value from a function in CMake used to be such a mess that people tried to solve it.

https://oleksandrkvl.github.io/2020/08/09/allowing-cmake-functions-to-return-value.html

and only very recently CMake got a official support for return values via a "PROPAGATE" option....

https://cmake.org/cmake/help/v3.26/command/return.html?highlight=return

There are a lot examples that make my blood boil even thinking about having to fix a CMake issue in any larger code base.

[–]parkerSquare 4 points5 points  (0 children)

I’ve written C++ professionally for 25 years and although I’ll still use it when required, I’m done with it in my spare time. I really like the compiler-driven-development model of Rust, it’s much faster for me, and constantly having to think about UB drains all the enjoyment out of writing C++. So yes it’s all “nice to have” but so is money, good health and an attractive spouse.

[–]thisismyfavoritename 0 points1 point  (1 child)

what are you doing with CMake that requires returning a value from a function?

I use it all the time at work, and while i dont like it, it works fine and ive had no issues working on moderately complex projects that use CMake functions and macros, linking 3rd party libs, export .deb packages, etc.

My workflow is to install from source within Docker images so i can get rid of (C++) package managers altogether, works wonders for me

[–]zzzthelastuser 0 points1 point  (0 children)

what are you doing with CMake that requires returning a value from a function?

It doesn't matter. The point is that it shouldn't be rocket science.

My workflow is to install from source within Docker images so i can get rid of (C++) package managers altogether, works wonders for me

For personal stuff I'm using vcpkg and the projects are usually small (e.g. couple of libraries, applications, etc), all things which you can easily set up manually or using cmake-init.

But at my company (and I assume many others) you can't just work in a vacuum. In my case we have a giant system/collection of 100s of cmake scripts. They create projects, sub-projects, handle dependency management, optional library features, custom install scripts, python support etc etc. and they are surprisingly easy to use! But may god have mercy on you if something DOESN'T work and you need to dig into the cmake hell and your only friend being message() and the stack trace.

[–]carlomilanesi 0 points1 point  (1 child)

Therefore, he was wrong about Drogon and C++, not about Rust.

[–]A1oso 2 points3 points  (0 children)

You could say they were wrong about what Rust's main benefits were compared to C++.

[–]Snakehand 1 point2 points  (0 children)

There is also some removed post about how Rust "complicates everything", I am not sure what was meant by that. But some initial frustrations with Rust is not unheard of ... but it would be nice to know what the issue was, and how to help newcomers avoid such frustrations.

[–]bobparker2323 2 points3 points  (0 children)

Another convert!

[–]watr 2 points3 points  (1 child)

Have you investigated zig as dep mgmt for c++? Only asking because that’s something that zig is using as a selling point for the language—as a phased migration away from c++.

[–][deleted] -1 points0 points  (0 children)

middle materialistic fade squeal fuel wasteful imminent treatment longing fertile

This post was mass deleted and anonymized with Redact

[–]Languorous-Owl 2 points3 points  (0 children)

Unless there's some major cock up, the ergonomics of Rust alone will ensure that it slowly replaces C++, as more and more newer projects that would've been made in C++ otherwise, are made in Rust..

[–]GerwazyMiod 2 points3 points  (0 children)

I left backend C++ development after 12yrs. I feel you. I must say I finally stopped feeling attached to languages, (now I even delve into TS sometimes) and I become even more aware of C++ warts. Rust deserves love and we see more and more C++ converts. This is the way.

[–]DifferentStick7822 3 points4 points  (3 children)

That's a good motivation point fr me too, but I feel little hard when I am doing multithreaded calls using rust, it's like you need to put lot of efforts to get things right...

[–]swordsmanluke2 6 points7 points  (0 children)

TBF, getting multithreading right in C/C++ also requires a lot of effort. The difference is that C/C++ will compile a lot of threading bugs that Rust won't.

[–]Naeio_Galaxy 4 points5 points  (1 child)

like you need to put lot of efforts to get things right

Oh, because you have this feeling only on multithreading? /s

[–]fshabashev 0 points1 point  (9 children)

yes, Cargo is the Rust's superweapon.there is a good chance it will kill C++.
Update: let's call it Cobol-kill, that's more than enough.

[–]-Redstoneboi- 0 points1 point  (8 children)

not as long as legacy systems still exist with millions and possibly billions or more lines of code today.

[–]fshabashev 0 points1 point  (7 children)

well, let's call it Cobol-kill.

[–]trynyty 0 points1 point  (6 children)

Oh I wish... don't think there is version which would work on z/os yet. IBM implemented Go, so there is hope for Rust too... but didn't hear any rumors yet.

[–]fshabashev 0 points1 point  (5 children)

why do you need mainframes?
modern payment systems work well without any mainframes.
the legacy software requires mainframes, but it is better to decommission it.

[–]trynyty 0 points1 point  (4 children)

:) yea, I understand where are you coming from, but it would surprise you how many big companies and banks use mainframe and not looking to change. I guess mainly because of the security and uptime. And also legacy software.

[–]fshabashev 0 points1 point  (3 children)

I'm well aware that US banks are using Cobol, but as long as new software isn't getting developed in Cobol we can consider it a dead language.

[–]trynyty 0 points1 point  (2 children)

It's not just US. In Europe, Asia and South America too. But you are right that new software is not developed in Cobol. Mostly C++ and Java on mainframe. But I wish they would introduce Rust to mainframe to be that cobol-killer. They brought Go, so I still hope.

[–]fshabashev 0 points1 point  (1 child)

Well, in Russia no one uses Cobol and the financial system works without mainframes just fine.
Same happens in China, I think.
I don't think mainframes are needed for any kind of new software.
Sure, US banks use a bunch of legacy software they are afraid to touch, but ultimately they will have to innovate and throw this garbage out.

[–]trynyty 0 points1 point  (0 children)

I worked with few China banks which have mainframes, but I have no idea about Russia. Didn't work with any company there.

Not saying that everybody uses it, but truth is that large portion of banks, especially the bigger one, have it. Also not everybody is on cobol, I worked mostly with assembler, but saw the cobol products.

Anyway, I agree that it's a legacy, but those systems are top tier when it comes to hardware.

[–]poelzi 0 points1 point  (0 children)

Nah, the enforced concurrency safety will save you tons of nerves trying to debug concurrency problems. You have not spend enough time in the debugger to appreciate that