From fb891f33da3428602d765905b1395a9a7e798e4a Mon Sep 17 00:00:00 2001 From: Rafael Cardoso Fernandes Sousa Date: Wed, 24 Nov 2021 14:07:28 -0600 Subject: [PATCH] Fix the cmake parser to identify more patterns --- cmake/utils.cmake | 196 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 149 insertions(+), 47 deletions(-) diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 01b489f2a..c5ee65384 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -15,35 +15,83 @@ endfunction () # Reads a Makefile into CMake vars. macro(ParseMakefileVars MAKEFILE_IN) message(STATUS "Reading vars from ${MAKEFILE_IN}...") - set (IfElse 0) - set (ElseSeen 0) + set (C_COMPILER ${CMAKE_C_COMPILER_ID}) + set (IfElse 0) + set (ElseSeen 0) + set (SkipIfs 0) + set (SkipElse 0) file(STRINGS ${MAKEFILE_IN} makefile_contents) foreach (makefile_line ${makefile_contents}) -#message(STATUS "parsing ${makefile_line}") - if (${IfElse} GREATER 0) + #message(STATUS "parsing ${makefile_line}") + # 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}") if (NOT "${line_match}" STREQUAL "") -# message(STATUS "ENDIF ${makefile_line}") - set (IfElse 0) - set (ElseSeen 0) + if (${SkipIfs} EQUAL 0) + set (SkipElse 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 () endif () string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}") - if (NOT "${line_match}" STREQUAL "") -# message(STATUS "ELSE ${makefile_line}") - set (ElseSeen 1) - continue () - endif() - if ( (${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR ( ${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1)) -# message(STATUS "skipping ${makefile_line}") - continue () + if (NOT "${line_match}" STREQUAL "") + if (${SkipIfs} EQUAL 0) + #message(STATUS "ELSE ${makefile_line}") + set (ElseSeen 1) + else () + #message(STATUS "skipping ${makefile_line}") + endif () + 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 () + # 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}") 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_value ${CMAKE_MATCH_2}) + #set(var_value ${CMAKE_MATCH_2}) string(STRIP ${CMAKE_MATCH_2} var_value) # check for Makefile variables in the string, e.g. $(TSUFFIX) 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}) endforeach () set(${var_name} ${var_value}) - else () - string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}") - if (NOT "${line_match}" STREQUAL "") -#message(STATUS "match on include ${line_match}") - ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1}) - else () -# message(STATUS "unmatched line ${line_match}") - string(REGEX MATCH "ifeq \\(\\$\\(([_A-Z]+)\\),[ \t]*([0-9_A-Z]+)\\)" line_match "${makefile_line}") - if (NOT "${line_match}" STREQUAL "") -# message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_2}") - if (DEFINED ${${CMAKE_MATCH_1}} AND ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2}) -# message (STATUS "condition is true") - set (IfElse 1) - else () - set (IfElse 2) - endif () + continue () + endif () + # Include a new file to be parsed + string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}") + if (NOT "${line_match}" STREQUAL "") + #message(STATUS "match on include ${line_match}") + ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1}) + continue () + endif () + # The if statement that precedes this else has the path taken + # Thus, this else statement has to be skipped. + string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}") + if (NOT "${line_match}" STREQUAL "") + #message(STATUS "skipping ${makefile_line}") + set (SkipElse 1) + 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 () - string(REGEX MATCH "ifneq \\(\\$\\(([_A-Z]+)\\),[ \t]*([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_2}") - if ( ${CMAKE_MATCH_1} STREQUAL C_COMPILER) - set (CMAKE_MATCH_1 CMAKE_C_COMPILER) - endif () - if (NOT ( ${${CMAKE_MATCH_1}} STREQUAL ${CMAKE_MATCH_2})) -# message (STATUS "condition is true") - set (IfElse 1) - else () - set (IfElse 2) - endif () - endif () + set (IfElse 2) + endif () + else () + if (${CMAKE_MATCH_1} STREQUAL "ifdef") + set (IfElse 2) + else () + #message (STATUS "condition is true") + set (IfElse 1) endif () endif () + continue () 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 () endmacro ()