summaryrefslogtreecommitdiffstats
path: root/cmake/module/feature.cmake
blob: d350227c16520978974cc7584607ccbe783a61e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#[[
 # Copyright (c) 2026 Alexey Gavrilov <alexey.gavrilov@mail.com>
 #
 # This file is part of ObjectiveOS.
 #
 # ObjectiveOS is free software: you can redistribute it and/or modify it under
 # the terms of the GNU General Public License as published by the Free Software
 # Foundation, either version 3 of the License, or (at your option) any later
 # version.
 #
 # ObjectiveOS is distributed in the hope that it will be useful, but WITHOUT ANY
 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License along with
 # ObjectiveOS. If not, see <https://www.gnu.org/licenses/>.
 ]]

get_property(IS_INITIALZIED GLOBAL PROPERTY POPULATING_FEATURES SET)

if(NOT IS_INITIALZIED)
    set_property(GLOBAL PROPERTY POPULATING_FEATURES "")
    set_property(GLOBAL PROPERTY FEATURES_LIST "")
    # Features list that cannot to finish the save process
    set_property(GLOBAL PROPERTY CONSERVED_FEATURES "")

    # Name of out file
    set(FEATURE_OUT_FILE "CMakeFeatureOut.txt" CACHE STRING "Features data
    out filename")
    set(FEATURE_AVAILABLE_FIELDS "NAME;DESCRIPTION;TAGS;HASHCOMMIT;AUTHORSHIP"
    CACHE STRING "Available feature fields")
endif()

function(startFeatureRecording target)
    get_property(
        POPULATING_FEATURES_PROPERTY
        GLOBAL PROPERTY
            POPULATING_FEATURES
    )

    if(TARGET ${target})
        list(APPEND POPULATING_FEATURES_PROPERTY ${target})
    else()
        message(WARNING "${target} isn't target")
    endif()

    set_property(
        GLOBAL PROPERTY
            POPULATING_FEATURES ${POPULATING_FEATURES_PROPERTY}
    )
endfunction()

function(saveRecordingFeature)
    get_property(
        POPULATING_FEATURES_PROPERTY GLOBAL PROPERTY
            POPULATING_FEATURES)
    get_property(
        FEATURES_LIST_PROPERTY GLOBAL PROPERTY
            FEATURES_LIST)
    get_property(
        CONSERVED_FEATURES_PROPERTY GLOBAL PROPERTY
            CONSERVED_FEATURES)
    list(LENGTH POPULATING_FEATURES_PROPERTY POPULATING_FEATURES_LENGTH)

    # Divided save feature on three category: nothing to save, cannot to finish
    # and can finish
    if(POPULATING_FEATURES_LENGTH LESS 1)
        message(WARNING "Nothing feature to save")
    elseif(POPULATING_FEATURES_LENGTH EQUAL 1)
        list(POP_BACK POPULATING_FEATURES_PROPERTY SAVING_FEATURE)
        list(APPEND FEATURES_LIST_PROPERTY ${SAVING_FEATURE})
        # Finish save process for all features in CONSERVED_FEATURES list
        while(NOT "${CONSERVED_FEATURES_PROPERTY}" STREQUAL "")
            list(POP_BACK CONSERVED_FEATURES_PROPERTY CONSERVED_FEATURE)

            # Get last saved feature
            list(GET FEATURES_LIST_PROPERTY -1 LAST_SAVED_FEATURE)

            get_property(
                INHERITED_DEPENDENCIES TARGET ${LAST_FEATURE} PROPERTY
                    FEATURE_DEPENDENCIES)
            get_property(
                CONSERVED_FEATURE_DEPENDENCIES TARGET ${CONSERVED_FEATURE} PROPERTY
                    FEATURE_DEPENDENCIES)

            # Next conserved features are inherit dependencies from parent feature
            list(APPEND CONSERVED_FEATURE_DEPENDENCIES ${INHERITED_DEPENDENCIES})
            set_property(TARGET ${CONSERVED_FEATURE} PROPERTY
            FEATURE_DEPENDENCIES ${CONSERVED_FEATURE_DEPENDENCIES})

            # Save conserved feature
            list(APPEND FEATURES_LIST_PROPERTY ${CONSERVED_FEATURE})
        endwhile()
    elseif(POPULATING_FEATURES_LENGTH GREATER 1)
        list(POP_BACK POPULATING_FEATURES_PROPERTY UNFINISHED_FEATURE)
        list(APPEND CONSERVED_FEATURES_PROPERTY UNFINISHED_FEATURE)
    endif()

    set_property(GLOBAL PROPERTY
        POPULATING_FEATURES
            ${POPULATING_FEATURES_PROPERTY})
    set_property(GLOBAL PROPERTY
        FEATURES_LIST
            ${FEATURES_LIST_PROPERTY})
    set_property(GLOBAL PROPERTY
        CONSERVED_FEATURES
            ${CONSERVED_FEATURES_PROPERTY})
endfunction()

#[[
 # Available fields are: STRING:NAME, STRING:DESCRIPTION, LIST:TAGS,
 # STRING:HASHCOMMIT, STRING:AUTHORSHIP
 # NAME and HASHCOMMIT must be specified.
 ]]
