1#!/usr/bin/env python3 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# ***** END GPL LICENSE BLOCK ***** 20 21# <pep8 compliant> 22 23""" 24Example linux usage 25 python3 ~/blender-git/blender/build_files/cmake/cmake_netbeans_project.py ~/blender-git/cmake 26 27Windows not supported so far 28""" 29 30import sys 31 32# until we have arg parsing 33import project_info 34if not project_info.init(sys.argv[-1]): 35 sys.exit(1) 36 37from project_info import ( 38 SIMPLE_PROJECTFILE, 39 SOURCE_DIR, 40 CMAKE_DIR, 41 PROJECT_DIR, 42 source_list, 43 is_project_file, 44 is_c_header, 45 # is_py, 46 cmake_advanced_info, 47 cmake_compiler_defines, 48 cmake_cache_var, 49 project_name_get, 50) 51 52 53import os 54from os.path import join, dirname, normpath, relpath, exists 55 56 57def create_nb_project_main(): 58 from xml.sax.saxutils import escape 59 60 files = list(source_list(SOURCE_DIR, filename_check=is_project_file)) 61 files_rel = [relpath(f, start=PROJECT_DIR) for f in files] 62 files_rel.sort() 63 64 if SIMPLE_PROJECTFILE: 65 pass 66 else: 67 includes, defines = cmake_advanced_info() 68 69 if (includes, defines) == (None, None): 70 return 71 72 # for some reason it doesn't give all internal includes 73 includes = list(set(includes) | set(dirname(f) for f in files if is_c_header(f))) 74 includes.sort() 75 76 if 0: 77 PROJECT_NAME = "Blender" 78 else: 79 # be tricky, get the project name from git if we can! 80 PROJECT_NAME = project_name_get() 81 82 make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM") 83 make_exe_basename = os.path.basename(make_exe) 84 85 # --------------- NB specific 86 defines = [("%s=%s" % cdef) if cdef[1] else cdef[0] for cdef in defines] 87 defines += [cdef.replace("#define", "").strip() for cdef in cmake_compiler_defines()] 88 89 def file_list_to_nested(files): 90 # convert paths to hierarchy 91 paths_nested = {} 92 93 def ensure_path(filepath): 94 filepath_split = filepath.split(os.sep) 95 96 pn = paths_nested 97 for subdir in filepath_split[:-1]: 98 pn = pn.setdefault(subdir, {}) 99 pn[filepath_split[-1]] = None 100 101 for path in files: 102 ensure_path(path) 103 return paths_nested 104 105 PROJECT_DIR_NB = join(PROJECT_DIR, "nbproject") 106 if not exists(PROJECT_DIR_NB): 107 os.mkdir(PROJECT_DIR_NB) 108 109 # SOURCE_DIR_REL = relpath(SOURCE_DIR, PROJECT_DIR) 110 111 f = open(join(PROJECT_DIR_NB, "project.xml"), 'w') 112 113 f.write('<?xml version="1.0" encoding="UTF-8"?>\n') 114 f.write('<project xmlns="http://www.netbeans.org/ns/project/1">\n') 115 f.write(' <type>org.netbeans.modules.cnd.makeproject</type>\n') 116 f.write(' <configuration>\n') 117 f.write(' <data xmlns="http://www.netbeans.org/ns/make-project/1">\n') 118 f.write(' <name>%s</name>\n' % PROJECT_NAME) 119 f.write(' <c-extensions>c,m</c-extensions>\n') 120 f.write(' <cpp-extensions>cpp,cxx,cc,mm</cpp-extensions>\n') 121 f.write(' <header-extensions>h,hxx,hh,hpp,inl</header-extensions>\n') 122 f.write(' <sourceEncoding>UTF-8</sourceEncoding>\n') 123 f.write(' <make-dep-projects/>\n') 124 f.write(' <sourceRootList>\n') 125 f.write(' <sourceRootElem>%s</sourceRootElem>\n' % SOURCE_DIR) # base_root_rel 126 f.write(' </sourceRootList>\n') 127 f.write(' <confList>\n') 128 f.write(' <confElem>\n') 129 f.write(' <name>Default</name>\n') 130 f.write(' <type>0</type>\n') 131 f.write(' </confElem>\n') 132 f.write(' </confList>\n') 133 f.write(' <formatting>\n') 134 f.write(' <project-formatting-style>false</project-formatting-style>\n') 135 f.write(' </formatting>\n') 136 f.write(' </data>\n') 137 f.write(' </configuration>\n') 138 f.write('</project>\n') 139 140 f.close() 141 142 f = open(join(PROJECT_DIR_NB, "configurations.xml"), 'w') 143 144 f.write('<?xml version="1.0" encoding="UTF-8"?>\n') 145 f.write('<configurationDescriptor version="95">\n') 146 f.write(' <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">\n') 147 f.write(' <df root="%s" name="0">\n' % SOURCE_DIR) # base_root_rel 148 149 # write files! 150 files_rel_local = [normpath(relpath(join(CMAKE_DIR, path), SOURCE_DIR)) for path in files_rel] 151 files_rel_hierarchy = file_list_to_nested(files_rel_local) 152 # print(files_rel_hierarchy) 153 154 def write_df(hdir, ident): 155 dirs = [] 156 files = [] 157 for key, item in sorted(hdir.items()): 158 if item is None: 159 files.append(key) 160 else: 161 dirs.append((key, item)) 162 163 for key, item in dirs: 164 f.write('%s <df name="%s">\n' % (ident, key)) 165 write_df(item, ident + " ") 166 f.write('%s </df>\n' % ident) 167 168 for key in files: 169 f.write('%s<in>%s</in>\n' % (ident, key)) 170 171 write_df(files_rel_hierarchy, ident=" ") 172 173 f.write(' </df>\n') 174 175 f.write(' <logicalFolder name="ExternalFiles"\n') 176 f.write(' displayName="Important Files"\n') 177 f.write(' projectFiles="false"\n') 178 f.write(' kind="IMPORTANT_FILES_FOLDER">\n') 179 # f.write(' <itemPath>../GNUmakefile</itemPath>\n') 180 f.write(' </logicalFolder>\n') 181 182 f.write(' </logicalFolder>\n') 183 # default, but this dir is infact not in blender dir so we can ignore it 184 # f.write(' <sourceFolderFilter>^(nbproject)$</sourceFolderFilter>\n') 185 f.write(r' <sourceFolderFilter>^(nbproject|__pycache__|.*\.py|.*\.html|.*\.blend)$</sourceFolderFilter>\n') 186 187 f.write(' <sourceRootList>\n') 188 f.write(' <Elem>%s</Elem>\n' % SOURCE_DIR) # base_root_rel 189 f.write(' </sourceRootList>\n') 190 191 f.write(' <projectmakefile>Makefile</projectmakefile>\n') 192 193 # paths again 194 f.write(' <confs>\n') 195 f.write(' <conf name="Default" type="0">\n') 196 197 f.write(' <toolsSet>\n') 198 f.write(' <compilerSet>default</compilerSet>\n') 199 f.write(' <dependencyChecking>false</dependencyChecking>\n') 200 f.write(' <rebuildPropChanged>false</rebuildPropChanged>\n') 201 f.write(' </toolsSet>\n') 202 f.write(' <codeAssistance>\n') 203 f.write(' </codeAssistance>\n') 204 f.write(' <makefileType>\n') 205 206 f.write(' <makeTool>\n') 207 f.write(' <buildCommandWorkingDir>.</buildCommandWorkingDir>\n') 208 209 if make_exe_basename == "ninja": 210 build_cmd = "ninja" 211 clean_cmd = "ninja -t clean" 212 else: 213 build_cmd = "${MAKE} -f Makefile" 214 clean_cmd = "${MAKE} -f Makefile clean" 215 216 f.write(' <buildCommand>%s</buildCommand>\n' % escape(build_cmd)) 217 f.write(' <cleanCommand>%s</cleanCommand>\n' % escape(clean_cmd)) 218 f.write(' <executablePath>./bin/blender</executablePath>\n') 219 del build_cmd, clean_cmd 220 221 def write_toolinfo(): 222 f.write(' <incDir>\n') 223 for inc in includes: 224 f.write(' <pElem>%s</pElem>\n' % inc) 225 f.write(' </incDir>\n') 226 f.write(' <preprocessorList>\n') 227 for cdef in defines: 228 f.write(' <Elem>%s</Elem>\n' % escape(cdef)) 229 f.write(' </preprocessorList>\n') 230 231 f.write(' <cTool>\n') 232 write_toolinfo() 233 f.write(' </cTool>\n') 234 235 f.write(' <ccTool>\n') 236 write_toolinfo() 237 f.write(' </ccTool>\n') 238 239 f.write(' </makeTool>\n') 240 f.write(' </makefileType>\n') 241 # finished makefile info 242 243 f.write(' \n') 244 245 for path in files_rel_local: 246 is_c = path.endswith(".c") 247 f.write(' <item path="%s"\n' % path) 248 f.write(' ex="false"\n') 249 f.write(' tool="%d"\n' % (0 if is_c else 1)) 250 f.write(' flavor2="%d">\n' % (3 if is_c else 0)) 251 f.write(' </item>\n') 252 253 f.write(' <runprofile version="9">\n') 254 f.write(' <runcommandpicklist>\n') 255 f.write(' </runcommandpicklist>\n') 256 f.write(' <runcommand>%s</runcommand>\n' % os.path.join(CMAKE_DIR, "bin/blender")) 257 f.write(' <rundir>%s</rundir>\n' % SOURCE_DIR) 258 f.write(' <buildfirst>false</buildfirst>\n') 259 f.write(' <terminal-type>0</terminal-type>\n') 260 f.write(' <remove-instrumentation>0</remove-instrumentation>\n') 261 f.write(' <environment>\n') 262 f.write(' </environment>\n') 263 f.write(' </runprofile>\n') 264 265 f.write(' </conf>\n') 266 f.write(' </confs>\n') 267 268 # todo 269 270 f.write('</configurationDescriptor>\n') 271 272 f.close() 273 274 275def main(): 276 create_nb_project_main() 277 278 279if __name__ == "__main__": 280 main() 281