diff --git a/Meta/CMake/serenity_components.cmake b/Meta/CMake/serenity_components.cmake new file mode 100644 index 0000000000..d2b5d475a0 --- /dev/null +++ b/Meta/CMake/serenity_components.cmake @@ -0,0 +1,90 @@ +# +# Target properties and functions for optionally building libraries and applications +# + +define_property(TARGET PROPERTY SERENITY_COMPONENT_NAME BRIEF_DOCS "SerenityOS component name" FULL_DOCS "-") +define_property(TARGET PROPERTY SERENITY_COMPONENT_DESCRIPTION BRIEF_DOCS "SerenityOS component description" FULL_DOCS "-") +define_property(TARGET PROPERTY SERENITY_COMPONENT_RECOMMENDED BRIEF_DOCS "SerenityOS component recommended (flag)" FULL_DOCS "-") +define_property(TARGET PROPERTY SERENITY_COMPONENT_REQUIRED BRIEF_DOCS "SerenityOS component required (flag)" FULL_DOCS "-") +define_property(TARGET PROPERTY SERENITY_COMPONENT_DEPENDS BRIEF_DOCS "SerenityOS component dependencies" FULL_DOCS "-") + +function(serenity_component name) + cmake_parse_arguments(PARSE_ARGV 1 SERENITY_COMPONENT "RECOMMENDED;REQUIRED" "DESCRIPTION" "TARGETS;DEPENDS") + string(TOUPPER "${name}" NAME_UPPER) + option("BUILD_${NAME_UPPER}" "Build ${name}" "${SERENITY_COMPONENT_RECOMMENDED}") + add_custom_target("Component${name}") + set_target_properties( + "Component${name}" PROPERTIES + SERENITY_COMPONENT_NAME "${name}" + SERENITY_COMPONENT_DESCRIPTION "${SERENITY_COMPONENT_DESCRIPTION}" + SERENITY_COMPONENT_RECOMMENDED "${SERENITY_COMPONENT_RECOMMENDED}" + SERENITY_COMPONENT_REQUIRED "${SERENITY_COMPONENT_REQUIRED}" + SERENITY_COMPONENT_DEPENDS "${SERENITY_COMPONENT_DEPENDS}" + ) + if(NOT "${SERENITY_COMPONENT_TARGETS}" STREQUAL "") # note: one component is /bin/false, which makes this tricky + foreach(target IN LISTS SERENITY_COMPONENT_TARGETS) + add_dependencies("Component${name}" "${target}") + endforeach() + endif() + if(BUILD_EVERYTHING OR "${BUILD_${NAME_UPPER}}" OR SERENITY_COMPONENT_REQUIRED) + add_dependencies(components "Component${name}") + endif() + foreach(dependency IN LISTS SERENITY_COMPONENT_DEPENDS) + add_dependencies("Component${name}" "Component${dependency}") + endforeach() +endfunction() + +function(export_components_helper file_name current_dir) + get_property(sub_dirs DIRECTORY "${current_dir}" PROPERTY SUBDIRECTORIES) + foreach(sub_dir IN LISTS sub_dirs) + export_components_helper("${file_name}" "${sub_dir}") + endforeach() + + get_property(targets DIRECTORY "${current_dir}" PROPERTY BUILDSYSTEM_TARGETS) + foreach(target IN LISTS targets) + get_target_property(type "${target}" TYPE) + if (type STREQUAL "INTERFACE_LIBRARY") + continue() # Custom properties are not allowed to be set on INTERFACE libaries + endif() + get_target_property(component_name "${target}" SERENITY_COMPONENT_NAME) + if(NOT "${component_name}" STREQUAL "") + get_target_property(component_name "${target}" SERENITY_COMPONENT_NAME) + get_target_property(component_description "${target}" SERENITY_COMPONENT_DESCRIPTION) + get_target_property(component_recommended "${target}" SERENITY_COMPONENT_RECOMMENDED) + get_target_property(component_required "${target}" SERENITY_COMPONENT_REQUIRED) + get_target_property(component_depends "${target}" SERENITY_COMPONENT_DEPENDS) + file(APPEND "${file_name}" "[${component_name}]\n") + file(APPEND "${file_name}" "description=${component_description}\n") + if(component_recommended) + file(APPEND "${file_name}" "recommended=1\n") + else() + file(APPEND "${file_name}" "recommended=0\n") + endif() + if(component_required) + file(APPEND "${file_name}" "required=1\n") + else() + file(APPEND "${file_name}" "required=0\n") + endif() + string(TOUPPER "${component_name}" component_name_upper) + if("${BUILD_${component_name_upper}}") + file(APPEND "${file_name}" "user_selected=1\n") + else() + file(APPEND "${file_name}" "user_selected=0\n") + endif() + + file(APPEND "${file_name}" "depends=${component_depends}\n") + file(APPEND "${file_name}" "\n") + endif() + endforeach() +endfunction() + +function(export_components file_name) + file(WRITE "${file_name}" "[Global]\n") + if(BUILD_EVERYTHING) + file(APPEND "${file_name}" "build_everything=1\n") + else() + file(APPEND "${file_name}" "build_everything=0\n") + endif() + file(APPEND "${file_name}" "\n") + export_components_helper("${file_name}" "${CMAKE_CURRENT_SOURCE_DIR}") +endfunction() diff --git a/Meta/CMake/utils.cmake b/Meta/CMake/utils.cmake index 9243304f71..e2a88b2375 100644 --- a/Meta/CMake/utils.cmake +++ b/Meta/CMake/utils.cmake @@ -1,3 +1,6 @@ + +include(${CMAKE_CURRENT_LIST_DIR}/serenity_components.cmake) + function(serenity_install_headers target_name) file(GLOB_RECURSE headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") foreach(header ${headers}) @@ -134,86 +137,6 @@ function(serenity_app target_name) endif() endfunction() -define_property(TARGET PROPERTY SERENITY_COMPONENT_NAME BRIEF_DOCS "SerenityOS component name" FULL_DOCS "-") -define_property(TARGET PROPERTY SERENITY_COMPONENT_DESCRIPTION BRIEF_DOCS "SerenityOS component description" FULL_DOCS "-") -define_property(TARGET PROPERTY SERENITY_COMPONENT_RECOMMENDED BRIEF_DOCS "SerenityOS component recommended (flag)" FULL_DOCS "-") -define_property(TARGET PROPERTY SERENITY_COMPONENT_REQUIRED BRIEF_DOCS "SerenityOS component required (flag)" FULL_DOCS "-") -define_property(TARGET PROPERTY SERENITY_COMPONENT_DEPENDS BRIEF_DOCS "SerenityOS component dependencies" FULL_DOCS "-") - -function(serenity_component name) - cmake_parse_arguments(SERENITY_COMPONENT "RECOMMENDED;REQUIRED" "DESCRIPTION" "TARGETS;DEPENDS" ${ARGN}) - string(TOUPPER "${name}" NAME_UPPER) - option("BUILD_${NAME_UPPER}" "Build ${name}" ${SERENITY_COMPONENT_RECOMMENDED}) - add_custom_target("Component${name}") - set_property(TARGET "Component${name}" PROPERTY SERENITY_COMPONENT_NAME ${name}) - set_property(TARGET "Component${name}" PROPERTY SERENITY_COMPONENT_DESCRIPTION ${SERENITY_COMPONENT_DESCRIPTION}) - set_property(TARGET "Component${name}" PROPERTY SERENITY_COMPONENT_RECOMMENDED ${SERENITY_COMPONENT_RECOMMENDED}) - set_property(TARGET "Component${name}" PROPERTY SERENITY_COMPONENT_REQUIRED ${SERENITY_COMPONENT_REQUIRED}) - set_property(TARGET "Component${name}" PROPERTY SERENITY_COMPONENT_DEPENDS ${SERENITY_COMPONENT_DEPENDS}) - if(NOT "${SERENITY_COMPONENT_TARGETS}" STREQUAL "") - foreach(target IN LISTS SERENITY_COMPONENT_TARGETS) - add_dependencies("Component${name}" "${target}") - endforeach() - endif() - if(BUILD_EVERYTHING OR BUILD_${NAME_UPPER} OR SERENITY_COMPONENT_REQUIRED) - add_dependencies(components "Component${name}") - endif() - foreach(dependency ${SERENITY_COMPONENT_DEPENDS}) - add_dependencies("Component${name}" "Component${dependency}") - endforeach() -endfunction() - -macro(export_components_helper file_name current_dir) - get_property(sub_dirs DIRECTORY ${current_dir} PROPERTY SUBDIRECTORIES) - foreach(sub_dir ${sub_dirs}) - export_components_helper(${file_name} ${sub_dir}) - endforeach() - - get_property(targets DIRECTORY ${current_dir} PROPERTY BUILDSYSTEM_TARGETS) - foreach(target ${targets}) - get_property(component_name TARGET ${target} PROPERTY SERENITY_COMPONENT_NAME) - if(NOT "${component_name}" STREQUAL "") - get_property(component_name TARGET ${target} PROPERTY SERENITY_COMPONENT_NAME) - get_property(component_description TARGET ${target} PROPERTY SERENITY_COMPONENT_DESCRIPTION) - get_property(component_recommended TARGET ${target} PROPERTY SERENITY_COMPONENT_RECOMMENDED) - get_property(component_required TARGET ${target} PROPERTY SERENITY_COMPONENT_REQUIRED) - get_property(component_depends TARGET ${target} PROPERTY SERENITY_COMPONENT_DEPENDS) - file(APPEND ${file_name} "[${component_name}]\n") - file(APPEND ${file_name} "description=${component_description}\n") - if(component_recommended) - file(APPEND ${file_name} "recommended=1\n") - else() - file(APPEND ${file_name} "recommended=0\n") - endif() - if(component_required) - file(APPEND ${file_name} "required=1\n") - else() - file(APPEND ${file_name} "required=0\n") - endif() - string(TOUPPER "${component_name}" component_name_upper) - if(BUILD_${component_name_upper}) - file(APPEND ${file_name} "user_selected=1\n") - else() - file(APPEND ${file_name} "user_selected=0\n") - endif() - - file(APPEND ${file_name} "depends=${component_depends}\n") - file(APPEND ${file_name} "\n") - endif() - endforeach() -endmacro() - -function(export_components file_name) - file(WRITE ${file_name} "[Global]\n") - if(BUILD_EVERYTHING) - file(APPEND ${file_name} "build_everything=1\n") - else() - file(APPEND ${file_name} "build_everything=0\n") - endif() - file(APPEND ${file_name} "\n") - export_components_helper(${file_name} ${CMAKE_CURRENT_SOURCE_DIR}) -endfunction() - function(compile_gml source output string_name) set(source ${CMAKE_CURRENT_SOURCE_DIR}/${source}) add_custom_command(