Fixing CMake 3.10.1 to work with Boost 1.66
Wednesday December 20, 2017 09:32:55

I went to use the latest version of Boost yesterday only to find I couldn't make it work. “Hmm,” I thought, "didn't I just sacrifice hours of my life to do this very thing and write a blog post about it so I could remind myself later?"

After digging through CMake's included FindBoost.cmake file it turns out that Boost Build has changed behavior this release to put the architecture and address model into the library names it spits out. So the copious amount of code in FindBoost.cmake looks for a file named boost_coroutine-vc141-mt-gd-1_66 but doesn't find it because in Boost 1.66 that file is named boost_coroutine-vc141-mt-gd-x64-1_66 (the x64 is new) (the docs confirm this).

Second problem: CMake's Find Boost module (FindBoost.cmake) is oddly insistent on *not* defining import library targets for the Boost library if it doesn't know what version of Boost you're using. This is kind of a big deal as it means you can never use a new version of Boost correctly until CMake's authors figure out what is needed for that version of Boost and update FindBoost.cmake themselves.

As a hideous hack, this problem can be worked around as follows:

  1. (UPDATE: there's a way easier way to deal with this, see here for info.) Using a python script, copy all of the binary files (dlls and stuff) to a cenv, renaming them so they no longer contain x64. Here's the script, which must be run from the directory containing the Boost binaries and requires setting the environment variable CGET_PREFIX (which is done automatically for me by my tool Cenv):
    import os
    import shutil
    
    prefix = os.environ['CGET_PREFIX']
    
    for filename in os.listdir('.'):
        if '-x64' in filename:
            new_filename = filename.replace('-x64', '')
            new_path = os.path.join(prefix, 'lib', new_filename)
            print('{} -> {}'.format(filename, new_path))
            shutil.copyfile(filename, new_path)
    

  2. Edit the FindBoost.cmake file (on my machine, it's located at C:\Program Files\CMake\share\cmake-3.10\Modules\FindBoost.cmake) and change the following bit of code:
    if(NOT Boost_VERSION VERSION_LESS 106600)
      message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
      set(_Boost_IMPORTED_TARGETS FALSE)
    endif()
    

    to
    if(NOT Boost_VERSION VERSION_LESS 106600)
      message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
      # set(_Boost_IMPORTED_TARGETS FALSE)
    endif()
    

I'll admit I'm having a hard time understanding why the authors of CMake were so persnickety about only creating the import targets when they themselves had blessed a new Boost version; it would seem to encoruage people using bleeding edge versions of Boost to avoid the import targets in favor of the other variables the Find Boost module spits out, which doesn't seem to fit the spirit of modern CMake.

I'm sure they had their reasons, but I'd argue for users it makes sense to simply alter our own versions of CMake so it will behave as expected and avoid littering our own CMake scripts with workarounds that won't be necessary in a future release of CMake anyway.





<---2017-12-21 09:32:55 history 2017-12-09 09:32:55--->



-All material © 2007 Tim Simpson unless otherwise noted-