function(setFeatureField field value)
    get_property(
        POPULATING_FEATURES_PROPERTY
        GLOBAL PROPERTY
            POPULATING_FEATURES
    )
    list(POP_BACK POPULATING_FEATURES_PROPERTY RECORDING_FEATURE)

    # Check on current recording feature
    if(RECORDING_FEATURE)
        # If field is available and value is define, save target property with
        # associated value
        if(field IN_LIST FEATURE_AVAILABLE_FIELDS AND value)
            set_property(
                TARGET ${RECORDING_FEATURE}
                PROPERTY
                    "FEATURE_${field}" ${value}
            )
        endif()
    else()
        message(WARNING "No recording feature")
    endif()
endfunction()

#[[
 # Element in names must be an architecture, compiler or another feature. Would be a list.
 ]]
function(setFeatureDependency names)
    get_property( POPULATING_FEATURES_PROPERTY GLOBAL PROPERTY POPULATING_FEATURES)
    list(POP_BACK POPULATING_FEATURES_PROPERTY RECORDING_FEATURE)
    list(GET -1 POPULATING_FEATURES_PROPERTY FEATURE_DEP_INHERIT)

    get_property(FEATURES_LIST_PROPERTY GLOBAL PROPERTY FEATURES_LIST)

    if(RECORDING_FEATURE)
        set(featdep "")

        foreach(dependency IN LISTS names)
            if(
                (dependency IN_LIST FEATURES_LIST_PROPERTY
                OR dependency IN_LIST POPULATING_FEATURES_PROPERTY
                AND NOT dependency STREQUAL ${RECORDING_FEATURE})
                OR (dependency IN_LIST OBJECTIVE_SUPPORTED_PROCESSORS)
                OR (dependency MATCHES "gcc" OR dependency MATCHES "clang")
            )
                list(APPEND featdep ${dependency})
            else()
                message(WARNING "\"${dependency}\" is wrong")
            endif()
        endforeach()
        set_property(TARGET ${RECORDING_FEATURE} PROPERTY FEATURE_DEPENDENCIES
        ${featdep})

    else()
        message(WARNING "No recording feature")
    endif()
endfunction()

#[[
 # Function that push features data into file. Content is like cmake variables.
 # <FEATURE_PROPERTY> = "<VARIABLE>"
 ]]
function(outFeaturesToFile)
    get_property(FEATURES_LIST GLOBAL PROPERTY FEATURES_LIST)

    set(OUT_FILE "${CMAKE_BINARY_DIR}/${FEATURE_OUT_FILE}")
    file(WRITE "${OUT_FILE}"
        "# This file contains list of kernel configurable objects\n\n")

    foreach(feature IN LISTS FEATURES_LIST)
        get_property(FEATURE_DEPENDENCIES TARGET ${feature} PROPERTY
        FEATURE_DEPENDENCIES)

        file(APPEND "${OUT_FILE}" "# Properties for ${feature} feature\n")

        foreach(FIELD_NAME IN LISTS FEATURE_AVAILABLE_FIELDS)
            get_property("FEATURE_${FIELD_NAME}" TARGET ${feature} PROPERTY
                "FEATURE_${FIELD_NAME}")

            file(APPEND "${OUT_FILE}"
                "FEATURE_${feature}_${FIELD_NAME} = \"${FEATURE_${FIELD_NAME}}\"\n")
        endforeach()

        file(APPEND "${OUT_FILE}"
            "FEATURE_${feature}_${FIELD_NAME} = \"${FEATURE_DEPENDENCIES}\"\n\n\n")
    endforeach()
endfunction()