-
-
Save tusharpm/d71dd6cab8a00320ddb48cc82bf7f64c to your computer and use it in GitHub Desktop.
# Simple CMake utility to read variables from MK files | |
# - Gets contents from given file (name or path) | |
# - Parses the assignment statements | |
# - Makes the same assignments in the PARENT_SCOPE | |
if(POLICY CMP0007) | |
cmake_policy(SET CMP0007 NEW) | |
endif() | |
function(ReadVariables MKFile) | |
file(READ "${MKFile}" FileContents) | |
string(REPLACE "\\\n" "" FileContents ${FileContents}) | |
string(REPLACE "\n" ";" FileLines ${FileContents}) | |
list(REMOVE_ITEM FileLines "") | |
foreach(line ${FileLines}) | |
string(REPLACE "=" ";" line_split ${line}) | |
list(LENGTH line_split count) | |
if (count LESS 2) | |
message(STATUS "Skipping ${line}") | |
continue() | |
endif() | |
list(GET line_split -1 value) | |
string(STRIP ${value} value) | |
separate_arguments(value) | |
list(REMOVE_AT line_split -1) | |
foreach(var_name ${line_split}) | |
string(STRIP ${var_name} var_name) | |
set(${var_name} ${value} PARENT_SCOPE) | |
endforeach() | |
endforeach() | |
endfunction() |
# An example usage of the ReadVariables function | |
# Do this once in the project's top CMakeLists.txt | |
include(ReadVariables.cmake) | |
# Use the following from subdirectories as required | |
# CAUTION: this sets variables in the current scope (directory/function) | |
ReadVariables(opus_sources.mk) | |
message("OPUS_SOURCES: ${OPUS_SOURCES}") |
Thanks for the comment. I had ended up not using this script after all and left it on gist for future readers.
From your comments:
- The first one is straightforward to fix: quote
${value}
in line 23; i.e.:string(STRIP "${value}" value)
. - The second one is longer:
+=
is only one of the other assignments available in makefiles. I didn't have a need for it at the time of writing this function. While what you suggest could be done, I wouldn't recommend using CMake for parsing any text beyond the simplest of assignments.
Hi and thank you for your reply, I've only now got back to our CMake project where I used this function.
I've had tried to use the quotes you mentioned in line 23, but it didnt got rid of the # comment at the end of the line, so I ended up using this line right after line 23:
string(REGEX REPLACE "#.*" "" value ${value})
Which basically removes the # and everything after it on the same line, effectively ignoring comments on the line which is what I needed.
So if we got a line like this:
VAR1 = VALUE # THIS VALUE IS VERY IMPORTANT
Then string(REGEX REPLACE "#.*" "" value ${value}) will ignore the comment on the line and still take the VALUE as usual.
The 2nd one about += I ended up not using/needing as you suggested.
Thank you very much for your help!
I realize this is bringing up the dead :)
I changed the two lines for the outer for loop to
foreach(rawLine ${FileLines})
string(REGEX REPLACE "#.*" "" line ${rawLine})
Since any comment should be truncated. this way if the line is
.... # var = foo
nothing is done
Very nice job, it works well, 2 things that I found is that for variables that are set to nothing i.e.
MYVAR =
without a space after the =
It gives an error that STRIP requires 2 arguments.
Also this does not seem to work with +=
So something like this doesn't work:
abc = 1
abc += 1
doesnt give abc == 2, same for strings, it doesnt concatenate them.
but other than that this is pretty useful, thanks.