Skip to content

Instantly share code, notes, and snippets.

@Ryex
Created February 20, 2025 20:41
Show Gist options
  • Save Ryex/4d808c1917affbc3ff00a873ea7ad010 to your computer and use it in GitHub Desktop.
Save Ryex/4d808c1917affbc3ff00a873ea7ad010 to your computer and use it in GitHub Desktop.
cmake_minimum_required(VERSION 3.15)
if (NOT(CMAKE_SCRIPT_MODE_FILE AND NOT CMAKE_PARENT_LIST_FILE))
message(FATAL_ERROR "UpdateSources.cmake must be run in script mode")
return()
endif()
set(_script_file "${CMAKE_CURRENT_LIST_FILE}")
get_filename_component(_root "${_script_file}" ABSOLUTE) # _root/cmake/UpdateSources.cmake
get_filename_component(_root "${_root}" DIRECTORY) # _root/cmake/
get_filename_component(_root "${_root}" DIRECTORY) # _root/
set(IGNORE_PATHS
libraries
program_info
)
list(TRANSFORM IGNORE_PATHS PREPEND "${_root}/")
message(STATUS "IGNORING: ${IGNORE_PATHS}")
function(UpdateGlobSources _path _additional_paths_var)
set(_file "${_path}/CMakeLists.txt")
message("READING: ${_file}")
file(READ "${_file}" _content)
if(NOT EXISTS "${_file}")
return()
endif()
set(_line "")
set(_output "")
set(_in_sources FALSE)
set(_have_sources FALSE)
set(_sources "")
set(_found "")
set(_updating "")
set(_addtional_paths "")
string(LENGTH "${_content}" _content_len)
foreach(index RANGE 0 ${_content_len})
string(SUBSTRING "${_content}" ${index} 1 current_char)
string(CONCAT _line "${_line}" "${current_char}")
# message("char: ${index} : ${current_char} | line: ${_line}")
if("${current_char}" STREQUAL "\n")
# new line
set(_do_output TRUE)
string(STRIP "${_line}" _line_strip)
# message("STRIP: \"${_line_strip}\"")
if(
(NOT _in_sources)
AND ("${_line_strip}" MATCHES [[^#[ \t]*UPDATE SOURCES (GLOB(_RECURSE)?)[ \t]*(.*)$]])
)
set(_recurse FALSE)
set(_file_cmd "${CMAKE_MATCH_1}")
set(_globs "${CMAKE_MATCH_3}")
separate_arguments(_globs UNIX_COMMAND "${_globs}")
list(TRANSFORM _globs PREPEND "${_path}/" )
message("GLOB_CMD: ${_file_cmd} ${_globs}")
file(${_file_cmd} _sources RELATIVE "${_path}/" ${_globs})
set(_have_sources TRUE)
set(_found "")
message("SOURCES: ${_sources}")
elseif(
_have_sources
AND ("${_line_strip}" MATCHES [[^[Ss][Ee][Tt]\(([A-Za-z0-9_-]+)[ \t]*$]])
)
set(_in_sources TRUE)
message(STATUS "UPDATING: ${CMAKE_MATCH_1}")
set(_updating "${CMAKE_MATCH_1}")
set(_found "")
elseif(
_have_sources
AND ("${_line_strip}" MATCHES [[^[Ss][Ee][Tt]\(([A-Za-z0-9_-]+)[ \t]*(.*)\)$]])
)
set(_do_output FALSE)
message(STATUS "UPDATING: ${CMAKE_MATCH_1}")
set(_updating "${CMAKE_MATCH_1}")
set(_line_sources "${CMAKE_MATCH_2}")
separate_arguments(_line_sources UNIX_COMMAND "${_line_sources}")
set(_found "")
set(_output_sources "")
foreach(_line_source IN LISTS _line_sources)
if("${_line_source}" IN_LIST _sources)
list(APPEND _found "${_line_source}")
string(CONCAT _output_sources "${_output_sources}" " ${_line_source}\n")
endif()
endforeach()
foreach(_source IN LISTS _sources)
if(NOT "${_source}" IN_LIST _found)
string(CONCAT _output_sources "${_output_sources}" " ${_source}\n")
endif()
endforeach()
string(CONCAT _output "${_output}" "set(${_updating}\n${_output_sources})")
elseif(
_in_sources
AND ("${_line_strip}" MATCHES [[^\)[ \t]*$]])
)
set(_in_sources FALSE)
set(_updating "")
foreach(_source IN LISTS _sources)
if(NOT "${_source}" IN_LIST _found)
string(CONCAT _output "${_output}" " ${_source}\n")
endif()
endforeach()
elseif(
_in_sources
AND (NOT "${_line_strip}" MATCHES [[^#]])
AND (NOT "${_line_strip}" STREQUAL "")
)
if("${_line_strip}" IN_LIST _sources)
set(_do_output TRUE)
list(APPEND _found "${_line_strip}")
else()
set(_do_output FALSE)
endif()
elseif(
_have_sources
AND (NOT _in_sources)
)
set(_sources "")
set(_have_sources FALSE)
elseif(
(NOT _in_sources)
AND ("${_line_strip}" MATCHES [[^[Aa][Dd][Dd]_[Ss][Uu][Bb][Dd][Ii][Rr][Ee][Cc][Tt][Oo][Rr][Yy]\((.*)( EXCLUDE_FROM_ALL)?\)$]])
)
list(APPEND _addtional_paths "${_path}/${CMAKE_MATCH_1}")
endif()
if(_do_output)
string(CONCAT _output "${_output}" "${_line}")
endif()
set(_line "")
endif()
endforeach()
set(${_additional_paths_var} ${_addtional_paths} PARENT_SCOPE)
if(NOT "${_output}" STREQUAL "${_content}")
message(STATUS "UPDATE: ${_file} has changed")
file(WRITE "${_file}" "${_output}")
endif()
endfunction(UpdateGlobSources)
list(APPEND _path_stack "${_root}")
while(_path_stack)
list(POP_FRONT _path_stack _cur_path)
message(STATUS "PROCESSING: ${_cur_path}")
UpdateGlobSources("${_cur_path}" _next_paths)
foreach(_path ${_next_paths})
get_filename_component(_parent "${_path}" DIRECTORY) # _root/
get_filename_component(_parent_parent "${_parent}" DIRECTORY) # _root/
if(
(NOT "${_path}" IN_LIST IGNORE_PATHS)
AND (NOT "${_parent}" IN_LIST IGNORE_PATHS)
AND (NOT "${_parent_parent}" IN_LIST IGNORE_PATHS)
)
list(APPEND _path_stack "${_path}")
endif()
endforeach()
endwhile()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment