Observation on the ged_exec changes - going that route, we're basically down to runtime-only detection of any errors in programmatic usage of libged. I was originally hesitant to go ged_exec only, on the theory that at least with ged_zap et. al. being explicitly called out we would have a modicum of validation that the code was calling something that is intended to be present in libged. I'm not opposed to going with the simpler route, but I just want to make sure and call out that we are moving to a runtime-only-validation configuration. I know we already had that anyway with GED argc/argv argument processing, so in one sense it's not a huge change, but since it does lose us that "compiler checking the command name is valid" insight I wanted to mention it.
I think with everything being dynamically loaded, it really makes the most sense. Otherwise, it's already really a dynamic call and the only saving grace is that we had to violate modularity to expose it.
They're technically already dynamic in a sense because of the automatic wrapper calling into ged_exec(), the only difference being the wrapper serving as a potential debugger breakpoint, but the actual call was still subject to whatever was put into argv[0]. architecturally the work was still happening dynamically.
I think the big win is modularity. Having every plugin have to be defined inside libged really defeats having everything in one place and propagates solutions like the mged/setup.c and tclcad/commands.c listings when they can/should just call exec.
Plus the plugins themselves can still define a public ged_cmd function now if they want, and that will work. They can be prebound into one library or linked against individually.
How is the new libged plugin method supposed to work? I get a lot of errors like
/bin/ld: libbrlcad.so: undefined reference to `__ged_cmd_ptr_fbclear_cmd'
when linking statically to libged.a.
Hopefully @starseeker can chime in because I'm having trouble making sense of the plugin.h interface. way too many layers of complexity and preprocessor hell imho.
it looks like the REGISTER_GED_COMMAND() macro is ultimately what is creating that symbol (a struct pointer). I just don't see where that is coming from.
GED_DECLARE_COMMAND_SET -> GED_DECLARE_COMMAND_METADATA -> LIST_MACRO -> GED__DECL_META_X -> .. appears to result in the former struct ged_cmd_impl declaration, so that's not it.
there appears to be three different preprocessor symbols that control visibility, LIBGED_STATIC_CORE and GED_PLUGIN_ONLY and GED_PLUGIN so presumably something is mismatched there.
Looks like LIBGED_STATIC_CORE is on by default, so it's declaring those entry points but then somehow they're not actually available. Quick guess would be to try setting -DLIBGED_STATIC_CORE=OFF when building BRL-CAD might be a workaround but presumably something needs to be fixed declaration-wise for the static lib to be right (if it's referencing __ged_cmd_ptr_*'s that don't exist in the .a, that's a mistake). If you nm -a libged.a, do you see __ged_cmd_ptr_fbclear_cmd ?
The static libged.a has round about have the size of the dynamic libged.so. Usually, the static libraries are larger than the dynamic ones. E.g., librt.a has more than 3 times the size of librt.so. (I've Debug build.) Therefore, there seems to be something missing.
nm -a libged.a | grep fbclear
U __ged_cmd_ptr_fbclear_cmd
0000000000007568 T ged_exec_fbclear
0000000000000648 d _ZZ16ged_exec_fbclearE7cmdname
Looks like a mistake in src/libged/CMakeLists.txt - I was only doing the plugin sources and build flags propagation for libged, not libged-static. https://github.com/BRL-CAD/brlcad/commit/728627f981a109ae1c07869a45c2c1ff81cea07c results in a jump in libged.a size locally for me from 17M to 81M
@Daniel Rossberg Is misc/win32-msvc still fairly representative of how you're assembling your libbrlcad.so file? I really need to get something into our main build that tickles the files the way your setup does so we see breakages like this one immediately...
starseeker said:
Daniel Rossberg Is misc/win32-msvc still fairly representative of how you're assembling your libbrlcad.so file? I really need to get something into our main build that tickles the files the way your setup does so we see breakages like this one immediately...
To be honest, I haven't used this since years. MOOSE is the way to go. It would be okay for me to remove this.
Now, I see a lot of link errors from src/libbu/fort.c, like
/bin/ld: /home/rossberg/bin/brlcad/lib/libbu.a(unity_2_c.c.o):/home/rossberg/Devel/BRL-CAD/brlcad/src/libbu/fort.c:3789: multiple definition of `fort_calloc'; /home/rossberg/bin/brlcad/lib/libged.a(unity_3_c.c.o):/home/rossberg/Devel/BRL-CAD/brlcad/src/libbu/fort.c:3789: first defined here
However, the file's header says
/* The file was GENERATED by an amalgamation script.*/
/* DO NOT EDIT BY HAND!!! */
https://github.com/seleznevae/libfort is our upstream - the "cleanest" answer would be to make a PR with whatever changes are indicated and then generate a new fort.c from there.
However, there is a libbu API that exposes fort.c capabilities - I may be able to have bot.cpp and stat.cpp work through that.
That's the first thing to try. Stand by...
I've pushed a change making the libfort usage fully internal to libbu - hopefully that helps
@Daniel Rossberg https://github.com/BRL-CAD/MOOSE/tree/latest has the tweaks I made to get MOOSE to build on Linux against latest main brlcad.
Thanks for noting me. After you successfully fixed the libfort issue, I did some updates to MOOSE too, but stopped after hitting the dependency of libged to manifold, There, I needed some time thinking about how to handle this.
I'll compare our versions the next days. I think that I had to do some more changes. I'll keep you informed...
Is the problem that we have multiple libraries depending on manifold? Or some other issue?
Certainly not speaking for him or his concerns but from a SWE perspective it is very uncommon/bad for a c++ api in particular to transitively impose volatile link requirements that aren’t directly used. In this case, apps using moose are beholden at link time and intimately aware of libs that are not its concern (nor really moose’s).
Probably a case where moose really should be calling all ged plugins dynamically not static embedding.
So... am I doing something incorrect in how I'm using Manifold? Or not building the static libraries correctly?
starseeker said:
Is the problem that we have multiple libraries depending on manifold? Or some other issue?
At first glance, the problem is that the manifold library has to be linked dynamically, but MOOSE follows an "everything in one library" principle. I had to think about this.
I want to keep this principle, but I'm aware that it can be hold for the core only. GED is however very much everything, not only the core. Therefore, I cannot expect to have everything in one large BLOB when including libged.
As alternative, I added a CMake flag BRLCAD_STATIC_LINK to MOOSE, which switches the linkage type to dynamic, if not set. And, I thought about unsetting this flag, i.e. requiring dynamic linkage, if MODULE_COMMANDSTRING is set.
Currently, my plan is to not unset BRLCAD_STATIC_LINK if MODULE_COMMANDSTRING is set, link as much as possible statically, but there will remain some external dependencies.
Pushed my MOOSE stuff to GitHub.
I still get linker errors when linking arbalest with the new libbrlcad. But, the dynamic version works.
@starseeker while cool to see the pattern tool folded in, did you look at the resulting UI?? the updated clone CLI is absolutely atrocious imho... AI vomit.
it's four completely different input modes baked into one synopsis option set that all appear to be completely independent with each other. even where a new option was added that could have been made globally consistent (like --zdir) a very similar but different named option was injected, one that only works with that mode (and that is still encoded, so you have to read the doc in detail). It's entirely what I'd expect iterating and having it add the next mode as a target goal without regard to UI consistency or UX implication.
I think if didn't cheat the synopsis summary with "[options]" it would be pretty apparent how egregious it is... Can you put it through more paces before that gets published as new clone CLI? ..
"Fold MGED pattern tool functionality into clone command" was rather understated to say the least...
I think I see how it happened. It folded three separate tcl procs that pattern tool was using under the hood, but took no steps to unify them so that they make any sense cohesively under one command. So we got a 4-to-1 garbage merge.
Update for the chat - @Sean and I went a few rounds and came up with what should be a cleaner options approach to the clone/pattern merger.
@Daniel Rossberg I think I'm going to be able to solve the problem of needing to link manifold dynamically - still working on it, but looks promising
Last updated: May 14 2026 at 02:10 UTC