For those experimenting with bext, the latest main will now clone and build its own copy of bext as part of the configure stage if a BRLCAD_EXT_DIR location isn't supplied.
@Sean If you're going to remove the src/bext submodule, be sure to update the docs and remove the build logic that checks for it
@starseeker Ooops, I just saw an empty dir and thought it was leftover. Where does it check for it? Why does it need to be there empty?
https://github.com/BRL-CAD/brlcad/blob/main/misc/CMake/BRLCAD_EXT_Setup.cmake#L50
That's how unpopulated submodules in git work, AFAIK - a shallow bext clone is like that, as well
okay, so it's currently looking for it that way.. and that possibly explains some other issues I kept running into.
bit unexpected to have running something in the build dir affect the source tree by default. I assumed it was cloning into the build dir. Invoking action was a build action, so it probably shouldn't be touching the source dir.
Any reason it couldn't just be an external project add like bext is doing? That way, the clone rule will live in the build logic and the files will be in the build tree.
If the cmake configure does a clone, it is doing it in the build dir. The submodule in src/ was to allow a single git clone command to download everything needed for any BRL-CAD build config, in a single shot
If the user clones BRL-CAD with a git clone --recursive, then (and only then) src/bext is populated. Otherwise, everything happens in the build directory
Ahh, okay, so then it doesn't explain some other issues I kept running into...
Weird. I never did the recursive, but the auto kept giving me trouble. I've since switched to a manual build of bext because it would be broken after any change to a submodule (different reasons iirc).
So then sounds like there's three ways -- a recursive clone into src, an auto clone into builddir, or manual BRLCAD_EXT_DIR
Correct.
The first is intended for the "I don't care about disk space, make sure I've got everything I'll ever need" case. The second is the "only build what I need for this config of BRL-CAD" case. The third is the "I'm going to be compiling this sucker a lot, I don't want to keep rebuilding this" case.
Regarding the question of automatically responding to updated sources from git updates... My best guess is it would take some sort of custom UPDATE_COMMAND: https://cmake.org/cmake/help/latest/module/ExternalProject.html#update-step-options
Sticking rsync -a --delete into the Itcl ExternalProject_Add as an UPDATE_COMMAND results in rebuilding every time, so it appears to be triggering as expected - the trick would be to conditionally trigger based on a change in the original sources, rather than just doing it blindly. Probably a CMake script could do it...
@starseeker food for thought, thanks for checking. Might be a little more hairy if updates involve new patches also -- would probably need to catch any change inside the dependency subdir, invalidate it, and proceed as before (ideally). Not sure it's worth the extra logic though if that'd need to get injected into any places outside update_command (e.g., patching).
On a mildly point -- the itcl header patch is no bueno. There's no Tcl vars accessible to Itcl at that point, so the vars are invalid/empty.
The patch file itself, or the associated CMake logic?
I'm testing some ideas now - you have a point that things will get hairy if we all start piling into updating dependencies. I initially shied away from the added complexity in the initial work, but I'll see if I can find a reasonable solution
Oh, right gotcha - the Itcl build is doing find_package for Tcl, but the parent isn't
Duh.
This project reminded me of bext taken to the extreme... https://github.com/fosslinux/live-bootstrap/tree/master
They fully bootstrap a modern OS starting with nothing but a few hex numbers, progressing through to building tools that build the tools that build the tools, etc. Full steps here: https://github.com/fosslinux/live-bootstrap/blob/master/parts.rst
Cool!
That reminds me a little of some of my ideas for hobby projects from ten years+ ago... although I never thought about taking it to that extreme. I must salute their awesome craziness :-)
Is there a best practice for how to work with it? E.g., how to set BRLCAD_EXT_SOURCE_DIR and BRLCAD_EXT_BUILD_DIRBRLCAD_EXT_BUILD_DIR? I tried to set them in the CMake GUI. Then, it first complained about the not existing first directory. I thought, it will be created automatically. Next, it threw an error while trying to use the default external build directory.
Obviously, I did something wrong. What is best practice for doing this?
-DBRLCAD_EXT_DIR=/home/user/bext_output is usually how I set things up for a pre-existing BEXT build.
If you don't have a pre-existing bext build, you shouldn't need to do anything - configure should take care of things.
You shouldn't need to delve into the lower level variables unless you're (say) trying to have BRL-CAD's configure manage a build from a pre-existing bext source tree clone. That'd be when to set BRLCAD_EXT_SOURCE_DIR
I don't think there are too many cases where you'd want to override BRLCAD_EXT_BUILD_DIR - about the only thing that comes to mind is if for some reason you're having to do a BRL-CAD build on a small or almost full disk and you want to put the bext build outputs somewhere else, but still want the CMake configure to manage the build.
https://github.com/BRL-CAD/bext?tab=readme-ov-file#using-the-build-outputs-with-brl-cad
I was testing with different versions and branches, e.g. devel_k-g and main. There, the bext build was the most time consuming part (over an hour each with hotel WiFi). That's why I would like to have one build for all.
It looks like BRLCAD_EXT_DIR isn't memorized. What I did:
:right: Until here, it works well. CMake runs some seconds and prepares the build without cloning bext.
Now, I started the CMake GUI to adjust the install directory. After pressing configure, it started cloning the bext stuff again.
Ah, I see. You're right, it's not being written to the cache and a repeat configure forgets about it. Does https://github.com/BRL-CAD/brlcad/commit/0144bdd6edc77a7c722c9269343ccc3398213ded do what you need?
:+1: Looks good.
CMake was fast, now I'm running make.
@Sean I'm setting up in a branch to make tinygltf a bext component rather than embedded in BRL-CAD - let me know when a good time to merge would be.
@starseeker go for it
I tried using (git clone --recurse-submodules https://github.com/BRL-CAD/brlcad) to obtain all the files, but I got the following error while compiling the bext file using
(
f279e83ff4a41e294eeef597a8b3ba3.png
).I didn't find the line "verbose_add_subdirectory" in it, and the files "(ProjectName)(project)" and "(cmake_minimum_required(VERSION 3.31))" don't exist.
e6dc2720df8baefdaea1f4c41da55bd.png
I wonder why BUILD_STATIC_LIBS isn't set for bext, or inherited from brlcad.
I set it to ON, if it wasn't set before.
Actually, I need to check if our docs are out of date - we took the src/bext submodule out of the main brlcad repo. It was causing more trouble than it was worth.
so the recursive submodules clone of brlcad isn't useful anymore. You'd need to clone bext recursively.
Then set BRLCAD_EXT_SOURCE_DIR to the cloned bext source directory: -DBRLCAD_EXT_SOURCE_DIR=/path/to/bext
@starseeker Looks like we can point submodules to specific version tags instead of sha or heads/master and such. Any reason not to other than wanting something newer than they've released? That would be one way to maintain an automatic BoM. I updated the ospray/appleseed stack and have them pointing to specific rev tags as a test, seems to work nicely.
Works for me. I think I went with pointing at our local RELEASE branch just to have a uniform convention, but I'm not strongly tied to it if there's a better answer. In a few cases (netpbm for sure, probably a couple others) we do mod locally but I think in most cases that should be doable.
It is really nice to just run "git submodule status" and see the revisions right there.
Just tried to build bext from scratch (Debian stable/trixie, gcc 14.2.0). It fails applying the zlib patches.
@Daniel Rossberg can you post the error log? I just checked it on a system and seems to be working -- at least bext's main directly, haven't tried the loast auto-download version tagged on brlcad repo which is out of date.
Will do ... tomorrow.
It was the latest bext main with a build from scratch: cmake ../../../bext -DCMAKE_BUILD_TYPE=Debug -DENABLE_ALL=ON
The error message was
[ 24%] Performing patch step for 'ZLIB_BLD'
patching file CMakeLists.txt
Reversed (or previously applied) patch detected! Skipping patch.
6 out of 6 hunks ignored -- saving rejects to file CMakeLists.txt.rej
patching file deflate.c
Reversed (or previously applied) patch detected! Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file deflate.c.rej
patching file gzguts.h
Reversed (or previously applied) patch detected! Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file gzguts.h.rej
patching file gzread.c
Reversed (or previously applied) patch detected! Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file gzread.c.rej
patching file inftrees.c
Reversed (or previously applied) patch detected! Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file inftrees.c.rej
patching file win32/zlib1.rc
Reversed (or previously applied) patch detected! Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file win32/zlib1.rc.rej
patching file zconf.h.in
Reversed (or previously applied) patch detected! Skipping patch.
5 out of 5 hunks ignored -- saving rejects to file zconf.h.in.rej
make[2]: *** [zlib/CMakeFiles/ZLIB_BLD-install.dir/build.make:94: zlib/ZLIB_BLD-prefix/src/ZLIB_BLD-stamp/ZLIB_BLD-patch] Error 1
make[1]: *** [CMakeFiles/Makefile2:1758: zlib/CMakeFiles/ZLIB_BLD-install.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Then, I looked at the mentioned files and it looks like the patches were applied successfully, but the build script values this as an error.
Then, I removed everything from the zlib directory in the build directory and run make again. After that, zlib could be build.
Could it be that the patches were applied twice during configuration and build?
There are some intermediate states I've occasionally hit where it tries to re-apply patches to already patched copies of the sources - I'm not quite sure what the specific triggers are. I usually just do what you did to clear the error.
I looked and could not find a smoking gun on how it'd end up in a multiple patch state. best guess is either a cmake bug (likely) and/or some obscure subproject_add race condition where the sentinel files aren't gatekeeping the patching properly. seems plausible on things like libz since there are multiple subproject_adds that depend on it, so a parallel build will have multiple attempts to set it up.
with no cause evident, we can address the symptom and make already-applied patches non-fatal. I added a wrapper that checks whether the patch is already applied. if it's already applied, it makes the return code successful. that allows the build to proceed as it would have had the patching succeeded.
Maybe, I should mention that I did a recursive clone of bext, before running cmake.
However, the really annoying errors in the bext build are the ones like:
[ 90%] Performing build step for 'ITK_BLD'
CMake Error at /home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD-stamp/ITK_BLD-build-Debug.cmake:37 (message):
Command failed: 2
'make'
See also
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD-stamp/ITK_BLD-build-*.log
-- stdout output is:
[ 11%] Building C object CMakeFiles/itk3.4.dir/generic/itkStubInit.c.o
[ 22%] Building C object CMakeFiles/itk3.4.dir/generic/itkStubLib.c.o
[ 33%] Building C object CMakeFiles/itk3.4.dir/generic/itk_archetype.c.o
-- stderr output is:
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c: In function ‘Itk_CreateGenericOptTable’:
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:3991:48: error: passing argument 4 of ‘tclStubsPtr->tcl_SplitList’ from incompatible pointer type [-Wincompatible-pointer-types]
3991 | if (Tcl_SplitList(interp, options, &confc, &confv) != TCL_OK) {
| ^~~~~~
| |
| char ***
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:3991:48: note: expected ‘const char ***’ but argument is of type ‘char ***’
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:3995:52: error: passing argument 4 of ‘tclStubsPtr->tcl_SplitList’ from incompatible pointer type [-Wincompatible-pointer-types]
3995 | if (Tcl_SplitList(interp, confv[i], &optc, &optv) != TCL_OK) {
| ^~~~~
| |
| char ***
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:3995:52: note: expected ‘const char ***’ but argument is of type ‘char ***’
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c: In function ‘Itk_CreateGenericOpt’:
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:4129:49: error: passing argument 4 of ‘tclStubsPtr->tcl_SplitList’ from incompatible pointer type [-Wincompatible-pointer-types]
4129 | result = Tcl_SplitList(interp, info, &optc, &optv);
| ^~~~~
| |
| char ***
/home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD/generic/itk_archetype.c:4129:49: note: expected ‘const char ***’ but argument is of type ‘char ***’
make[5]: *** [CMakeFiles/itk3.4.dir/build.make:107: CMakeFiles/itk3.4.dir/generic/itk_archetype.c.o] Error 1
make[4]: *** [CMakeFiles/Makefile2:90: CMakeFiles/itk3.4.dir/all] Error 2
make[3]: *** [Makefile:136: all] Error 2
CMake Error at /home/rossberg/Devel/BRL-CAD/build/bext/Debug/itk/ITK_BLD-prefix/src/ITK_BLD-stamp/ITK_BLD-build-Debug.cmake:47 (message):
Stopping after outputting logs.
make[2]: *** [itk/CMakeFiles/ITK_BLD-install.dir/build.make:83: itk/ITK_BLD-prefix/src/ITK_BLD-stamp/ITK_BLD-build] Eror 1
make[1]: *** [CMakeFiles/Makefile2:3729: itk/CMakeFiles/ITK_BLD-install.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
In my eyes, this is a bug in the gcc 14 compiler.
The errors can be suppressed by explicit casts or compiler switch.
Constness mismatch -- either something the newer compiler is just doing for fun, or there's some difference in build flags under the hood. Either way, easy enough to patch on our end since that older itk is out of sync constwise with tcl - I just added a patch for that error to itk. Are there more?
Sean said:
Constness mismatch -- either something the newer compiler is just doing for fun, or there's some difference in build flags under the hood. Either way, easy enough to patch on our end since that older itk is out of sync constwise with tcl - I just added a patch for that error to itk. Are there more?
Yes, there where more. I'll test again and report - maybe tomorrow.
I tested bext on MS Windows with the latest Visual Studio 2026 Community version.
Submodule 'itk3/itk' (https://github.com/BRL-CAD/itk) registered for path 'itk'
Cloning into 'C:/Users/rossberg/Documents/Devel/BRL-CAD/bext/itk/itk'...
fatal: unable to access 'https://github.com/BRL-CAD/itk/': Recv failure: Connection was reset
fatal: Fetched in submodule path 'itk', but it did not contain 0d1dc9780c59c2b81e78a1351652fd4488fe67c0. Direct fetching of that commit failed.
CMake Error: File C:/Users/rossberg/Documents/Devel/BRL-CAD/bext/itk/itk/license.terms does not exist.
CMake Error at itk/CMakeLists.txt:96 (configure_file):
configure_file Problem configuring file
From https://github.com/BRL-CAD/itk
* branch 0d1dc9780c59c2b81e78a1351652fd4488fe67c0 -> FETCH_HEAD
Submodule path 'itk': checked out '0d1dc9780c59c2b81e78a1351652fd4488fe67c0'
Network issue? Shouldn't be, but can't rule out.
"Connection was reset" is typically a network issue (or an app crash or corruption causing a crash), but not usually anything on our end. Unless you can confirm it's reproducible, I'm seeing the same sha but error-free of course.
Next gcc 14 error message:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c: In function ‘propertyValuesSetColor’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c:1186:67: error: passing argument 2 of ‘getInheritPointer’ from incompatible pointer type [-Wincompatible-pointer-types]
1186 | HtmlColor **pInherit = (HtmlColor **)getInheritPointer(p, pCVar);
| ^~~~~
| |
| HtmlColor **
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c:1033:65: note: expected ‘unsigned char *’ but argument is of type ‘HtmlColor **’
1033 | getInheritPointer (HtmlComputedValuesCreator *p, unsigned char *pVar)
| ~~~~~~~~~~~~~~~^~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c: In function ‘propertyValuesSetSize’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c:1689:61: error: passing argument 2 of ‘getInheritPointer’ from incompatible pointer type [-Wincompatible-pointer-types]
1689 | int *pInherit = (int *)getInheritPointer(p, pIVal);
| ^~~~~
| |
| int *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmlprop.c:1033:65: note: expected ‘unsigned char *’ but argument is of type ‘int *’
1033 | getInheritPointer (HtmlComputedValuesCreator *p, unsigned char *pVar)
| ~~~~~~~~~~~~~~~^~~~
I added (unsigned char*) casts.
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c: In function ‘rowGroupIterate’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c:1158:31: error: passing argument 2 of ‘rowIterate’ from incompatible pointer type [-Wincompatible-pointer-types]
1158 | rowIterate(pTree, &sRow, p);
| ^~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c:1061:40: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
1061 | rowIterate (HtmlTree *pTree, HtmlNode *pNode, RowIterateContext *p)
| ~~~~~~~~~~^~~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c: In function ‘tableIterate’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c:1284:36: error: passing argument 2 of ‘rowGroupIterate’ from incompatible pointer type [-Wincompatible-pointer-types]
1284 | rowGroupIterate(pTree, &sRowGroup, &sRowContext);
| ^~~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltable.c:1118:45: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
1118 | rowGroupIterate (HtmlTree *pTree, HtmlNode *pNode, RowIterateContext *p)
| ~~~~~~~~~~^~~~~
I added (HtmlNode*) casts.
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c: In function ‘fragmentAddElement’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:3078:40: error: passing argument 2 of ‘implicitCloseCount’ from incompatible pointer type [-Wincompatible-pointer-types]
3078 | implicitCloseCount(pTree, pFragment->pCurrent, eType, &nClose);
| ~~~~~~~~~^~~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:123:48: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
123 | implicitCloseCount (HtmlTree *pTree, HtmlNode *pCurrent, int eTag, int *pNClose)
| ~~~~~~~~~~^~~~~~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:3108:46: error: passing argument 2 of ‘nodeHandlerCallbacks’ from incompatible pointer type [-Wincompatible-pointer-types]
3108 | nodeHandlerCallbacks(pTree, pFragment->pCurrent);
| ~~~~~~~~~^~~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:468:50: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
468 | nodeHandlerCallbacks (HtmlTree *pTree, HtmlNode *pNode)
| ~~~~~~~~~~^~~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c: In function ‘fragmentAddClosingTag’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:3122:25: error: passing argument 1 of ‘explicitCloseCount’ from incompatible pointer type [-Wincompatible-pointer-types]
3122 | explicitCloseCount(p->pCurrent, eType, zType, &nClose);
| ~^~~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:94:15: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
94 | HtmlNode *pCurrent, /* Node currently being constructed */
| ~~~~~~~~~~^~~~~~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:3125:38: error: passing argument 2 of ‘nodeHandlerCallbacks’ from incompatible pointer type [-Wincompatible-pointer-types]
3125 | nodeHandlerCallbacks(pTree, p->pCurrent);
| ~^~~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:468:50: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
468 | nodeHandlerCallbacks (HtmlTree *pTree, HtmlNode *pNode)
| ~~~~~~~~~~^~~~~
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c: In function ‘HtmlParseFragment’:
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:3150:45: error: passing argument 2 of ‘nodeHandlerCallbacks’ from incompatible pointer type [-Wincompatible-pointer-types]
3150 | nodeHandlerCallbacks(pTree, sContext.pCurrent);
| ~~~~~~~~^~~~~~~~~
| |
| HtmlElementNode *
/home/rossberg/Devel/BRL-CAD/bext/tkhtml/tkhtml/src/htmltree.c:468:50: note: expected ‘HtmlNode *’ but argument is of type ‘HtmlElementNode *’
468 | nodeHandlerCallbacks (HtmlTree *pTree, HtmlNode *pNode)
| ~~~~~~~~~~^~~~~
I added (HtmlNode*) casts.
That's all.
Last updated: Jun 06 2026 at 02:08 UTC