[Cmake] Set a variable to a list of filenames that match a pattern

Karr, David David . Karr at titan . com
Wed, 23 Jul 2003 09:58:47 -0400


I'd like to be able to use a regular expression (or something
similar) to search directories for files and assign the=20
resulting list of files to a variable.  Can I do this in=20
the current version of CMake?


I managed to do what I wanted, but only by modifying the source of
CMake version 1.6.7.  What I did was to add a new variant of the=20
SET command:

   SET(var FILES expr_1 expr_2 expr_3 ... expr_n)

Each of the expressions expr_1 ... expr_n is treated as a regular
expression and is expanded into a list of filenames that match the=20
expression.  The expression may contain a directory path; if so,
everything up to the last '/' character in the expression is=20
included in the path, and this must be a literal string (no=20
wildcards or other pattern-matching).  The path is included in=20
every filename in the resulting list. =20

For example, suppose we have the following files:

  x/CMakeLists.txt
  x/alpha.cpp
  x/bravo.cpp
  x/y/romeo.cpp
  x/y/juliet.cpp

And suppose the contents of CMakeLists.txt are:

  SET(sources FILES *.cpp y/*.cpp)
  MESSSAGE(sources)

Then if we run CMake in the directory x, it prints out

  alpha.cpp;bravo.cpp;y/romeo.cpp;y/juliet.cpp


My motivation for wanting this feature is that I have a
project in which a very large number of files are built=20
in a single library.  I don't want to have so many files in
a single directory, and there are certain groupings of
files I want to maintain, so the files are divided among
several directories in a hierarchy, and in the root of
this hierarchy I want my CMakeLists.txt file to build the
library.  Clearly, I could define some variables literally
in order to accomplish the same goal, for example

  SET(sources alpha.cpp bravo.cpp y/romeo.cpp y/juliet.cpp)

However, I also don't want to have to train every programmer
who ever works in this library (which is every programmer on
the project!) how to modify the CMakeLists.txt file every
time they add or delete a source from the library.  It's=20
easier to train them that to add a class to the library you=20
put the class's source file in the appropriate directory,=20
and to remove a class you delete its source file.  (Also I'm
very lazy in some ways and would like to avoid the task of
adding more than a thousand filenames explicitly to my=20
CMakeLists.txt files in order to port the project to CMake.)


As for how I implemented this, the key points were that if
while processing a SET command, args[1] is "FILES", then for
for i =3D 2, ..., I separate args[i] into a path and a name and
use the Glob function to interpret the name as a regular
expression and make a list of files that match the
name in the indicated directory.  Since Glob assembles the
filenames without any path information in a single string
(with semicolons between filenames), I expand the string to
a vector, and assemble a new string in which I've inserted
the path in front of each filename.


I'd still rather use an existing feature of the generally=20
release CMake if it were reasonably similar.

-- David A. Karr (karr at acm . org)