spl-core 7.9.0__tar.gz → 7.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spl_core-7.9.0 → spl_core-7.11.0}/PKG-INFO +2 -1
- {spl_core-7.9.0 → spl_core-7.11.0}/pyproject.toml +2 -1
- spl_core-7.11.0/src/spl_core/__init__.py +1 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/common.cmake +91 -13
- spl_core-7.11.0/src/spl_core/test_utils/artifacts_archiver.py +318 -0
- spl_core-7.9.0/src/spl_core/__init__.py +0 -1
- {spl_core-7.9.0 → spl_core-7.11.0}/LICENSE +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/README.md +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/__run.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/common/__init__.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/common/path.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/conan.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/config/KConfig +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/gcov_maid/__init__.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/gcov_maid/gcov_maid.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kconfig/__init__.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kconfig/kconfig.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kconfig.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/__init__.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/create.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/.vscode/cmake-variants.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/KConfig +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/CMakeLists.txt +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/doc/_images/screenshot.png +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/doc/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/src/greeter.c +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/src/greeter.h +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/greeter/test/test_greeter.cc +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/main/CMakeLists.txt +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/main/doc/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/main/src/main.c +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/test/EnglishVariant/test__EnglishVariant.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/test/German/test__GermanVariant.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/variants/EnglishVariant/config.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/variants/EnglishVariant/parts.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/variants/GermanVariant/config.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/variants/GermanVariant/config.txt +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/variants/GermanVariant/parts.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.gitignore +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/cmake-kits.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/extensions.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/launch.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/settings.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/tasks.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/CMakeLists.txt +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/README.md +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/bootstrap.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/build.bat +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/build.ps1 +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/conf.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/Doxyfile.in +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/common/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/components/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/doxygen-awesome/LICENSE +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/doxygen-awesome/doxygen-awesome.css +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/software_architecture/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/software_requirements/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/test_report_template.txt +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/index.rst +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/pypeline.yaml +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/pyproject.toml +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/pytest.ini +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/scoopfile.json +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/tools/toolchains/clang/toolchain.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/tools/toolchains/gcc/toolchain.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/main.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/spl.cmake +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/steps/collect_pr_changes.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/test_utils/archive_artifacts_collection.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/test_utils/base_variant_test_runner.py +0 -0
- {spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/test_utils/spl_build.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: spl-core
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.11.0
|
|
4
4
|
Summary: Software Product Line Support for CMake
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Avengineers
|
|
@@ -23,6 +23,7 @@ Requires-Dist: kconfiglib (>=14.1,<15.0)
|
|
|
23
23
|
Requires-Dist: mlx-traceability (>=10.0,<11.0)
|
|
24
24
|
Requires-Dist: myst-parser (>=0.16)
|
|
25
25
|
Requires-Dist: py-app-dev (>=2.1,<3.0)
|
|
26
|
+
Requires-Dist: py7zr (>=1.0.0,<2.0.0)
|
|
26
27
|
Requires-Dist: pypeline-runner (>=1,<=2)
|
|
27
28
|
Requires-Dist: pypeline-semantic-release (>=0.4.1,<=0.5.0)
|
|
28
29
|
Requires-Dist: sphinx (>=7.3,<8.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "spl-core"
|
|
3
|
-
version = "7.
|
|
3
|
+
version = "7.11.0"
|
|
4
4
|
description = "Software Product Line Support for CMake"
|
|
5
5
|
authors = ["Avengineers <karsten.guenther@kamg.de>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -48,6 +48,7 @@ sphinx-book-theme = "^1.1"
|
|
|
48
48
|
sphinx-design = ">=0.5,<0.7"
|
|
49
49
|
pypeline-semantic-release = ">=0.4.1,<=0.5.0"
|
|
50
50
|
pypeline-runner = ">=1,<=2"
|
|
51
|
+
py7zr = "^1.0.0"
|
|
51
52
|
|
|
52
53
|
[tool.poetry.group.dev.dependencies]
|
|
53
54
|
pytest = ">=7,<9"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "7.11.0"
|
|
@@ -10,31 +10,81 @@ macro(_spl_get_absolute_path out in)
|
|
|
10
10
|
endif()
|
|
11
11
|
endmacro()
|
|
12
12
|
|
|
13
|
+
# SPL_ADD_COMPONENT
|
|
14
|
+
#
|
|
15
|
+
# Arguments:
|
|
16
|
+
#
|
|
17
|
+
# component_path - the path to the component's directory
|
|
18
|
+
# [target_executable] - (optional) name of the target executable. This is the second argument of the macro.
|
|
19
|
+
#
|
|
20
|
+
# Needs to know:
|
|
21
|
+
#
|
|
22
|
+
# component_path - because it must call add_subdirectory to the component's directory
|
|
23
|
+
# target_executable
|
|
24
|
+
# - required to determine the build directory for the component (one can not call add_subdirectory
|
|
25
|
+
# for the same component multiple times with the same build directory)
|
|
26
|
+
# - must be set to the "global" scope because it is required in spl_create_component to append it to the component name.
|
|
27
|
+
# spl_create_component gets to decide the component name and will make it "global" for this macro to read it back.
|
|
28
|
+
#
|
|
13
29
|
macro(spl_add_component component_path)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
add_subdirectory(${CMAKE_SOURCE_DIR}/${component_path})
|
|
30
|
+
set(target_executable "${ARGV1}")
|
|
31
|
+
message(DEBUG "spl_add_component: component_path=${component_path}, target_executable=${target_executable}")
|
|
17
32
|
|
|
18
|
-
|
|
33
|
+
# Set global variables for spl_create_component
|
|
34
|
+
unset(GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE)
|
|
35
|
+
if("${target_executable}" STREQUAL "")
|
|
36
|
+
set(target_executable ${LINK_TARGET_NAME})
|
|
37
|
+
add_subdirectory(${CMAKE_SOURCE_DIR}/${component_path})
|
|
38
|
+
else()
|
|
39
|
+
set(GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE "${target_executable}")
|
|
40
|
+
add_subdirectory(${CMAKE_SOURCE_DIR}/${component_path} "${CMAKE_BINARY_DIR}/${target_executable}/${component_path}")
|
|
41
|
+
endif()
|
|
42
|
+
# Add the newly created component to the linked libraries
|
|
43
|
+
if(TARGET ${GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME})
|
|
19
44
|
if(BUILD_KIT STREQUAL prod)
|
|
20
|
-
target_link_libraries(${
|
|
45
|
+
target_link_libraries(${target_executable} ${GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME})
|
|
21
46
|
endif()
|
|
22
47
|
endif()
|
|
23
48
|
endmacro()
|
|
24
49
|
|
|
50
|
+
# SPL_ADD_NAMED_COMPONENT
|
|
51
|
+
#
|
|
52
|
+
# Arguments:
|
|
53
|
+
#
|
|
54
|
+
# component_name - the name of the component. (!) This macro expects that a CMake variable with this name holds the component path.
|
|
55
|
+
# This means that ${${component_name}} is the component path.
|
|
56
|
+
# [target_executable] - (optional) name of the target executable.
|
|
57
|
+
#
|
|
58
|
+
# Needs to know:
|
|
59
|
+
#
|
|
60
|
+
# component_path - because it must call add_subdirectory to the component's directory
|
|
61
|
+
# target_executable
|
|
62
|
+
# - required to determine the build directory for the component (one can not call add_subdirectory
|
|
63
|
+
# for the same component multiple times without specifying the build directory)
|
|
64
|
+
# - must be set to the "global" scope because it is required in spl_create_component to append it to the component name
|
|
65
|
+
#
|
|
25
66
|
macro(spl_add_named_component component_name)
|
|
26
|
-
|
|
67
|
+
set(target_executable "${ARGV1}")
|
|
27
68
|
set(component_path ${${component_name}})
|
|
69
|
+
if(NOT IS_ABSOLUTE ${component_path})
|
|
70
|
+
set(component_path ${CMAKE_SOURCE_DIR}/${component_path})
|
|
71
|
+
endif()
|
|
72
|
+
message(DEBUG "spl_add_named_component: component_name=${component_name}, component_path=${component_path}, target_executable=${target_executable}")
|
|
28
73
|
|
|
29
|
-
|
|
74
|
+
# Set global variables for spl_create_component
|
|
75
|
+
unset(GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE)
|
|
76
|
+
if("${target_executable}" STREQUAL "")
|
|
77
|
+
set(target_executable ${LINK_TARGET_NAME})
|
|
30
78
|
add_subdirectory(${component_path})
|
|
31
79
|
else()
|
|
32
|
-
|
|
80
|
+
set(GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE "${target_executable}")
|
|
81
|
+
add_subdirectory(${component_path} "${CMAKE_BINARY_DIR}/${target_executable}/${component_name}")
|
|
33
82
|
endif()
|
|
34
83
|
|
|
35
|
-
|
|
84
|
+
# Add the newly created component to the linked libraries
|
|
85
|
+
if(TARGET ${GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME})
|
|
36
86
|
if(BUILD_KIT STREQUAL prod)
|
|
37
|
-
target_link_libraries(${
|
|
87
|
+
target_link_libraries(${target_executable} ${GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME})
|
|
38
88
|
endif()
|
|
39
89
|
endif()
|
|
40
90
|
endmacro()
|
|
@@ -121,6 +171,20 @@ macro(_spl_get_google_test)
|
|
|
121
171
|
enable_testing()
|
|
122
172
|
endmacro(_spl_get_google_test)
|
|
123
173
|
|
|
174
|
+
# SPL_CREATE_COMPONENT
|
|
175
|
+
#
|
|
176
|
+
# Arguments (they are all optional):
|
|
177
|
+
#
|
|
178
|
+
# NAME - Use this as component name instead of define it from the component path.
|
|
179
|
+
# LONG_NAME - A longer name of the component to be used in reports.
|
|
180
|
+
# LIBRARY_TYPE - The type of library to create (e.g., STATIC, SHARED, OBJECT)
|
|
181
|
+
#
|
|
182
|
+
# Needs to know:
|
|
183
|
+
# - target_executable - global variable set by the spl_add_component macros to make sure different component
|
|
184
|
+
# names are used for different executables
|
|
185
|
+
#
|
|
186
|
+
# The component name will be made "global" such that the spl_add_compoent macro can add it to the executable
|
|
187
|
+
#
|
|
124
188
|
macro(spl_create_component)
|
|
125
189
|
cmake_parse_arguments(CREATE_COMPONENT "" "NAME;LONG_NAME;LIBRARY_TYPE" "" ${ARGN})
|
|
126
190
|
|
|
@@ -132,11 +196,22 @@ macro(spl_create_component)
|
|
|
132
196
|
# Determine the unique component name based on the relative path of the component
|
|
133
197
|
file(RELATIVE_PATH component_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_LIST_DIR})
|
|
134
198
|
|
|
199
|
+
unset(GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME)
|
|
135
200
|
if(NOT CREATE_COMPONENT_NAME)
|
|
201
|
+
# The component relative path to the project root dictates the component name
|
|
136
202
|
_spl_slash_to_underscore(component_name ${component_path})
|
|
137
203
|
else()
|
|
204
|
+
# Explicit name provided - use it as-is
|
|
138
205
|
set(component_name ${CREATE_COMPONENT_NAME})
|
|
139
206
|
endif()
|
|
207
|
+
# If there is a custom target executable, prefix the component name
|
|
208
|
+
if(GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE)
|
|
209
|
+
set(component_name ${GLOBAL__SPL_ADD_COMPONENT__TARGET_EXECUTABLE}_${component_name})
|
|
210
|
+
endif()
|
|
211
|
+
# Make the component name public
|
|
212
|
+
set(GLOBAL__SPL_CREATE_COMPONENT__NEW_COMPONENT_NAME ${component_name} PARENT_SCOPE)
|
|
213
|
+
|
|
214
|
+
message(DEBUG "spl_create_component: component_name=${component_name}")
|
|
140
215
|
|
|
141
216
|
# Collect all productive sources for later usage (e.g., in an extension)
|
|
142
217
|
list(APPEND PROD_SOURCES ${SOURCES})
|
|
@@ -193,8 +268,9 @@ macro(spl_create_component)
|
|
|
193
268
|
\"reports_output_dir\": \"\"
|
|
194
269
|
}")
|
|
195
270
|
set(_component_is_header_only FALSE)
|
|
271
|
+
|
|
196
272
|
# If prod and sources or test and test_sources define library. Else make it an interface and set the flag
|
|
197
|
-
if
|
|
273
|
+
if((BUILD_KIT STREQUAL prod AND SOURCES) OR
|
|
198
274
|
(BUILD_KIT STREQUAL test AND TEST_SOURCES))
|
|
199
275
|
add_library(${component_name} ${CREATE_COMPONENT_LIBRARY_TYPE} ${SOURCES})
|
|
200
276
|
else()
|
|
@@ -367,6 +443,7 @@ Code Coverage
|
|
|
367
443
|
# Implicitly add default include directories to provided interfaces
|
|
368
444
|
list(APPEND PROVIDED_INTERFACES ${CMAKE_CURRENT_LIST_DIR}/src)
|
|
369
445
|
list(APPEND PROVIDED_INTERFACES ${CMAKE_CURRENT_BINARY_DIR})
|
|
446
|
+
|
|
370
447
|
# Get rid of duplicates, in case the default directories where explicitly defined
|
|
371
448
|
list(REMOVE_DUPLICATES PROVIDED_INTERFACES)
|
|
372
449
|
|
|
@@ -382,12 +459,13 @@ Code Coverage
|
|
|
382
459
|
# Define the target public interfaces to be used instead of the global include directories.
|
|
383
460
|
if(TARGET ${component_name})
|
|
384
461
|
foreach(interfaceDir IN LISTS PROVIDED_INTERFACES)
|
|
385
|
-
if
|
|
462
|
+
if(_component_is_header_only)
|
|
386
463
|
target_include_directories(${component_name} INTERFACE ${interfaceDir})
|
|
387
464
|
else()
|
|
388
465
|
target_include_directories(${component_name} PUBLIC ${interfaceDir})
|
|
389
466
|
endif()
|
|
390
467
|
endforeach()
|
|
468
|
+
|
|
391
469
|
foreach(component IN LISTS REQUIRED_INTERFACES)
|
|
392
470
|
if(_component_is_header_only)
|
|
393
471
|
target_link_libraries(${component_name} INTERFACE ${component})
|
|
@@ -740,7 +818,7 @@ macro(spl_run_conan)
|
|
|
740
818
|
endmacro(spl_run_conan)
|
|
741
819
|
|
|
742
820
|
macro(_spl_set_ninja_wrapper_as_cmake_make)
|
|
743
|
-
set
|
|
821
|
+
set(NINJA_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/ninja_wrapper.bat)
|
|
744
822
|
file(WRITE ${NINJA_WRAPPER}
|
|
745
823
|
"@echo off
|
|
746
824
|
@call %~dp0%/activate_run.bat
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
import py7zr
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ArtifactsArchive:
|
|
11
|
+
"""
|
|
12
|
+
This class represents a single archive containing artifacts.
|
|
13
|
+
It collects artifacts to be packed and archived.
|
|
14
|
+
|
|
15
|
+
Currently supports 7z and Artifactory.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class ArchiveArtifact:
|
|
20
|
+
"""
|
|
21
|
+
Represents a single artifact to be archived.
|
|
22
|
+
This class holds the archive path (relative to the output directory of the 7z archive)
|
|
23
|
+
and the absolute path of the artifact.
|
|
24
|
+
It is used to ensure that artifacts are correctly archived with their intended paths.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
archive_path: Path
|
|
28
|
+
absolute_path: Path
|
|
29
|
+
|
|
30
|
+
def __init__(self, out_dir: Path, archive_name: str) -> None:
|
|
31
|
+
self.out_dir: Path = out_dir
|
|
32
|
+
self.archive_name: str = archive_name
|
|
33
|
+
self.archive_artifacts: List[ArtifactsArchive.ArchiveArtifact] = []
|
|
34
|
+
|
|
35
|
+
def register(self, artifacts: List[Path]) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Register artifacts for archiving.
|
|
38
|
+
Args:
|
|
39
|
+
artifacts: List of paths to artifacts (files or directories) to be archived.
|
|
40
|
+
"""
|
|
41
|
+
for artifact in artifacts:
|
|
42
|
+
self._add_artifact(artifact)
|
|
43
|
+
|
|
44
|
+
def _add_artifact(self, artifact_path: Path) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Add an artifact (file or directory) to the archive list.
|
|
47
|
+
Args:
|
|
48
|
+
artifact_path: path to the artifact to be archived.
|
|
49
|
+
"""
|
|
50
|
+
# Convert to absolute path first
|
|
51
|
+
absolute_path = artifact_path.resolve() if not artifact_path.is_absolute() else artifact_path
|
|
52
|
+
|
|
53
|
+
# Calculate the relative path from out_dir for the archive
|
|
54
|
+
if absolute_path.is_relative_to(self.out_dir.absolute()):
|
|
55
|
+
archive_path = absolute_path.relative_to(self.out_dir.absolute())
|
|
56
|
+
else:
|
|
57
|
+
# If not relative to out_dir, just use the name
|
|
58
|
+
archive_path = Path(absolute_path.name)
|
|
59
|
+
|
|
60
|
+
self.archive_artifacts.append(
|
|
61
|
+
self.ArchiveArtifact(
|
|
62
|
+
archive_path=archive_path,
|
|
63
|
+
absolute_path=absolute_path,
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def create_archive(self) -> Path:
|
|
68
|
+
"""
|
|
69
|
+
Create a 7z file containing the collected artifacts.
|
|
70
|
+
Returns:
|
|
71
|
+
Path: The path to the created 7z file.
|
|
72
|
+
Raises:
|
|
73
|
+
Exception: If there is an error creating the 7z file.
|
|
74
|
+
"""
|
|
75
|
+
# Construct the full archive path
|
|
76
|
+
archive_path = self.out_dir / self.archive_name
|
|
77
|
+
|
|
78
|
+
# Create output directory if it doesn't exist
|
|
79
|
+
archive_path.parent.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
|
|
81
|
+
# Delete the file if it already exists
|
|
82
|
+
if archive_path.exists():
|
|
83
|
+
archive_path.unlink()
|
|
84
|
+
|
|
85
|
+
if not self.archive_artifacts:
|
|
86
|
+
print("Warning: No artifacts registered for archiving")
|
|
87
|
+
# Create empty 7z file
|
|
88
|
+
with py7zr.SevenZipFile(archive_path, "w") as archive:
|
|
89
|
+
pass
|
|
90
|
+
return archive_path
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
with py7zr.SevenZipFile(archive_path, "w") as archive:
|
|
94
|
+
for artifact in self.archive_artifacts:
|
|
95
|
+
if not artifact.absolute_path.exists():
|
|
96
|
+
print(f"Warning: Artifact {artifact.absolute_path} does not exist, skipping")
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
if artifact.absolute_path.is_file():
|
|
101
|
+
archive.write(artifact.absolute_path, arcname=str(artifact.archive_path))
|
|
102
|
+
elif artifact.absolute_path.is_dir():
|
|
103
|
+
# py7zr can handle directories directly
|
|
104
|
+
archive.writeall(artifact.absolute_path, arcname=str(artifact.archive_path))
|
|
105
|
+
except Exception as file_error:
|
|
106
|
+
print(f"Warning: Failed to add {artifact.absolute_path} to archive: {file_error}")
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
print(f"7z file created at: {archive_path}")
|
|
110
|
+
return archive_path
|
|
111
|
+
except Exception as e:
|
|
112
|
+
print(f"Error creating artifacts 7z file: {e}")
|
|
113
|
+
raise e
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ArtifactsArchiver:
|
|
117
|
+
"""
|
|
118
|
+
This class manages multiple ArtifactsArchive instances.
|
|
119
|
+
It provides a unified interface for registering artifacts to different archives.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self) -> None:
|
|
123
|
+
self.archives: Dict[str, ArtifactsArchive] = {}
|
|
124
|
+
self._target_repos: Dict[str, str] = {}
|
|
125
|
+
|
|
126
|
+
def add_archive(self, out_dir: Path, archive_filename: str, target_repo: Optional[str] = None, archive_name: str = "default") -> ArtifactsArchive:
|
|
127
|
+
"""
|
|
128
|
+
Add a new archive to the archiver.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
out_dir: Output directory for the archive
|
|
132
|
+
archive_filename: Filename for the archive
|
|
133
|
+
target_repo: Target repository path for Artifactory upload (optional)
|
|
134
|
+
archive_name: Name identifier for the archive (defaults to "default")
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
The created ArtifactsArchive instance
|
|
138
|
+
"""
|
|
139
|
+
archive = ArtifactsArchive(out_dir, archive_filename)
|
|
140
|
+
self.archives[archive_name] = archive
|
|
141
|
+
# Store the target repo information for this archive only if provided
|
|
142
|
+
if target_repo is not None:
|
|
143
|
+
self._target_repos[archive_name] = target_repo
|
|
144
|
+
return archive
|
|
145
|
+
|
|
146
|
+
def register(self, artifacts: List[Path], archive_name: str = "default") -> None:
|
|
147
|
+
"""
|
|
148
|
+
Register artifacts for archiving to a specific archive.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
artifacts: List of paths to artifacts (files or directories) to be archived.
|
|
152
|
+
archive_name: Name of the archive to register artifacts to (defaults to "default")
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
KeyError: If the specified archive_name doesn't exist
|
|
156
|
+
"""
|
|
157
|
+
if archive_name not in self.archives:
|
|
158
|
+
raise KeyError(f"Archive '{archive_name}' not found. Available archives: {list(self.archives.keys())}")
|
|
159
|
+
|
|
160
|
+
self.archives[archive_name].register(artifacts)
|
|
161
|
+
|
|
162
|
+
def get_archive(self, archive_name: str) -> ArtifactsArchive:
|
|
163
|
+
"""
|
|
164
|
+
Get a specific archive by name.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
archive_name: Name of the archive to retrieve
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
The ArtifactsArchive instance
|
|
171
|
+
|
|
172
|
+
Raises:
|
|
173
|
+
KeyError: If the specified archive_name doesn't exist
|
|
174
|
+
"""
|
|
175
|
+
if archive_name not in self.archives:
|
|
176
|
+
raise KeyError(f"Archive '{archive_name}' not found. Available archives: {list(self.archives.keys())}")
|
|
177
|
+
|
|
178
|
+
return self.archives[archive_name]
|
|
179
|
+
|
|
180
|
+
def create_all_archives(self) -> Dict[str, Path]:
|
|
181
|
+
"""
|
|
182
|
+
Create all registered archives.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Dictionary mapping archive names to their created file paths
|
|
186
|
+
"""
|
|
187
|
+
created_archives = {}
|
|
188
|
+
for archive_name, archive in self.archives.items():
|
|
189
|
+
created_archives[archive_name] = archive.create_archive()
|
|
190
|
+
return created_archives
|
|
191
|
+
|
|
192
|
+
def create_rt_upload_json(self, out_dir: Path) -> Path:
|
|
193
|
+
"""
|
|
194
|
+
Create a single rt-upload.json file containing all archives.
|
|
195
|
+
|
|
196
|
+
This function replicates the logic from the Jenkinsfile for determining the RT_TARGET
|
|
197
|
+
and creating the upload specification file. It uses Jenkins environment variables
|
|
198
|
+
when available, otherwise falls back to default values.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
output_dir: Directory where the rt-upload.json file will be created
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Path to the created rt-upload.json file
|
|
205
|
+
"""
|
|
206
|
+
# Set local defaults first
|
|
207
|
+
change_id = None
|
|
208
|
+
branch_name = "local_branch"
|
|
209
|
+
build_number = "local_build"
|
|
210
|
+
|
|
211
|
+
# Adapt values when Jenkins environment is detected
|
|
212
|
+
# TODO: check if an existing library can be used for CI context detection
|
|
213
|
+
if os.environ.get("JENKINS_URL"):
|
|
214
|
+
change_id = os.environ.get("CHANGE_ID")
|
|
215
|
+
jenkins_branch_name = os.environ.get("BRANCH_NAME")
|
|
216
|
+
jenkins_build_number = os.environ.get("BUILD_NUMBER")
|
|
217
|
+
tag_name = os.environ.get("TAG_NAME")
|
|
218
|
+
|
|
219
|
+
if change_id:
|
|
220
|
+
# Pull request case
|
|
221
|
+
branch_name = f"PR-{change_id}"
|
|
222
|
+
elif tag_name:
|
|
223
|
+
# Tag build case
|
|
224
|
+
branch_name = tag_name
|
|
225
|
+
elif jenkins_branch_name:
|
|
226
|
+
# Regular branch case
|
|
227
|
+
branch_name = jenkins_branch_name
|
|
228
|
+
|
|
229
|
+
if jenkins_build_number:
|
|
230
|
+
build_number = jenkins_build_number
|
|
231
|
+
|
|
232
|
+
# Create the files array for Artifactory upload format
|
|
233
|
+
files_array = []
|
|
234
|
+
|
|
235
|
+
for archive_name, archive in self.archives.items():
|
|
236
|
+
if archive_name in self._target_repos:
|
|
237
|
+
target_repo = self._target_repos[archive_name]
|
|
238
|
+
|
|
239
|
+
# Construct the RT target path
|
|
240
|
+
rt_target = f"{target_repo}/{branch_name}/{build_number}/"
|
|
241
|
+
|
|
242
|
+
# Add this archive to the files array
|
|
243
|
+
files_array.append(
|
|
244
|
+
{
|
|
245
|
+
"pattern": archive.archive_name,
|
|
246
|
+
"target": rt_target,
|
|
247
|
+
"recursive": "false",
|
|
248
|
+
"flat": "false",
|
|
249
|
+
"regexp": "false",
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Create the single rt-upload.json file
|
|
254
|
+
json_path = out_dir / "rt-upload.json"
|
|
255
|
+
|
|
256
|
+
spec = {"files": files_array}
|
|
257
|
+
|
|
258
|
+
with open(json_path, "w") as f:
|
|
259
|
+
json.dump(spec, f, indent=4)
|
|
260
|
+
|
|
261
|
+
return json_path
|
|
262
|
+
|
|
263
|
+
def list_archives(self) -> List[str]:
|
|
264
|
+
"""
|
|
265
|
+
Get a list of all archive names.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
List of archive names
|
|
269
|
+
"""
|
|
270
|
+
return list(self.archives.keys())
|
|
271
|
+
|
|
272
|
+
def create_archive(self, archive_name: str = "default") -> Path:
|
|
273
|
+
"""
|
|
274
|
+
Create a specific archive (convenience method for single-archive use case).
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
archive_name: Name of the archive to create (defaults to "default")
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Path to the created archive file
|
|
281
|
+
|
|
282
|
+
Raises:
|
|
283
|
+
KeyError: If the specified archive_name doesn't exist
|
|
284
|
+
"""
|
|
285
|
+
if archive_name not in self.archives:
|
|
286
|
+
raise KeyError(f"Archive '{archive_name}' not found. Available archives: {list(self.archives.keys())}")
|
|
287
|
+
|
|
288
|
+
return self.archives[archive_name].create_archive()
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# Example usage:
|
|
292
|
+
#
|
|
293
|
+
# ## Simple single-archive use case with target repo:
|
|
294
|
+
# archiver = ArtifactsArchiver()
|
|
295
|
+
# archiver.add_archive(Path("./build/output"), "results.7z", "my-repo/results") # uses "default" name
|
|
296
|
+
# archiver.register([Path("./build/test_report.xml"), Path("./build/coverage.html")]) # registers to "default"
|
|
297
|
+
# archive_path = archiver.create_archive() # creates the "default" archive
|
|
298
|
+
# upload_json = archiver.create_rt_upload_json(Path("./build/output"))
|
|
299
|
+
#
|
|
300
|
+
# ## Simple single-archive use case without target repo (archive only):
|
|
301
|
+
# archiver = ArtifactsArchiver()
|
|
302
|
+
# archiver.add_archive(Path("./build/output"), "results.7z") # no target repo, uses "default" name
|
|
303
|
+
# archiver.register([Path("./build/test_report.xml"), Path("./build/coverage.html")])
|
|
304
|
+
# archive_path = archiver.create_archive() # creates the "default" archive
|
|
305
|
+
# # upload_json = archiver.create_rt_upload_json(Path("./build/output")) # would create empty JSON
|
|
306
|
+
#
|
|
307
|
+
# ## Multi-archive use case:
|
|
308
|
+
# archiver = ArtifactsArchiver()
|
|
309
|
+
# archiver.add_archive(Path("./build/output"), "test_results.7z", "my-repo/test-results", "test_results")
|
|
310
|
+
# archiver.add_archive(Path("./build/output"), "coverage.7z", "my-repo/coverage", "coverage_reports")
|
|
311
|
+
# archiver.add_archive(Path("./build/output"), "docs.7z", None, "documentation") # no target repo for docs
|
|
312
|
+
#
|
|
313
|
+
# archiver.register([Path("./build/test_report.xml")], "test_results")
|
|
314
|
+
# archiver.register([Path("./build/coverage.html")], "coverage_reports")
|
|
315
|
+
# archiver.register([Path("./build/docs/")], "documentation")
|
|
316
|
+
#
|
|
317
|
+
# created_files = archiver.create_all_archives()
|
|
318
|
+
# upload_json = archiver.create_rt_upload_json(Path("./build/output")) # only includes archives with target repos
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "7.9.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/application/src/main/src/main.c
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/cmake-kits.json
RENAMED
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/extensions.json
RENAMED
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/launch.json
RENAMED
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/settings.json
RENAMED
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/.vscode/tasks.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/common/index.rst
RENAMED
|
File without changes
|
{spl_core-7.9.0 → spl_core-7.11.0}/src/spl_core/kickstart/templates/project/doc/components/index.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|