Friday, January 22, 2016

CMake + MSVC Frustrations - Solutions Wanted

It's been several weeks since Blender switched over to CMake. While some teething troubles while adapting to a new setup are to be expected, some are more disruptive than others... and it's usually these that are the ones that won't go away!

Having used this new setup for a few weeks, unfortunately, I have to say that there are a few quirks with this new CMake + MSVC setup which are currently very much inferior to my old setup with Scons + Mingw. (Part of the pain has been spared by the fact that I'm working on a pet project in a separate branch that I've purposefully left in a pre-scons-removal state... it will stay that way for as long as possible). If anyone is aware of any solutions to any of these problems, do let me know!




1) Corrupted Builds - The situation here is a bit ludicrous! In the past 3 or so weeks, I've ended up needing to do some 5-10 "clean builds" (i.e. delete the directories/make clean/etc., then do a full build again) on numerous occasions for various reasons. Over the past decade with scons+mingw however, I've only needed to do this sort of thing once every 2-4 years!

The situation has come up due to various issues, such as:
   - Some precompiled library got updated or build flags changed. But, I can't seem to get CMake to regenerate the gunk to force it to use the new stuff. So... recompile!  [Frequency - 1-2 times a week it seems]

   - I've just kicked off a compile, and then realise while waiting for it to get through some checks of modules that haven't changed that I made a small mistake in one file. (Worse is when this error is in a frequently used header file, like DNA_scene_types.h or one of the BLI ones... if you touch one of those, you basically need to recompile most but not all of Blender, so it takes a while... ack!). With scons, I'd just abort the build right then and there, fix the issue, and restart the compile again with barely a second thought. However, with CMake + MSVC, this is a death sentence for the build. Particularly bad is if it had already started compiling some other files, as by aborting, it will not properly recompile the file it was working on, but when starting the build again, the aborted file will no longer be considered for recompiling. So.... you get a build with mixed states, and weird non-deterministic behaviour all of a sudden :/     [Frequency - HIGH. I do this a lot]

   - A few other random times when some weirdness happens, and I just need to make it rebuild everything again for good measure.  [Frequency - Once a fortnight or so I guess]

This one is quite bad, as it's currently something I cannot predict or control! It's pretty much randomly unreliable, which sucks pretty bad, as you could go from waiting for a short fix-compile-test cycle, to suddenly needing to wait a few minutes as the machine goes off to grill another few steaks.


2) Updating Blender's Bundled Scripts...
This is perhaps the biggest bottleneck I have right now, and is a mixture of several different problems.

  a) Verbosity
For whatever reason, the "install" target (which performs the copying of all needed stuffs from your source tree and libs folders to the place where the built binaries reside) prints a LOT of redundant stuff to the screen... and printing long lines of text like this makes builds slow!

First, it seems run CMake again, which proceeds to scan all the Blender modules, reporting that each one of these is up to date and doesn't need to be included in whatever mischief we're getting up to.

Then, it goes through each of the VS project files for each of those modules, and again reports that all of those are fine (or actually how those map to compiled .lib files)

Then, it finally starts checking on which files it's supposed to copy over, and which are fine already. Enter more "-- Up to date:  <long path to some file>"

... and so on... until it may, by chance stumble across a file you've updated, in which case it will then copy it over.

   b) Stupid unpacking of Python (with no option to turn it off), Every. Single. Time.
About halfway through the file status checking process, it gets to a point where it goes: "let's extract all the python libraries". At which point, it starts doing, *this*:
-- Extracting Python to: C:/blenderdev/master2/build/bin/Release/2.76/python
x bin/


x bin/msvcp120.dll


x bin/msvcr120.dll


x bin/python.exe


x bin/vcomp120.dll


x lib/


x lib/abc.py


x lib/aifc.py


x lib/antigravity.py


x lib/argparse.py


x lib/ast.py


x lib/asynchat.py


x lib/asyncio/


x lib/asyncio/base_events.py


x lib/asyncio/base_subprocess.py


x lib/asyncio/compat.py


x lib/asyncio/constants.py


x lib/asyncio/coroutines.py


x lib/asyncio/events.py


x lib/asyncio/futures.py


x lib/asyncio/locks.py


x lib/asyncio/log.py
          ... <snipped for your sanity> ...

I kid you not! It does this every bloody time this thing runs. AFAIK, there's no way to turn this off (unlike in scons... but there, it didn't really matter so much if it did/didn't unpack, as since it didn't print about each and every file it unpacked, it didn't really matter at all in the end).

(After this, it then proceeds to check the status of the "lib/site-packages" stuff, and also duly notes that everything was already up to date)

    c) WHY does it need to run cmake and go through all the vs project files for the main binary again?! They're not bloody needed, and won't affect anything!  When this thing runs (and it needs to run, if you've done changes on both sides - both in C/C++ and Python), it usually has just compiled that stuff... and now it's doing it again!

    d) There isn't really any nice way to make it "just" grab the changed scripts and dump them in the release folder. It has to go through all this verbose printing and sluggish extracting every single time. Gah!

With scons, I'd set it up so that I could just do "sgc scripts" if I updated the Py scripts. That would bypass compiling the main binary, but still do the script copying stuff at the end, except that since scons was more sensible about what it reported, this ended up being a much more efficient process!  i.e.
python scons\scons.py BF_TOOLSET=mingw WITH_BF_NOBLENDER=1 BF_QUICK=xxxJUSTSKIPEVERYTHING

This one is a BIG issue for productivity at the moment. It's bloody annoying too.


3) Recompiling just a few modules to quickly iterate on a bug fix
Often when working on things, my work is confined to a particular submodule (e.g. editors/animation or editors/gpencil or blenkernel). With scons, I could do "sgc quicky editors" or "sgc quicky anim" or "sgc quicky arm"   ("sgc quicky"  being an alias for "python scons\scons.py BF_TOOLSET=mingw BF_QUICK=..."). Currently with CMake + MSVC (via the terminal), I can't do this.

This is not as critical as the other items. Waiting a bit longer to iterate on the compile-test-fix cycle is not such a biggie... I can just pretend it's a slower machine or heavier codebase. Besides, the waiting isn't too draggy in this case.



4) Build errors don't fail immediately
Another annoying quirk made worse by the verbosity of the thing is that if a file errors out for any reason, the build process just carries right on, until it's compiled mostly everything else it can handle. Then, and only then when the final link fails, does it report build failure. On the plus side, errors are in red here, making it a bit easier to find them in the sea of noise.

This is just a mild annoyance. Less convenient, but not critical to getting stuff done.

(EDIT: Apparently this is an annoying limitation of msbuild that devs have frequently asked MS for, with no success to date. Get your act together MS!)

No comments:

Post a Comment