4 # ***** BEGIN GPL LICENSE BLOCK *****
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
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.
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 Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # Contributor(s): Campbell Barton, M.G. Kishalmi
22 # ***** END GPL LICENSE BLOCK *****
28 c:\Python32\python.exe c:\blender_dev\blender\build_files\cmake\cmake_qtcreator_project.py c:\blender_dev\cmake_build
31 python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake
36 from os.path import join, dirname, normpath, abspath, splitext, relpath, exists
38 base = join(os.path.dirname(__file__), "..", "..")
42 SIMPLE_PROJECTFILE = False
45 CMAKE_DIR = sys.argv[-1]
47 if not os.path.exists(os.path.join(CMAKE_DIR, "CMakeCache.txt")):
48 CMAKE_DIR = os.getcwd()
49 if not os.path.exists(os.path.join(CMAKE_DIR, "CMakeCache.txt")):
50 print("CMakeCache.txt not found in %r or %r\n Pass CMake build dir as an argument, or run from that dir, aborting" % (CMAKE_DIR, os.getcwd()))
56 PROJECT_DIR = CMAKE_DIR
59 def source_list(path, filename_check=None):
60 for dirpath, dirnames, filenames in os.walk(path):
63 if dirpath.startswith("."):
66 for filename in filenames:
67 filepath = join(dirpath, filename)
68 if filename_check is None or filename_check(filepath):
73 def is_cmake(filename):
74 ext = splitext(filename)[1]
75 return (ext == ".cmake") or (filename.endswith("CMakeLists.txt"))
78 def is_c_header(filename):
79 ext = splitext(filename)[1]
80 return (ext in (".h", ".hpp", ".hxx"))
84 ext = splitext(filename)[1]
88 def is_glsl(filename):
89 ext = splitext(filename)[1]
90 return (ext == ".glsl")
94 ext = splitext(filename)[1]
95 return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc"))
98 def is_c_any(filename):
99 return is_c(filename) or is_c_header(filename)
102 def is_svn_file(filename):
103 dn, fn = os.path.split(filename)
104 filename_svn = join(dn, ".svn", "text-base", "%s.svn-base" % fn)
105 return exists(filename_svn)
108 def is_project_file(filename):
109 return (is_c_any(filename) or is_cmake(filename) or is_glsl(filename)) # and is_svn_file(filename)
112 def cmake_advanced_info():
113 """ Extracr includes and defines from cmake.
116 def create_eclipse_project(CMAKE_DIR):
118 if sys.platform == "win32":
119 cmd = 'cmake %r -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR
121 cmd = 'cmake %r -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR
130 create_eclipse_project(CMAKE_DIR)
132 from xml.dom.minidom import parse
133 tree = parse(os.path.join(CMAKE_DIR, ".cproject"))
135 f = open(".cproject_pretty", 'w')
136 f.write(tree.toprettyxml(indent=" ", newl=""))
138 ELEMENT_NODE = tree.ELEMENT_NODE
140 cproject, = tree.getElementsByTagName("cproject")
141 for storage in cproject.childNodes:
142 if storage.nodeType != ELEMENT_NODE:
145 if storage.attributes["moduleId"].value == "org.eclipse.cdt.core.settings":
146 cconfig = storage.getElementsByTagName("cconfiguration")[0]
147 for substorage in cconfig.childNodes:
148 if substorage.nodeType != ELEMENT_NODE:
151 moduleId = substorage.attributes["moduleId"].value
153 # org.eclipse.cdt.core.settings
154 # org.eclipse.cdt.core.language.mapping
155 # org.eclipse.cdt.core.externalSettings
156 # org.eclipse.cdt.core.pathentry
157 # org.eclipse.cdt.make.core.buildtargets
159 if moduleId == "org.eclipse.cdt.core.pathentry":
160 for path in substorage.childNodes:
161 if path.nodeType != ELEMENT_NODE:
163 kind = path.attributes["kind"].value
166 # <pathentry kind="mac" name="PREFIX" path="" value=""/opt/blender25""/>
167 defines.append((path.attributes["name"].value, path.attributes["value"].value))
169 # <pathentry include="/data/src/blender/blender/source/blender/editors/include" kind="inc" path="" system="true"/>
170 includes.append(path.attributes["include"].value)
174 return includes, defines
177 def cmake_cache_var(var):
178 cache_file = open(os.path.join(CMAKE_DIR, "CMakeCache.txt"))
179 lines = [l_strip for l in cache_file for l_strip in (l.strip(),) if l_strip if not l_strip.startswith("//") if not l_strip.startswith("#")]
183 if l.split(":")[0] == var:
184 return l.split("=", 1)[-1]
188 def cmake_compiler_defines():
189 compiler = cmake_cache_var("CMAKE_C_COMPILER") # could do CXX too
192 print("Couldn't find the compiler, os defines will be omitted...")
196 temp_c = tempfile.mkstemp(suffix=".c")[1]
197 temp_def = tempfile.mkstemp(suffix=".def")[1]
199 os.system("%s -dM -E %s > %s" % (compiler, temp_c, temp_def))
201 temp_def_file = open(temp_def)
202 lines = [l.strip() for l in temp_def_file if l.strip()]
203 temp_def_file.close()
211 def create_qtc_project_main():
212 files = list(source_list(base, filename_check=is_project_file))
213 files_rel = [relpath(f, start=PROJECT_DIR) for f in files]
216 # --- qtcreator specific, simple format
217 if SIMPLE_PROJECTFILE:
218 # --- qtcreator specific, simple format
219 PROJECT_NAME = "Blender"
220 f = open(join(PROJECT_DIR, "%s.files" % PROJECT_NAME), 'w')
221 f.write("\n".join(files_rel))
223 f = open(join(PROJECT_DIR, "%s.includes" % PROJECT_NAME), 'w')
224 f.write("\n".join(sorted(list(set(dirname(f) for f in files_rel if is_c_header(f))))))
226 qtc_prj = join(PROJECT_DIR, "%s.creator" % PROJECT_NAME)
227 f = open(qtc_prj, 'w')
228 f.write("[General]\n")
230 qtc_cfg = join(PROJECT_DIR, "%s.config" % PROJECT_NAME)
231 if not exists(qtc_cfg):
232 f = open(qtc_cfg, 'w')
233 f.write("// ADD PREDEFINED MACROS HERE!\n")
235 includes, defines = cmake_advanced_info()
237 # for some reason it doesnt give all internal includes
238 includes = list(set(includes) | set(dirname(f) for f in files_rel if is_c_header(f)))
241 PROJECT_NAME = "Blender"
242 FILE_NAME = PROJECT_NAME.lower()
243 f = open(join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w')
244 f.write("\n".join(files_rel))
246 f = open(join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w')
247 f.write("\n".join(sorted(includes)))
249 qtc_prj = join(PROJECT_DIR, "%s.creator" % FILE_NAME)
250 f = open(qtc_prj, 'w')
251 f.write("[General]\n")
253 qtc_cfg = join(PROJECT_DIR, "%s.config" % FILE_NAME)
254 f = open(qtc_cfg, 'w')
255 f.write("// ADD PREDEFINED MACROS HERE!\n")
256 defines_final = [("#define %s %s" % item) for item in defines]
257 defines_final += cmake_compiler_defines() # defines from the compiler
258 f.write("\n".join(defines_final))
260 print("Blender project file written to: %s" % qtc_prj)
264 def create_qtc_project_python():
265 files = list(source_list(base, filename_check=is_py))
266 files_rel = [relpath(f, start=PROJECT_DIR) for f in files]
269 # --- qtcreator specific, simple format
270 PROJECT_NAME = "Blender_Python"
271 FILE_NAME = PROJECT_NAME.lower()
272 f = open(join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w')
273 f.write("\n".join(files_rel))
275 qtc_prj = join(PROJECT_DIR, "%s.creator" % FILE_NAME)
276 f = open(qtc_prj, 'w')
277 f.write("[General]\n")
279 qtc_cfg = join(PROJECT_DIR, "%s.config" % FILE_NAME)
280 if not exists(qtc_cfg):
281 f = open(qtc_cfg, 'w')
282 f.write("// ADD PREDEFINED MACROS HERE!\n")
284 print("Python project file written to: %s" % qtc_prj)
288 create_qtc_project_main()
289 create_qtc_project_python()
292 if __name__ == "__main__":