From b1f603151b36edf9cf59db48eaf15d413e58a5e5 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Tue, 28 Mar 2023 18:44:13 +0200 Subject: [PATCH 1/5] CMake: avoid redundancy - Define variables to hold the actual names. - Add comments about he steps Signed-off-by: Axel Heider --- camkes_vm_helpers.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/camkes_vm_helpers.cmake b/camkes_vm_helpers.cmake index 62de7c05..f991351f 100644 --- a/camkes_vm_helpers.cmake +++ b/camkes_vm_helpers.cmake @@ -70,11 +70,15 @@ function(DefineCAmkESVMFileServer) get_target_property(fileserver_images vm_fserver_config FILES) get_target_property(fileserver_deps vm_fserver_config DEPS) # Build CPIO archive given the defined kernel and rootfs images + set(CPIO_ARCHIVE "file_server_archive.o") include(cpio) - MakeCPIO(file_server_archive.o "${fileserver_images}" DEPENDS "${fileserver_deps}") - add_library(fileserver_cpio STATIC EXCLUDE_FROM_ALL file_server_archive.o) - set_property(TARGET fileserver_cpio PROPERTY LINKER_LANGUAGE C) - ExtendCAmkESComponentInstance(FileServer fserv LIBS fileserver_cpio) + MakeCPIO("${CPIO_ARCHIVE}" "${fileserver_images}" DEPENDS "${fileserver_deps}") + # Build a library from the CPIO archive + set(FILESERVER_LIB "fileserver_cpio") + add_library("${FILESERVER_LIB}" STATIC EXCLUDE_FROM_ALL "${CPIO_ARCHIVE}") + set_property(TARGET "${FILESERVER_LIB}" PROPERTY LINKER_LANGUAGE C) + # Add the CPIO-library to the FileServer component + ExtendCAmkESComponentInstance(FileServer fserv LIBS "${FILESERVER_LIB}") endfunction(DefineCAmkESVMFileServer) # Function for declaring the CAmkESVM root server. Taking the camkes application From 13e9c808956f5edcd5689f8809c335bc57f5f31b Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Wed, 6 Jul 2022 13:38:17 +0200 Subject: [PATCH 2/5] CMake: extend file server functions - allow custom type and instance names - allow passing files for DefineCAmkESVMFileServer(), this avoids calling AddToFileServer() - AddToFileServer() becomes just a light wrapper - use instance specific name for archive and lib Signed-off-by: Axel Heider --- camkes_vm_helpers.cmake | 251 +++++++++++++++++++++++++++++++++------- 1 file changed, 210 insertions(+), 41 deletions(-) diff --git a/camkes_vm_helpers.cmake b/camkes_vm_helpers.cmake index f991351f..5d1840d6 100644 --- a/camkes_vm_helpers.cmake +++ b/camkes_vm_helpers.cmake @@ -63,22 +63,175 @@ function(DeclareCAmkESVM init_component) ) endfunction(DeclareCAmkESVM) +# # Function defines a CAmkESVMFileServer using the declared fileserver images # and fileserver dependencies. These images are placed into a CPIO archive. +# +# Parameters: +# +# TYPE +# Type of the file server CAmkES component. +# Optional, defaults to "FileServer" +# +# INSTANCE +# Instance name of the file server CAmkES component. +# Optional, defaults to "fserv" +# +# FILES [ [...]] +# The files to be added. Each item has the form [:], where +# the optional allows using a different name for the file in the +# archive than on the disk. The build will abort if is not found. +# Each item can either be a single file item or a CMake list of items (such a +# CMake list is basically a string with elements separated by ';'). This +# allows building lists of files in advance, which may contain different files +# for different configurations. An empty string as item is also explicitly +# allowed for convenience reasons. Thus supports cases where a an item does +# not exist in every configuration and the respective CMake variable used for +# the item is just left empty. +# +# DEPENDS [ [...]] +# Any additional dependencies for the file/image the caller is adding to the +# file server +# +# function(DefineCAmkESVMFileServer) - # Retrieve defined kernel images, rootfs images and extraction dependencies - get_target_property(fileserver_images vm_fserver_config FILES) - get_target_property(fileserver_deps vm_fserver_config DEPS) - # Build CPIO archive given the defined kernel and rootfs images - set(CPIO_ARCHIVE "file_server_archive.o") + + cmake_parse_arguments( + PARSE_ARGV + 0 + PARAM # variable prefix + "" # option arguments + "TYPE;INSTANCE" # optional single value arguments + "FILES;DEPENDS" # optional multi value arguments + ) + + if(PARAM_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown arguments: ${PARAM_UNPARSED_ARGUMENTS}") + endif() + + if(NOT PARAM_TYPE) + set(PARAM_TYPE "FileServer") + endif() + + if(PARAM_INSTANCE) + set(FSRV_TARGET "${PARAM_INSTANCE}_config") + else() + set(PARAM_INSTANCE "fserv") + set(FSRV_TARGET "vm_fserver_config") + endif() + + # The target might exist already when AddToFileServer() was called. + if(NOT TARGET ${FSRV_TARGET}) + add_custom_target(${FSRV_TARGET}) + endif() + + # For dependencies and files, both lists and lists of list are supported for + # convenience reasons. Furthermore, empty entries are also allowed. This + # can happen when the caller uses variables for the lists, when in some + # configurations the lists remain empty. + + foreach(element IN LISTS PARAM_DEPENDS) + foreach(item IN LISTS element) + if(item) + set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY DEPS ${item}) + endif() + endforeach() + endforeach() + + foreach(element IN LISTS PARAM_FILES) + foreach(item IN LISTS element) # [:] + if(item) + string( + REGEX + MATCH + "^([^:]+)(:([^:]+))?$" + cpio_item + "${item}" + ) + if(NOT cpio_item) + message(FATAL_ERROR "invalid parameter format: '${item}'") + endif() + if(CMAKE_MATCH_3) + set(CPIO_NAME "${CMAKE_MATCH_1}") + set(FILE_NAME "${CMAKE_MATCH_3}") + else() + set(FILE_NAME "${CMAKE_MATCH_1}") + get_filename_component(CPIO_NAME "${FILE_NAME}" NAME) + endif() + set_property( + TARGET ${FSRV_TARGET} + APPEND + PROPERTY FILES "${CPIO_NAME}:${FILE_NAME}" + ) + endif() + endforeach() + endforeach() + + # now process the file/deps list + get_target_property(files ${FSRV_TARGET} FILES) + if(NOT files) # this also catches "files-NOTFOUND" if property is not set + set(files "") + endif() + get_target_property(deps ${FSRV_TARGET} DEPS) + if(NOT deps) # this also catches "deps-NOTFOUND" if property is not set + set(deps "") + endif() + + set(CPIO_FILES "") + foreach(item IN LISTS files) # : + string( + REGEX + MATCH + "^([^:]+):([^:]+)$" + cpio_item + "${item}" + ) + if(NOT cpio_item) + message(FATAL_ERROR "invalid CPIO file format: '${item}'") + endif() + set(CPIO_NAME "${CMAKE_MATCH_1}") + set(FILE_NAME "${CMAKE_MATCH_2}") + set(CPIO_FILE "${PARAM_INSTANCE}/files/${CPIO_NAME}") + add_custom_command( + OUTPUT "${CPIO_FILE}" + COMMENT "copy: ${FILE_NAME} -> ${CPIO_FILE}" + COMMAND + ${CMAKE_COMMAND} -E copy "${FILE_NAME}" "${CPIO_FILE}" + VERBATIM + DEPENDS ${FILE_NAME} ${deps} + ) + # There is no need to create an explicit target for the command above, + # the archive creation depends on all files in CPIO_FILES, where the + # command above is the creation rule for each one. + list(APPEND CPIO_FILES "${CPIO_FILE}") + endforeach() + + # Build CPIO archive. It implicitly depends on all files in CPIO_FILES, + # which have their own dependencies each from above. So we don't have any + # additional explicit dependencies here. + # Unfortunately MakeCPIO() currently allows passing plain file names only, + # it does not support paths. Thus, the archive will be created in the built + # output root folder, having it the instance specific subfolder would be a + # bit cleaner actually. + set(CPIO_ARCHIVE "${PARAM_INSTANCE}_cpio_archive.o") include(cpio) - MakeCPIO("${CPIO_ARCHIVE}" "${fileserver_images}" DEPENDS "${fileserver_deps}") - # Build a library from the CPIO archive - set(FILESERVER_LIB "fileserver_cpio") + # Due to the way MakeCPIO() is implemented, the file list must have absolute + # paths. Since we don't require CMake 3.12+ yet, we can't use the list + # transformation functions, but have to prepend each element manually. + set(CPIO_FILES_FQN "") + foreach(f IN LISTS CPIO_FILES) + list(APPEND CPIO_FILES_FQN "${CMAKE_CURRENT_BINARY_DIR}/${f}") + endforeach() + MakeCPIO("${CPIO_ARCHIVE}" "${CPIO_FILES_FQN}") + + # Build a library from the CPIO archive. Ensure the lib has a unique name + # within the project, as there could be more than one file server. + set(FILESERVER_LIB "${PARAM_INSTANCE}_file_archive_cpio") add_library("${FILESERVER_LIB}" STATIC EXCLUDE_FROM_ALL "${CPIO_ARCHIVE}") set_property(TARGET "${FILESERVER_LIB}" PROPERTY LINKER_LANGUAGE C) # Add the CPIO-library to the FileServer component - ExtendCAmkESComponentInstance(FileServer fserv LIBS "${FILESERVER_LIB}") + ExtendCAmkESComponentInstance("${PARAM_TYPE}" "${PARAM_INSTANCE}" LIBS "${FILESERVER_LIB}") + endfunction(DefineCAmkESVMFileServer) # Function for declaring the CAmkESVM root server. Taking the camkes application @@ -105,40 +258,56 @@ function(DeclareCAmkESVMRootServer camkes_config) endfunction(DeclareCAmkESVMRootServer) # Function for adding a file/image to the vm file server. -# filename_pref: The name the caller wishes to use to reference the file in the CPIO archive. This -# corresponds with the name set in the 'kernel_image' camkes variable for a given instance vm. -# file_dest: The location of the file/image the caller is adding to the file server -# DEPENDS: Any additional dependencies for the file/image the caller is adding to the -# file server +# +# Parameters: +# +# +# The name the caller wishes to use to reference the file in the CPIO archive. +# This corresponds with the name set in the 'kernel_image' camkes variable for +# a given instance vm. +# +# +# The location of the file/image the caller is adding to the file server +# +# INSTANCE +# Instance name of the file server CAmkES component. +# Optional, defaults to "fserv" +# +# DEPENDS [ [...]] +# Any additional dependencies for the file/image the caller is adding to the +# file server +# function(AddToFileServer filename_pref file_dest) - # Get any existing dependencies when adding the image into the file server archive - cmake_parse_arguments(PARSE_ARGV 2 CAMKES_FILESERVER "" "" "DEPENDS") - if(NOT "${CAMKES_FILESERVER_UNPARSED_ARGUMENTS}" STREQUAL "") - message(FATAL_ERROR "Unknown arguments to AddToFileServer") - endif() - # Create a copy of the file in the binary directory to the callers - # preferred name - add_custom_command( - OUTPUT file_server/${filename_pref} - COMMAND - ${CMAKE_COMMAND} -E copy "${file_dest}" - "${CMAKE_CURRENT_BINARY_DIR}/file_server/${filename_pref}" - VERBATIM - DEPENDS ${file_dest} ${CAMKES_FILESERVER_DEPENDS} - ) - #Create custom target for copy command - add_custom_target( - copy_${filename_pref} - DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/file_server/${filename_pref}" - ) - # Store the rootfs file location. Used when building the CPIO at a later stage - set_property( - TARGET vm_fserver_config - APPEND - PROPERTY FILES "${CMAKE_CURRENT_BINARY_DIR}/file_server/${filename_pref}" + + cmake_parse_arguments( + PARSE_ARGV + 2 + PARAM # variable prefix + "" # option arguments + "INSTANCE" # optional single value arguments + "DEPENDS" # optional multi value arguments ) - # Append soft link dependency - set_property(TARGET vm_fserver_config APPEND PROPERTY DEPS "copy_${filename_pref}") + + if(PARAM_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown arguments: ${PARAM_UNPARSED_ARGUMENTS}") + endif() + + if(PARAM_INSTANCE) + set(FSRV_TARGET "${PARAM_INSTANCE}_config") + else() + set(FSRV_TARGET "vm_fserver_config") + endif() + + if(NOT TARGET ${FSRV_TARGET}) + add_custom_target(${FSRV_TARGET}) + endif() + + set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY FILES "${filename_pref}:${file_dest}") + + if(PARAM_DEPENDS) + set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY DEPS ${PARAM_DEPENDS}) + endif() + endfunction(AddToFileServer) # Function for decompressing/extracting a vmlinux file from a given kernel image From 02a93576a6e5ecc106cafed8b0ebacd9686c687d Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Wed, 12 Apr 2023 18:43:47 +0200 Subject: [PATCH 3/5] CMake: don't create empty target by default The target will be created automatically when either the function DefineCAmkESVMFileServer() or AddToFileServer() is called. There is no gain creating an empty target that might never be used. Signed-off-by: Axel Heider --- camkes_vm_helpers.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/camkes_vm_helpers.cmake b/camkes_vm_helpers.cmake index 5d1840d6..6a398d07 100644 --- a/camkes_vm_helpers.cmake +++ b/camkes_vm_helpers.cmake @@ -7,9 +7,6 @@ cmake_minimum_required(VERSION 3.8.2) set(VM_PROJECT_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "") -if(NOT TARGET vm_fserver_config) - add_custom_target(vm_fserver_config) -endif() # Function for declaring a CAmkESVM. This is called for each Init component in the applications # camkes config. From 747533df482c522a7e0254ef283a94286d39271c Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Wed, 12 Apr 2023 19:02:29 +0200 Subject: [PATCH 4/5] CMake: remove AddToFileServer() With the new interface of DefineCAmkESVMFileServer() there is not need to have AddToFileServer(). CMake lists with files can be built instead and then passed to DefineCAmkESVMFileServer(). Signed-off-by: Axel Heider --- camkes_vm_helpers.cmake | 122 ++++++---------------------------------- 1 file changed, 16 insertions(+), 106 deletions(-) diff --git a/camkes_vm_helpers.cmake b/camkes_vm_helpers.cmake index 6a398d07..42b513f2 100644 --- a/camkes_vm_helpers.cmake +++ b/camkes_vm_helpers.cmake @@ -110,16 +110,8 @@ function(DefineCAmkESVMFileServer) set(PARAM_TYPE "FileServer") endif() - if(PARAM_INSTANCE) - set(FSRV_TARGET "${PARAM_INSTANCE}_config") - else() + if(NOT PARAM_INSTANCE) set(PARAM_INSTANCE "fserv") - set(FSRV_TARGET "vm_fserver_config") - endif() - - # The target might exist already when AddToFileServer() was called. - if(NOT TARGET ${FSRV_TARGET}) - add_custom_target(${FSRV_TARGET}) endif() # For dependencies and files, both lists and lists of list are supported for @@ -127,10 +119,11 @@ function(DefineCAmkESVMFileServer) # can happen when the caller uses variables for the lists, when in some # configurations the lists remain empty. + set(DEPS "") foreach(element IN LISTS PARAM_DEPENDS) foreach(item IN LISTS element) if(item) - set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY DEPS ${item}) + list(APPEND DEPS "${item}") endif() endforeach() endforeach() @@ -155,54 +148,24 @@ function(DefineCAmkESVMFileServer) set(FILE_NAME "${CMAKE_MATCH_1}") get_filename_component(CPIO_NAME "${FILE_NAME}" NAME) endif() - set_property( - TARGET ${FSRV_TARGET} - APPEND - PROPERTY FILES "${CPIO_NAME}:${FILE_NAME}" + set(CPIO_FILE "${PARAM_INSTANCE}/files/${CPIO_NAME}") + add_custom_command( + OUTPUT "${CPIO_FILE}" + COMMENT "copy: ${FILE_NAME} -> ${CPIO_FILE}" + COMMAND + ${CMAKE_COMMAND} -E copy "${FILE_NAME}" "${CPIO_FILE}" + VERBATIM + DEPENDS ${FILE_NAME} ${DEPS} ) + # There is no need to create an explicit target for the command + # above, because the archive creation depends on all files + # listed in CPIO_FILES. The command above is the creation rule + # for each one. + list(APPEND CPIO_FILES "${CPIO_FILE}") endif() endforeach() endforeach() - # now process the file/deps list - get_target_property(files ${FSRV_TARGET} FILES) - if(NOT files) # this also catches "files-NOTFOUND" if property is not set - set(files "") - endif() - get_target_property(deps ${FSRV_TARGET} DEPS) - if(NOT deps) # this also catches "deps-NOTFOUND" if property is not set - set(deps "") - endif() - - set(CPIO_FILES "") - foreach(item IN LISTS files) # : - string( - REGEX - MATCH - "^([^:]+):([^:]+)$" - cpio_item - "${item}" - ) - if(NOT cpio_item) - message(FATAL_ERROR "invalid CPIO file format: '${item}'") - endif() - set(CPIO_NAME "${CMAKE_MATCH_1}") - set(FILE_NAME "${CMAKE_MATCH_2}") - set(CPIO_FILE "${PARAM_INSTANCE}/files/${CPIO_NAME}") - add_custom_command( - OUTPUT "${CPIO_FILE}" - COMMENT "copy: ${FILE_NAME} -> ${CPIO_FILE}" - COMMAND - ${CMAKE_COMMAND} -E copy "${FILE_NAME}" "${CPIO_FILE}" - VERBATIM - DEPENDS ${FILE_NAME} ${deps} - ) - # There is no need to create an explicit target for the command above, - # the archive creation depends on all files in CPIO_FILES, where the - # command above is the creation rule for each one. - list(APPEND CPIO_FILES "${CPIO_FILE}") - endforeach() - # Build CPIO archive. It implicitly depends on all files in CPIO_FILES, # which have their own dependencies each from above. So we don't have any # additional explicit dependencies here. @@ -254,59 +217,6 @@ function(DeclareCAmkESVMRootServer camkes_config) ) endfunction(DeclareCAmkESVMRootServer) -# Function for adding a file/image to the vm file server. -# -# Parameters: -# -# -# The name the caller wishes to use to reference the file in the CPIO archive. -# This corresponds with the name set in the 'kernel_image' camkes variable for -# a given instance vm. -# -# -# The location of the file/image the caller is adding to the file server -# -# INSTANCE -# Instance name of the file server CAmkES component. -# Optional, defaults to "fserv" -# -# DEPENDS [ [...]] -# Any additional dependencies for the file/image the caller is adding to the -# file server -# -function(AddToFileServer filename_pref file_dest) - - cmake_parse_arguments( - PARSE_ARGV - 2 - PARAM # variable prefix - "" # option arguments - "INSTANCE" # optional single value arguments - "DEPENDS" # optional multi value arguments - ) - - if(PARAM_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown arguments: ${PARAM_UNPARSED_ARGUMENTS}") - endif() - - if(PARAM_INSTANCE) - set(FSRV_TARGET "${PARAM_INSTANCE}_config") - else() - set(FSRV_TARGET "vm_fserver_config") - endif() - - if(NOT TARGET ${FSRV_TARGET}) - add_custom_target(${FSRV_TARGET}) - endif() - - set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY FILES "${filename_pref}:${file_dest}") - - if(PARAM_DEPENDS) - set_property(TARGET ${FSRV_TARGET} APPEND PROPERTY DEPS ${PARAM_DEPENDS}) - endif() - -endfunction(AddToFileServer) - # Function for decompressing/extracting a vmlinux file from a given kernel image # decompress_target: The target name the caller wishes to use to generate the decompressed kernel # image From 5dae754b76d1f406dfe9f65584cd634378ea470c Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Thu, 13 Apr 2023 01:43:37 +0200 Subject: [PATCH 5/5] CMake: use dedicated folder for archive and lib Put the file server CPIO archive and lib in a dedicated folder to avoid "polluting" the build output root folder. Signed-off-by: Axel Heider --- camkes_vm_helpers.cmake | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/camkes_vm_helpers.cmake b/camkes_vm_helpers.cmake index 42b513f2..48e96beb 100644 --- a/camkes_vm_helpers.cmake +++ b/camkes_vm_helpers.cmake @@ -169,11 +169,7 @@ function(DefineCAmkESVMFileServer) # Build CPIO archive. It implicitly depends on all files in CPIO_FILES, # which have their own dependencies each from above. So we don't have any # additional explicit dependencies here. - # Unfortunately MakeCPIO() currently allows passing plain file names only, - # it does not support paths. Thus, the archive will be created in the built - # output root folder, having it the instance specific subfolder would be a - # bit cleaner actually. - set(CPIO_ARCHIVE "${PARAM_INSTANCE}_cpio_archive.o") + set(CPIO_ARCHIVE "${PARAM_INSTANCE}/cpio_archive.o") include(cpio) # Due to the way MakeCPIO() is implemented, the file list must have absolute # paths. Since we don't require CMake 3.12+ yet, we can't use the list @@ -184,11 +180,20 @@ function(DefineCAmkESVMFileServer) endforeach() MakeCPIO("${CPIO_ARCHIVE}" "${CPIO_FILES_FQN}") - # Build a library from the CPIO archive. Ensure the lib has a unique name - # within the project, as there could be more than one file server. + # Build a library from the CPIO archive. Even if put in the lib in an + # instance specific output folder, the lib's name has to be unique within + # the project, because it is also used as CMake target. set(FILESERVER_LIB "${PARAM_INSTANCE}_file_archive_cpio") add_library("${FILESERVER_LIB}" STATIC EXCLUDE_FROM_ALL "${CPIO_ARCHIVE}") - set_property(TARGET "${FILESERVER_LIB}" PROPERTY LINKER_LANGUAGE C) + set_target_properties( + "${FILESERVER_LIB}" + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY + "${PARAM_INSTANCE}" + LINKER_LANGUAGE + "C" + ) + # Add the CPIO-library to the FileServer component ExtendCAmkESComponentInstance("${PARAM_TYPE}" "${PARAM_INSTANCE}" LIBS "${FILESERVER_LIB}")