Some small fixes and changes:
[blender.git] / build_files / cmake / project_info.py
1 #!/usr/bin/env python
2
3 # ***** BEGIN GPL LICENSE BLOCK *****
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #
19 # Contributor(s): Campbell Barton, M.G. Kishalmi
20 #
21 # ***** END GPL LICENSE BLOCK *****
22
23 # <pep8 compliant>
24
25 """
26 Example Win32 usage:
27  c:\Python32\python.exe c:\blender_dev\blender\build_files\cmake\cmake_qtcreator_project.py c:\blender_dev\cmake_build
28
29 example linux usage
30  python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake
31 """
32
33 __all__ = (
34     "SIMPLE_PROJECTFILE",
35     "SOURCE_DIR",
36     "CMAKE_DIR",
37     "PROJECT_DIR",
38     "source_list",
39     "is_project_file",
40     "is_c_header",
41     "is_py",
42     "cmake_advanced_info",
43     "cmake_compiler_defines",
44 )
45
46 import sys
47 import os
48 from os.path import join, dirname, normpath, abspath, splitext, exists
49
50 SOURCE_DIR = join(dirname(__file__), "..", "..")
51 SOURCE_DIR = normpath(SOURCE_DIR)
52 SOURCE_DIR = abspath(SOURCE_DIR)
53
54 SIMPLE_PROJECTFILE = False
55
56 # get cmake path
57 CMAKE_DIR = sys.argv[-1]
58
59 if not exists(join(CMAKE_DIR, "CMakeCache.txt")):
60     CMAKE_DIR = os.getcwd()
61 if not exists(join(CMAKE_DIR, "CMakeCache.txt")):
62     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()))
63     sys.exit(1)
64
65
66 # could be either.
67 # PROJECT_DIR = SOURCE_DIR
68 PROJECT_DIR = CMAKE_DIR
69
70
71 def source_list(path, filename_check=None):
72     for dirpath, dirnames, filenames in os.walk(path):
73
74         # skip '.svn'
75         if dirpath.startswith("."):
76             continue
77
78         for filename in filenames:
79             filepath = join(dirpath, filename)
80             if filename_check is None or filename_check(filepath):
81                 yield filepath
82
83
84 # extension checking
85 def is_cmake(filename):
86     ext = splitext(filename)[1]
87     return (ext == ".cmake") or (filename.endswith("CMakeLists.txt"))
88
89
90 def is_c_header(filename):
91     ext = splitext(filename)[1]
92     return (ext in (".h", ".hpp", ".hxx"))
93
94
95 def is_py(filename):
96     ext = splitext(filename)[1]
97     return (ext == ".py")
98
99
100 def is_glsl(filename):
101     ext = splitext(filename)[1]
102     return (ext == ".glsl")
103
104
105 def is_c(filename):
106     ext = splitext(filename)[1]
107     return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc"))
108
109
110 def is_c_any(filename):
111     return is_c(filename) or is_c_header(filename)
112
113
114 def is_svn_file(filename):
115     dn, fn = os.path.split(filename)
116     filename_svn = join(dn, ".svn", "text-base", "%s.svn-base" % fn)
117     return exists(filename_svn)
118
119
120 def is_project_file(filename):
121     return (is_c_any(filename) or is_cmake(filename) or is_glsl(filename))  # and is_svn_file(filename)
122
123
124 def cmake_advanced_info():
125     """ Extracr includes and defines from cmake.
126     """
127
128     def create_eclipse_project(CMAKE_DIR):
129         print("CMAKE_DIR %r" % CMAKE_DIR)
130         if sys.platform == "win32":
131             cmd = 'cmake "%s" -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR
132         else:
133             cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR
134
135         os.system(cmd)
136
137     includes = []
138     defines = []
139
140     create_eclipse_project(CMAKE_DIR)
141
142     from xml.dom.minidom import parse
143     tree = parse(join(CMAKE_DIR, ".cproject"))
144     '''
145     f = open(".cproject_pretty", 'w')
146     f.write(tree.toprettyxml(indent="    ", newl=""))
147     '''
148     ELEMENT_NODE = tree.ELEMENT_NODE
149
150     cproject, = tree.getElementsByTagName("cproject")
151     for storage in cproject.childNodes:
152         if storage.nodeType != ELEMENT_NODE:
153             continue
154
155         if storage.attributes["moduleId"].value == "org.eclipse.cdt.core.settings":
156             cconfig = storage.getElementsByTagName("cconfiguration")[0]
157             for substorage in cconfig.childNodes:
158                 if substorage.nodeType != ELEMENT_NODE:
159                     continue
160
161                 moduleId = substorage.attributes["moduleId"].value
162
163                 # org.eclipse.cdt.core.settings
164                 # org.eclipse.cdt.core.language.mapping
165                 # org.eclipse.cdt.core.externalSettings
166                 # org.eclipse.cdt.core.pathentry
167                 # org.eclipse.cdt.make.core.buildtargets
168
169                 if moduleId == "org.eclipse.cdt.core.pathentry":
170                     for path in substorage.childNodes:
171                         if path.nodeType != ELEMENT_NODE:
172                             continue
173                         kind = path.attributes["kind"].value
174
175                         if kind == "mac":
176                             # <pathentry kind="mac" name="PREFIX" path="" value="&quot;/opt/blender25&quot;"/>
177                             defines.append((path.attributes["name"].value, path.attributes["value"].value))
178                         elif kind == "inc":
179                             # <pathentry include="/data/src/blender/blender/source/blender/editors/include" kind="inc" path="" system="true"/>
180                             includes.append(path.attributes["include"].value)
181                         else:
182                             pass
183
184     return includes, defines
185
186
187 def cmake_cache_var(var):
188     cache_file = open(join(CMAKE_DIR, "CMakeCache.txt"))
189     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("#")]
190     cache_file.close()
191
192     for l in lines:
193         if l.split(":")[0] == var:
194             return l.split("=", 1)[-1]
195     return None
196
197
198 def cmake_compiler_defines():
199     compiler = cmake_cache_var("CMAKE_C_COMPILER")  # could do CXX too
200
201     if compiler is None:
202         print("Couldn't find the compiler, os defines will be omitted...")
203         return
204
205     import tempfile
206     temp_c = tempfile.mkstemp(suffix=".c")[1]
207     temp_def = tempfile.mkstemp(suffix=".def")[1]
208
209     os.system("%s -dM -E %s > %s" % (compiler, temp_c, temp_def))
210
211     temp_def_file = open(temp_def)
212     lines = [l.strip() for l in temp_def_file if l.strip()]
213     temp_def_file.close()
214
215     os.remove(temp_c)
216     os.remove(temp_def)
217     return lines