Syndicate content

Writing a Shell Script from cmake

In cmake, you have a cool feature which allows you to create a file.

First you use a WRITE, then you use the APPEND to add more lines to the file.

That file may be a shell script, though. In that case, you run in a problem whenever you want to write a variable which uses the curly brackets (as in ${TEST}), because cmake sees those as its own variables.

There is an example of script that we use in our Snap! development.

file( WRITE  ${lint_script} "#!${BASH}\n"                                                            )
file( APPEND ${lint_script} "if test \${3##*.} = 'dtd'; then\n" )
file( APPEND ${lint_script} "  ${XMLLINT} --dtdvalid $3 --output $2 $1 && exit 0 || (rm $2; exit 1)\n" )
file( APPEND ${lint_script} "else\n" )
file( APPEND ${lint_script} "  ${XMLLINT} --schema $3 --output $2 $1 && exit 0 || (rm $2; exit 1)\n" )
file( APPEND ${lint_script} "fi\n" )

As we can see, we have many variables defined and used here.

The $1, $2, and $3 are the usual first, second and third parameters specified on the command line when calling the script.

The ${XMLLINT} variable is set by cmake with a find_program() call:

find_program( XMLLINT xmllint /usr/bin )

The ${BASH} variable is similar, we look for the location of the bash shell script and use the variable to generate the script from cmake.

However, $3 represents a path and a filename with an extension. We expect .dtd or .xsd as the extension of that file. Since it is dynamic and various calls to the script may use various setup, the script extracts the extension and then compares it with the 'dtd' string. To extract the string, we use the special shell syntax:


Which says: "Remove everything up to the last period and the last period."

Here we have a problem because the cmake interpretor wants to convert the ${3##*.} with the contents of the variable named "3##*." and that's not considered a valid name as per cmake so it generates an error and bails out.

To palliate to that problem, we have to escape the { character as we have shown in our first example:


and then cmake will write "${3##*.}", without the backslash (\), to the output file.


Syndicate content

Diverse Realty

Diverse Realty Team

Want a New Home?
Want to Sell Your House?

Call Alex at
+1 (916)
220 6482

Alexis Wilke, Realtor
Lic. # 02024063

Cory Marcus, Broker
Lic. # 01079165


Terms of Site Index

Find the page/content you are looking for with our index.

  • FIFO
    First In, First Out--This is another way to speak of a pipe or ring buffer. On one side, there is a generator that pushes data in and on the other side you have another program that reads the data sent by the generator. The data comes out in the same order it was pushed in. Usually the data are bytes, but it should be a short, long or even a complete event or object.
  • Gb

    Giga bytes--these days, the common measure for memory and disk space. It changed in the last 20 years from Kb (Kilo bytes) to Mb (Mega bytes) and to Gb. With disks, we are close to Tb (Tera bytes) and some people talk about Pb (Peta bytes).

  • Made to Order Software

    Made to Order Software is my company. m2osw for short. We offer many different types of software including some for Drupal (the CMS used for this very site.)

  • PHP
  • svn