[CMake] Memory cleanup of variables

Naram Qashat cyberbotx at cyberbotx.com
Wed Mar 11 11:41:27 EDT 2009


Bill Hoffman wrote:
> Naram Qashat wrote:
>> Bill Hoffman wrote:
>>> Naram Qashat wrote:
>>>> I have a CMake project that I have been testing with various 
>>>> verisons of CMake 2.4.x and 2.6.x to make sure it works as far back 
>>>> as 2.4.0, due to not knowing what version of CMake our users will be 
>>>> using since a lot of them use shells. In some instances, I have to 
>>>> read lines from a file using a specific regular expression.  With 
>>>> CMake 2.6.x, this works fine using the file(STRINGS) command.  With 
>>>> CMake 2.4.x, though (I haven't checked what versions specifically), 
>>>> after reading in a lot of files, I notice that a "memory exhausted" 
>>>> error comes up. I'm wondering when CMake cleans up the memory it 
>>>> uses, and if there is a way around this problem.  I would prefer not 
>>>> to force our uses to use CMake 2.6.x if their shell provider won't 
>>>> provide them something newer.
>>>>
>>> There may have been leaks in 2.4.X, not really much we can do about 
>>> that now....   What does the your cmake code look like that causes 
>>> the leak?
>>>
>>>
>>> -Bill
>>
>> I believe it is within this macro of mine:
>>
>> macro(read_from_file FILE REGEX STRINGS)
>>   if(CMAKE26_OR_BETTER)
>>     # For CMake 2.6.x or better, we can just use the STRINGS 
>> sub-command to get the lines that match the given regular expression 
>> (if one is given, otherwise get all lines)
>>     if(REGEX STREQUAL "")
>>       file(STRINGS ${FILE} RESULT)
>>     else(REGEX STREQUAL "")
>>       file(STRINGS ${FILE} RESULT REGEX ${REGEX})
>>     endif(REGEX STREQUAL "")
>>   else(CMAKE26_OR_BETTER)
>>     # For CMake 2.4.x, we need to do this manually, firstly we read 
>> the file in
>>     file(READ ${FILE} ALL_STRINGS)
>>     # Next we replace all newlines with semicolons
>>     string(REGEX REPLACE "\n" ";" ALL_STRINGS ${ALL_STRINGS})
>>     if(REGEX STREQUAL "")
>>       # For no regular expression, just set the result to all the lines
>>       set(RESULT ${ALL_STRINGS})
>>     else(REGEX STREQUAL "")
>>       # Clear the result list
>>       set(RESULT)
>>       # Iterate through all the lines of the file
>>       foreach(STRING ${ALL_STRINGS})
>>         # Check for a match against the given regular expression
>>         string(REGEX MATCH ${REGEX} STRING_MATCH ${STRING})
>>         # If we had a match, append the match to the list
>>         if(STRING_MATCH)
>>           append_to_list(RESULT ${STRING})
>>         endif(STRING_MATCH)
>>       endforeach(STRING)
>>     endif(REGEX STREQUAL "")
>>   endif(CMAKE26_OR_BETTER)
>>   # Set the given STRINGS variable to the result
>>   set(${STRINGS} ${RESULT})
>> endmacro(read_from_file)
>>
>> I had done this so I could call the macro and have it work with either 
>> 2.6.x or 2.4.x.
>>
> The only thing I can think of is to call a new cmake process in the loop 
> that does the string match, that way the leak will be contained in that 
> process.
> 
> execute_process(COMMAND ${CMAKE_COMMAND} -DFILE="${FILE}"-P 
> myscript.cmake OUTPUT_VARIABLE OUT)
> 
> myscript.cmake
>  file(READ ${FILE} ALL_STRINGS)
> ...
>   message(${RESULT})
> 
> -Bill

Thanks, that worked very well.  The only problems I had, though, were that the 
quotes were passed to the new invocation of CMake and that I had to use 
ERROR_VARIABLE instead of OUTPUT_VARIABLE, otherwise it works fine.

Thanks,
Naram Qashat


More information about the CMake mailing list