Refactor to use new protocol module and sipo.
[bertos.git] / wizard / create_preset.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 #
4 # This file is part of BeRTOS.
5 #
6 # Bertos is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 #
20 # As a special exception, you may use this file as part of a free software
21 # library without restriction.  Specifically, if other files instantiate
22 # templates or use macros or inline functions from this file, or you compile
23 # this file and link it with other files to produce an executable, this
24 # file does not by itself cause the resulting executable to be covered by
25 # the GNU General Public License.  This exception does not however
26 # invalidate any other reasons why the executable file might be covered by
27 # the GNU General Public License.
28 #
29 # Copyright 2010 Develer S.r.l. (http://www.develer.com/)
30 #
31 # Author: Francesco Sacchi <batt@develer.com>
32 #
33
34 import pickle
35 import sys
36 import os
37 import shutil
38 import pprint
39 import glob
40 import re
41
42 def remove(path):
43     if os.path.isdir(path):
44         shutil.rmtree(path, ignore_errors=True)
45     else:
46         try:
47             os.remove(path)
48         except OSError:
49             pass
50
51 def findPath(start, target):
52     pa = start
53     while pa != "/":
54         pa = os.path.abspath(pa + "/..")
55         if os.path.exists(pa + "/" + target):
56             return os.path.relpath(pa, start)
57
58 if len(sys.argv) < 3:
59     print "Usage: %s <project_dir> <preset_dir>" % sys.argv[0]
60     exit(0)
61
62 prj_dir = sys.argv[1]
63 preset_dir = sys.argv[2]
64
65 if not os.path.exists(prj_dir + "/project.bertos"):
66     print "%s does not seem a Wizard created project." % prj_dir
67     exit(1)
68
69 p = open(prj_dir + "/project.bertos")
70 s = pickle.load(p)
71 if s["WIZARD_VERSION"] < 3:
72     print "Project version too old."
73     exit(1)
74 pname = s["PROJECT_NAME"] 
75 preset_dir += pname
76
77 #find hw/ path for the board
78 hw_path = findPath(preset_dir, "hw")
79 if not hw_path:
80     print "hw/ path not found in parent directories of %s" % preset_dir
81     exit(1)
82
83 #find bertos/ path
84 bertos_path = findPath(preset_dir, "bertos")
85 if not bertos_path:
86     print "bertos/ path not found in parent directories of %s" % preset_dir
87     exit(1)
88
89 #Copy the project and remove unneeded files.
90 shutil.copytree(prj_dir, preset_dir)
91 remove(preset_dir + "/bertos")
92 remove(preset_dir + "/images")
93 remove(preset_dir + "/obj")
94 remove(preset_dir + "/Makefile")
95 remove(preset_dir + "/buildrev.h")
96 remove(preset_dir + "/VERSION")
97 remove(preset_dir + "/" + pname + ".project")
98 remove(preset_dir + "/" + pname + ".workspace")
99
100 #Flatten project sources.
101 #A wizard created project called pname
102 #usually has the following structure:
103 #
104 #pname
105 #  |
106 #  +-<project files>
107 #  |
108 #  +-bertos
109 #  |
110 #  +-pname
111 #      |   
112 #      +<pname sources>
113 #
114 #This has been done in order to have the chance to
115 #add multiple projects sharing the same bertos version.
116 #After the copy and after removing the bertos tree inside the 
117 #project, the double pname directory is redundant, so we move
118 #all pname sources into the parent directory
119 l = glob.glob(preset_dir + "/" + pname + "/*")
120 for f in l:
121     shutil.move(f, preset_dir)
122
123 #Remove the now empty project src dir and the hw/ dir.
124 #hw files are located in parent directories and are common
125 #for all projects on the same board. 
126 remove(preset_dir + "/" + pname)
127 remove(preset_dir + "/hw")
128
129 assert(os.path.exists(preset_dir + "/" + hw_path     + "/hw"))
130 assert(os.path.exists(preset_dir + "/" + bertos_path + "/bertos"))
131
132 #Update wizard project info.
133 #A preset is still a Wizard-editable project
134 #but has its bertos/ and hw/ dirs shared with 
135 #others.
136 s["BERTOS_PATH"] = bertos_path
137 s["PROJECT_HW_PATH"] = hw_path
138 s["PROJECT_SRC_PATH"] = "."
139 s["PRESET"] = True
140
141 # Calculate relative paths useful to discover where are the sources (and the hw
142 # files) relatively to the BeRTOS Makefile
143 bertos_path = os.path.abspath(preset_dir + "/" + bertos_path)
144 hw_path = os.path.abspath(preset_dir + "/" + hw_path)
145
146 src_path = os.path.relpath(preset_dir, bertos_path)
147 hw_path  = os.path.relpath(hw_path, bertos_path)
148
149 # Src path and hw path relatively to the BeRTOS Makefile.
150 s["PROJECT_SRC_PATH_FROM_MAKEFILE"] = src_path
151 s["PROJECT_HW_PATH_FROM_MAKEFILE"] = hw_path
152 toolchain = s["TOOLCHAIN"]["path"]
153 s["TOOLCHAIN"]["path"] = os.path.basename(toolchain)
154
155 pprint.pprint(s)
156 p = open(preset_dir + "/project.bertos", "w")
157 pickle.dump(s, p)
158
159 #Create a .spec file in order to make this preset visible in the Wizard
160 open(preset_dir + "/.spec", "w").write("name = '%s preset'" % pname)
161
162 #Update project makefiles adapting them to the new directory layout
163 mk = open(preset_dir + "/" + pname + ".mk").read()
164 mk = re.sub(r"(%s_SRC_PATH\s*=\s*).*" % pname, r"\1%s" % src_path, mk)
165 mk = re.sub(r"(%s_HW_PATH\s*=\s*).*" % pname, r"\1%s" % hw_path, mk)
166
167 #remove absolute path from toolchain
168 mk = re.sub(r'(%s_PREFIX\s*=\s*").*?([^/]*")' % pname, r'\1\2', mk)
169 open(preset_dir + "/" + pname + ".mk", "w").write(mk)