[CMake] emitting CMakeLists.txt for TRY_COMPILE considered harmful

Brandon J. Van Every bvanevery at gmail.com
Wed Nov 22 03:37:19 EST 2006


Summary: emitting a CMakeLists.txt is never parallel with standard 
coding practices in the toplevel CMakeLists.txt.  At a minimum, this 
causes programmers to do everything 2 different ways.  In the likely 
case, the emission fails because it is fragile as quotes are consumed.  
These kinds of problems can easily chew up a programmer's entire day, as 
I did today.

I need to test whether Darcs source control commands actually work in 
build environments.  It's dicey under Windows because there's no Cygwin 
version of Darcs, just a Windows native version.  That would seem good 
for Windows people, but the Windows Command Prompt, Cygwin shell, MSYS 
shell, and the Visual Studio shell are all distinct build environments.  
They don't share the same search paths, and they don't understand each 
other's path conventions.  So, aiming the right path at the right shell 
and tool is highly problematical.

I have working code for this problem, targeted at CMake 2.4.3.  In that 
version, I simply ducked all the problems.  I used WORKING_DIRECTORY as 
much as possible so that I wouldn't have to use the Darcs 
--repodir=E:\devel\src\chicken command option.  I resorted to such 
workarounds after 3 days of head scratching.  The head scratching did 
have a productive outcome, however: Brad implemented the VERBATIM 
feature in reaction to my problem.  Unfortunately, then I went into 
survival mode and was unable to allocate time to trying out VERBATIM 
while CMake 2.4.4 was still in beta.

Come CMake 2.4.4, I thought I would give VERBATIM a whirl.  Oddly, I was 
unable to get it to do anything constructive.  I started having success 
when I abandoned it, at least at the level of my topmost 
CMakeLists.txt.  Code like the following works fine:

      # NATIVE_PATH reverses slashes and adds quotes for Windows
      NATIVE_PATH(Chicken_SOURCE_DIR NATIVE_CHICKEN_SOURCE_DIR)
      NATIVE_PATH(CHANGELOG_FILE NATIVE_CHANGELOG_FILE)

      ADD_CUSTOM_TARGET(darcs-changelog ALL
        COMMENT "Generating ${NATIVE_CHANGELOG_FILE} from Darcs repository."
        COMMAND ${DARCS_EXE} changes 
--repodir=${NATIVE_CHICKEN_SOURCE_DIR} > ${NATIVE_CHANGELOG_FILE}
      )

But I cannot, for the life of me, emit similar code via a FILE(WRITE ...). 

    SOME_HAIRY_PATH(Chicken_SOURCE_DIR REPO)
   
    FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/try-darcs/CMakeLists.txt "
      PROJECT(try-darcs)
      ADD_CUSTOM_TARGET(try
        COMMAND ${DARCS_EXE} changes --repodir=${REPO} --last=0
      )
    ")

It doesn't matter what function I write for SOME_HAIRY_PATH.  Doesn't 
matter whether I add quotes, a level of escapes, more backslashes, less 
backslashes, anything, everything, nothing.  The problem is, the act of 
emitting a file in and of itself consumes quotes.  I should have strings 
like --repodir=\"E:\devel\src\chicken\" in the above example.  But that 
doesn't work because the single \ are interpreted as escapes for 
letters, giving CMake parse errors.   
--repodir=\"E:\\devel\\src\\chicken\" writes out to the file and doesn't 
generate parse errors, but the \\ aren't transformed into \, they stay 
as \\.  So Darcs barfs on them.

VERBATIM didn't seem to solve this.  Did I miss how it was supposed to 
be used?  Or was FILE(WRITE ...) consumption not considered?


Cheers,
Brandon Van Every



More information about the CMake mailing list