Fix the cmake parser to identify more patterns

This commit is contained in:
Rafael Cardoso Fernandes Sousa 2021-11-24 14:07:28 -06:00
parent ec4daf420f
commit fb891f33da
1 changed files with 149 additions and 47 deletions

View File

@ -15,35 +15,83 @@ endfunction ()
# Reads a Makefile into CMake vars. # Reads a Makefile into CMake vars.
macro(ParseMakefileVars MAKEFILE_IN) macro(ParseMakefileVars MAKEFILE_IN)
message(STATUS "Reading vars from ${MAKEFILE_IN}...") message(STATUS "Reading vars from ${MAKEFILE_IN}...")
set (IfElse 0) set (C_COMPILER ${CMAKE_C_COMPILER_ID})
set (ElseSeen 0) set (IfElse 0)
set (ElseSeen 0)
set (SkipIfs 0)
set (SkipElse 0)
file(STRINGS ${MAKEFILE_IN} makefile_contents) file(STRINGS ${MAKEFILE_IN} makefile_contents)
foreach (makefile_line ${makefile_contents}) foreach (makefile_line ${makefile_contents})
#message(STATUS "parsing ${makefile_line}") #message(STATUS "parsing ${makefile_line}")
if (${IfElse} GREATER 0) # Skip the entire scope of the else statement given that the if statement that precedes it has the valid condition.
# The variable SkipIfs is used to identify which endif statement closes the scope of the else statement.
if (${SkipElse} EQUAL 1)
#message(STATUS "skipping ${makefile_line}")
string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
MATH(EXPR SkipIfs "${SkipIfs}+1")
endif ()
string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}") string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "") if (NOT "${line_match}" STREQUAL "")
# message(STATUS "ENDIF ${makefile_line}") if (${SkipIfs} EQUAL 0)
set (IfElse 0) set (SkipElse 0)
set (ElseSeen 0) else ()
MATH(EXPR SkipIfs "${SkipIfs}-1")
endif ()
endif ()
continue ()
endif ()
# The variable IfElse is greater than 0 if and only if the previously parsed line is an if statement.
if (${IfElse} GREATER 0)
# If the current scope is the one that has to be skipped, the if/endif/else statements
# along with it till the endif that closes the current scope have to be ignored as well.
string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1))
#message(STATUS "skipping ${makefile_line}")
MATH(EXPR SkipIfs "${SkipIfs}+1")
continue ()
endif ()
endif ()
string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
if (${SkipIfs} EQUAL 0)
#message(STATUS "ENDIF ${makefile_line}")
set (IfElse 0)
set (ElseSeen 0)
else ()
#message(STATUS "skipping ${makefile_line}")
MATH(EXPR SkipIfs "${SkipIfs}-1")
endif ()
continue () continue ()
endif () endif ()
string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}") string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "") if (NOT "${line_match}" STREQUAL "")
# message(STATUS "ELSE ${makefile_line}") if (${SkipIfs} EQUAL 0)
set (ElseSeen 1) #message(STATUS "ELSE ${makefile_line}")
continue () set (ElseSeen 1)
endif() else ()
if ( (${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR ( ${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1)) #message(STATUS "skipping ${makefile_line}")
# message(STATUS "skipping ${makefile_line}") endif ()
continue () continue ()
endif()
# Skip the lines that are not part of the path that has to be taken.
if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1) OR (${SkipIfs} GREATER 0))
#message(STATUS "skipping ${makefile_line}")
continue ()
endif () endif ()
endif () endif ()
# Skip commented lines (the ones that start with '#')
string(REGEX MATCH "[ \t]*\\#.*$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "skipping ${makefile_line}")
continue ()
endif ()
string(REGEX MATCH "([0-9_a-zA-Z]+)[ \t]*=[ \t]*(.+)$" line_match "${makefile_line}") string(REGEX MATCH "([0-9_a-zA-Z]+)[ \t]*=[ \t]*(.+)$" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "") if (NOT "${line_match}" STREQUAL "")
#message(STATUS "match on ${line_match}") #message(STATUS "match on ${line_match}")
set(var_name ${CMAKE_MATCH_1}) set(var_name ${CMAKE_MATCH_1})
# set(var_value ${CMAKE_MATCH_2}) #set(var_value ${CMAKE_MATCH_2})
string(STRIP ${CMAKE_MATCH_2} var_value) string(STRIP ${CMAKE_MATCH_2} var_value)
# check for Makefile variables in the string, e.g. $(TSUFFIX) # check for Makefile variables in the string, e.g. $(TSUFFIX)
string(REGEX MATCHALL "\\$\\(([0-9_a-zA-Z]+)\\)" make_var_matches ${var_value}) string(REGEX MATCHALL "\\$\\(([0-9_a-zA-Z]+)\\)" make_var_matches ${var_value})
@ -54,39 +102,93 @@ macro(ParseMakefileVars MAKEFILE_IN)
string(REPLACE "$(${make_var})" "${${make_var}}" var_value ${var_value}) string(REPLACE "$(${make_var})" "${${make_var}}" var_value ${var_value})
endforeach () endforeach ()
set(${var_name} ${var_value}) set(${var_name} ${var_value})
else () continue ()
string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}") endif ()
if (NOT "${line_match}" STREQUAL "") # Include a new file to be parsed
#message(STATUS "match on include ${line_match}") string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}")
ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1}) if (NOT "${line_match}" STREQUAL "")
else () #message(STATUS "match on include ${line_match}")
# message(STATUS "unmatched line ${line_match}") ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1})
string(REGEX MATCH "ifeq \\(\\$\\(([_A-Z]+)\\),[ \t]*([0-9_A-Z]+)\\)" line_match "${makefile_line}") continue ()
if (NOT "${line_match}" STREQUAL "") endif ()
# message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_2}") # The if statement that precedes this else has the path taken
if (DEFINED ${${CMAKE_MATCH_1}} AND ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2}) # Thus, this else statement has to be skipped.
# message (STATUS "condition is true") string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
set (IfElse 1) if (NOT "${line_match}" STREQUAL "")
else () #message(STATUS "skipping ${makefile_line}")
set (IfElse 2) set (SkipElse 1)
endif () continue()
endif()
# Example 1: ifdef HAVE_MSA
# Example 2: ifndef ZNRM2KERNEL
string(REGEX MATCH "(ifdef|ifndef) ([0-9_A-Z]+)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "${CMAKE_MATCH_1} first: ${CMAKE_MATCH_2}")
set (ElseSeen 0)
if (DEFINED ${CMAKE_MATCH_2})
if (${CMAKE_MATCH_1} STREQUAL "ifdef")
#message (STATUS "condition is true")
set (IfElse 1)
else () else ()
string(REGEX MATCH "ifneq \\(\\$\\(([_A-Z]+)\\),[ \t]*([0-9_A-Z]+)\\)" line_match "${makefile_line}") set (IfElse 2)
if (NOT "${line_match}" STREQUAL "") endif ()
# message(STATUS "IFNEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_2}") else ()
if ( ${CMAKE_MATCH_1} STREQUAL C_COMPILER) if (${CMAKE_MATCH_1} STREQUAL "ifdef")
set (CMAKE_MATCH_1 CMAKE_C_COMPILER) set (IfElse 2)
endif () else ()
if (NOT ( ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2})) #message (STATUS "condition is true")
# message (STATUS "condition is true") set (IfElse 1)
set (IfElse 1)
else ()
set (IfElse 2)
endif ()
endif ()
endif () endif ()
endif () endif ()
continue ()
endif () endif ()
# Example 1: ifeq ($(SGEMM_UNROLL_M), 16)
# Example 2: ifeq ($(SGEMM_UNROLL_M)x$(SGEMM_UNROLL_N), 8x8)
# Example 3: ifeq ($(__BYTE_ORDER__)$(ELF_VERSION),__ORDER_BIG_ENDIAN__2)
# Ignore the second group since (?:...) does not work on cmake
string(REGEX MATCH "ifeq \\(\\$\\(([0-9_A-Z]+)\\)(([0-9_A-Za-z]*)\\$\\(([0-9_A-Z]+)\\))?,[ \t]*([0-9_A-Za-z]+)\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4} fourth: ${CMAKE_MATCH_5}")
if (DEFINED ${CMAKE_MATCH_1})
if (DEFINED ${CMAKE_MATCH_4})
set (STR ${${CMAKE_MATCH_1}}${CMAKE_MATCH_3}${${CMAKE_MATCH_4}})
else ()
set (STR ${${CMAKE_MATCH_1}})
endif ()
if (${STR} STREQUAL ${CMAKE_MATCH_5})
#message (STATUS "condition is true")
set (IfElse 1)
continue ()
endif ()
endif ()
set (IfElse 2)
continue ()
endif ()
# Example 1 (Group 3): ifneq ($(SGEMM_UNROLL_M), $(SGEMM_UNROLL_N))
# Example 2 (Group 4): ifneq ($(C_COMPILER), PGI)
string(REGEX MATCH "ifneq \\(\\$\\(([0-9_A-Z]+)\\),[ \t]*(\\$\\(([0-9_A-Z]+)\\)|([0-9_A-Z]+))\\)" line_match "${makefile_line}")
if (NOT "${line_match}" STREQUAL "")
#message(STATUS "IFNEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4}")
set (ElseSeen 0)
set (HasValidGroup 0)
if (DEFINED ${CMAKE_MATCH_3})
set (HasValidGroup 1)
set (STR ${${CMAKE_MATCH_3}})
elseif (NOT ${CMAKE_MATCH_4} STREQUAL "")
set (HasValidGroup 1)
set (STR ${CMAKE_MATCH_4})
endif ()
if (DEFINED ${CMAKE_MATCH_1} AND ${HasValidGroup} EQUAL 1)
if (NOT (${${CMAKE_MATCH_1}} STREQUAL ${STR}))
#message (STATUS "condition is true")
set (IfElse 1)
continue ()
endif ()
endif ()
set (IfElse 2)
continue ()
endif ()
#message(STATUS "unmatched line ${line_match}")
endforeach () endforeach ()
endmacro () endmacro ()