Skip to content

Instantly share code, notes, and snippets.

@tusharpm
Created May 28, 2017 09:58
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tusharpm/d71dd6cab8a00320ddb48cc82bf7f64c to your computer and use it in GitHub Desktop.
Save tusharpm/d71dd6cab8a00320ddb48cc82bf7f64c to your computer and use it in GitHub Desktop.
Reading external Makefile variables (only) into CMake
# 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}")
@gitthub89
Copy link

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.

@tusharpm
Copy link
Author

tusharpm commented Aug 9, 2021

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.

@gitthub89
Copy link

gitthub89 commented Nov 6, 2021

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment