How to generate CMakeLists.txt?

Viewed 107447

I need some pointers/advice on how to automatically generate CMakeLists.txt files for CMake. Does anyone know of any existing generators? I've checked the ones listed in the CMake Wiki but unfortunately they are not suitable for me.

I already have a basic Python script which traverses my project's directory structure and generates the required files but it's really "dumb" right now. I would like to augment it to take into account for example the different platforms I'm building for, the compiler\cross-compiler I'm using or different versions of the libraries dependencies I might have. I don't have much\expert experience with CMake and an example I could base my work or an already working generator could be of great help.

8 Answers

I'm maintaining a C++ software environment that has more than 1000 modules (shared, static libraries, programs) and uses more than 20 third parties (boost, openCV, Qt, Qwt...). This software environment hosts many programs (~50), each one picking up some libraries, programs and third parties. I use CMake to generate the makefiles and that's really great.

However, if you write your CMakeLists.txt as it is recommended to do (declare the module as being a library/program, importing source files, adding dependencies...). I agree with celavek: maintaining those CMakeLists.txt files is a real pain:

  • When you add a new file to a module, you need to update its CMakeLists.txt
  • When you upgrade a third party, you need to update the CMakeLists.txt of all modules using it
  • When you add a new dependency (library A now needs library B), you may need to update the CMakeLists.txt of all programs using A
  • When you want a new global settings to be changed (compiler setting, predefined variable, C++ standard used), you need to update all your CMakeLists.txt

Then, I see two strategies to adress those issues and likely the one mentioned by OP.

1- Have CMakeLists.txt be well written and be smart enough not to have a frozen behaviourto update themselves on the fly. That's what we have in our software environment. Each module has a standardized file organization (sources are in src folder, includes are in inc folder...) and have simple text files to specify their dependencies (with keywords we defined, like QT to say the module needs to link with Qt). Then, our CMakeLists.txt is a two-line file and simply calls a cmake macro we wrote to automatically setup the module. As a MCVE that would be:

CMakeLists.txt:

include( utl.cmake )
add_module( "mylib", lib )

utl.cmake:

macro( add_module name what )
    file(GLOB_RECURSE source_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
    if ( what STREQUEL "lib" )
        add_library( ${name} SHARED ${source_files} )
    elseif ( what STREQUEL "prg" )
        add_executable( ${name} ${source_files} )
    endif()
    # TODO: Parse the simple texts files to add target_link_libraries accordingly
endmacro()

Then, for all situations exposed above, you simply need to update utl.cmake, not the thousand of CMakeLists.txt you have...

Honestly, we are very happy with this approach, the system becomes very easy to maintain and we can easily add new dependencies, upgrade third parties, change some build/dependency strategies...

However, there remains a lot of CMake scripts to be written. And CMake script language sucks...the tool's very powerful, right, but the script's variable scope, the cache, the painful and not so well documented syntax (just to check if a list is empty you must ask for it's size and store this in a variable!), the fact it's not object oriented...make it a real pain to maintain.

So, I'm now convinced the real good approach may be to:

2- completly generate the CMakeLists.txt from a more powerful language like Python. The Python script would do things similar to what our utl.cmake does, instead it would generate a CMakeLists.txt ready to be passed CMake tool (with a format as proposed in HelloWorld, no variable, no function....it would only call standard CMake function).

I doubt such generic tool exists, because it's hard to produce the CMakeLists.txt files that will make everyone happy, you'll have to write it yourself. Note that gen-cmake does that (generates a CMakeLists.txt), but in a very primitive way and it apparently only supports Linux, but it may be a good start point.

This is likely to be the v2 of our software environment...one day.

Note : Additionally, if you want to support both qmake and cmake for instance, a well written Python script could generate both CMakeLists and pro files on demand!

Maybe this could be helpful:

https://conan.io/

The author has given some speeches about cmake and how to create modular projects using cmake into CPPCon. As far as I know, this tool require cmake, so that I suppose that generate it when you integrate new packages, or create new packages. Recently I read something about how to write a higher level description of the C/C++ project using a YAML file, but not sure if it is part of conan or not (what I read was from the author of conan). I have never used, and it is something pending for me, so that, please if you use it and fit your needs, comment your opinions about it and how it fit your scenario.

I was looking for such a generator but at the end I decided to write my own (partly because I wanted to understand how CMake works):

https://github.com/Aenteas/cmake-generator

It has a couple of additional features such as creating python wrappers (SWIG).

Writing a generator that suits everyone is impossible but I hope it will give you an idea in case you want to make your customized version.

Related