• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# encoding=utf-8
3# =========================================================================
4# @brief    Project genarator, parse compiler info & generate IAR/Makefile... project file
5
6# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#     http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18# =========================================================================
19
20import copy
21import os
22import json
23import re
24import shutil
25import sys
26
27script_dir = os.path.split(os.path.normpath(__file__))[0]
28makefile_template = os.path.join(script_dir, "sdk_template", "makefile")
29
30def load_json(json_file):
31    with open(json_file, 'r') as f:
32        temp = f.read()
33        return json.loads(temp)
34
35class CompileCommandParser:
36    def __init__(self, cc_file):
37        temp = load_json(cc_file)
38        self.compile_info = {}
39        for item in temp:
40            self.compile_info[item['file']] = {
41                'command': item['command'],
42                'directory': item['directory'],
43            }
44
45    def get_src_compile_info(self, src_name):
46        command = self.compile_info[src_name]['command']
47        defines = re.findall(r"-D([^ ]*)", command)
48        includes = re.findall(r"-I([^ ]*)", command)
49
50        ccflags = list(set(re.findall(r" (-[^ID][^ ]*)", command)))
51        ccflags.remove('-c')
52        ccflags.remove('-o')
53        pre_include = []
54        if '-include' in ccflags:
55            ccflags.remove('-include')
56            pre_include = list(set(re.findall(r" -include ([^ ]*)", command)))
57            ccflags.extend(['-include ' + x for x in pre_include])
58        return {
59            "DEFINES": list(set(defines)),
60            "INCLUDES": list(set(includes)),
61            "CCFLAGS": ccflags,
62            "PRE_INCLUDE": pre_include,
63        }
64
65class ComponentParser(CompileCommandParser):
66    def __init__(self, component_info_file, compile_command_file):
67        super(ComponentParser, self).__init__(compile_command_file)
68        with open(component_info_file, 'r') as fp:
69            data = fp.read()
70        data = data.replace('="', r'=\\\"')
71        data = data.replace('";', r'\\\";')
72        data = data.replace(r' \\\";', r' ";')
73        info = json.loads(data)
74        self.component_info = info.pop("COMPONENTS")
75        self.public_info = copy.deepcopy(info)
76        self.public_info["COMPONENT_LIST"] = list(self.component_info.keys())
77        self.public_info["CHIP"] = chip
78        self.public_info["CORE"] = core
79        self.public_info["ARCH"] = arch
80        self.public_info["TARGET_NAME"] = application_name
81        self.public_info["PKG_TARGET_NAME"] = pkg_target_name
82        for item, value in self.public_info.items():
83            if isinstance(value, str):
84                self.public_info[item] = [i for i in value.split(";") if i != '']
85        for component, value in self.component_info.items():
86            if not value["SOURCES"]:
87                continue
88
89            for component_items in value:
90                if isinstance(value[component_items], str):
91                    value[component_items] = [i for i in value[component_items].split(";") if i != '']
92            src = value["SOURCES"]
93
94class MakefileGenerator(ComponentParser):
95    def __init__(self, component_info_file, compile_command_file, project_file_dir, project_folder):
96        super(MakefileGenerator, self).__init__(component_info_file, compile_command_file)
97        self.replace_map = {}
98        # self.replace_map.update(toolchain)
99        self.project_file_dir = project_file_dir
100        self.project_folder = project_folder
101        self.make_dir = os.path.join(project_file_dir, project_folder, 'makefile')
102        if not os .path.exists(self.make_dir):
103            os.makedirs(self.make_dir)
104        self.gen_toolchain_file()
105        for component_name in self.component_info:
106            self.gen_component_file(component_name)
107        self.gen_root_file()
108        self.gen_makefile_cmd()
109
110    def gen_makefile_cmd(self):
111        with open(os.path.join(sdk_output_dir, f'make.cmd'), 'a+') as f:
112            f.writelines(self.make_dir + '\n')
113
114    def gen_toolchain_file(self):
115        with open(os.path.join(makefile_template, 'toolchain.make'), 'r') as f:
116            lines = f.readlines()
117        toolchain = load_json(toolchain_file)
118        for i, line in enumerate(lines):
119            lines[i] = self.deal_replace(line, toolchain)
120        with open(os.path.join(self.make_dir, f'toolchains.make'), 'w') as f:
121            f.writelines(lines)
122
123    def gen_component_file(self, component_name):
124        compile_info = self.component_info[component_name]
125        template = os.path.join(makefile_template, 'component_template.make')
126        out_path = 'components'
127        if "THIRD_PARTY" in compile_info:
128            print(compile_info["SOURCES"])
129        if "THIRD_PARTY" in compile_info and compile_info["THIRD_PARTY"][0] == "true":
130            template = os.path.join(makefile_template, 'third_party_template.make')
131            index = compile_info['COMPONENT_CUSTOM_CCFLAGS'].index("-include")
132            if index >= 0:
133                compile_info['COMPONENT_CUSTOM_CCFLAGS'][index] = "-include$(LITEOS_PLATFORM_MENUCONFIG_H)"
134                compile_info['COMPONENT_CUSTOM_CCFLAGS'].pop(index+1)
135        compile_info["COMPONENT_NAME"] = component_name
136        with open(template, 'r') as f:
137            lines = f.readlines()
138        for i, line in enumerate(lines):
139            lines[i] = self.deal_replace(line, compile_info)
140        if not os.path.exists(os.path.join(self.make_dir, out_path)):
141            os.makedirs(os.path.join(self.make_dir, out_path))
142        with open(os.path.join(self.make_dir, out_path, f'{component_name}.make'), 'w') as f:
143            f.writelines(lines)
144
145    def gen_root_file(self):
146        with open(os.path.join(makefile_template, 'template.mk'), 'r') as f:
147            lines = f.readlines()
148        for i, line in enumerate(lines):
149            lines[i] = self.deal_replace(line, self.public_info)
150        # if not os.path.exists(os.path.join(self.make_dir, 'components')):
151        #     os.makedirs(os.path.join(self.make_dir, 'components'))
152        with open(os.path.join(self.make_dir, 'Makefile'), 'w') as f:
153            f.writelines(lines)
154
155    def join_by_clum_num(self, lst, word, clum_num):
156        res = []
157        if not lst:
158            return res
159        c_word = lst[0]
160        for item in lst:
161            if item == "":
162                continue
163            if c_word == 0:
164                c_word = item
165                continue
166            if len(c_word) + len(word) + len(item) <= clum_num:
167                c_word = f"{c_word}{word}{item}"
168                continue
169            res.append(c_word)
170            c_word = item
171        return res
172
173    def deal_replace(self, line, replace_map):
174        l = re.findall("REPLACE_(\w*)", line)
175        for item in l:
176            if isinstance(replace_map[item], list):
177                replace_str = " \\\n    ".join(replace_map[item])
178                if replace_str:
179                    replace_str = " \\\n    %s" % (replace_str.strip())
180                replace_str = replace_str.replace(root_dir, "$(SDK_ROOT)")
181            elif isinstance(replace_map[item], str):
182                replace_str = replace_map[item].replace(root_dir, "$(SDK_ROOT)")
183            else:
184                print(replace_map[item])
185            line = line.replace(f"REPLACE_{item}", replace_str)
186        return line
187
188if __name__ == "__main__":
189    project_type = sys.argv[1]
190    application_name = sys.argv[2]
191    cc_json = sys.argv[3]
192    project_file_dir = sys.argv[4]
193    root_dir = sys.argv[5]
194    sdk_output_dir = sys.argv[6]
195    chip, core, board, arch, os_kernel, pkg_target_name = sys.argv[7].split(",")
196    toolchain_file = sys.argv[8]
197    component_info_file = sys.argv[9]
198    project_folder = f"{chip}_{core}_{board}_{os_kernel}_{pkg_target_name}"
199    project_type_list = project_type.split(",")
200    if 'makefile' in project_type_list:
201        MakefileGenerator(component_info_file, cc_json, project_file_dir, project_folder)
202