def build_libraries( ctx_modules, lib_name, output_path, build_dir, session ): # # Build either one library of all modules, or one library for each module. # if not os.path.exists( output_path ): os.makedirs( output_path ) libs = dict() if lib_name != None: libs[lib_name] = assureList( ctx_modules ) else: for mod in ctx_modules: libs[mod.getName()] = [mod,] all_objects = list() for lib, mods in libs.iteritems(): ctx_log.ctxlogBeginLibrary( lib ) obj_list = list() for mod in mods: mod_objs = mod.buildStaticObjects( session, build_dir ) obj_list += mod_objs if len(obj_list) > 0: session.buildStaticLibrary( obj_list, lib, output_path ) else: warningMessage("No object files to create library '%s'"%(lib)) all_objects+= obj_list ctx_log.ctxlogEndLibrary() return all_objects
def cmd_clean(args): view_dir = get_view_dir(args.view) obj_dir = view_dir + os.sep + '.ctx/obj' if args.all == True: import shutil try: shutil.rmtree(obj_dir) infoMessage("All objects successfully removed.") except: warningMessage("No objects removed.") pass
def cmd_clean(args): output_dir = args.view + os.sep + '.ctx/obj' if args.all == True: import shutil try: shutil.rmtree(output_dir) infoMessage("All objects successfully removed.") except: warningMessage("No objects removed.") pass else: errorMessage("Only 'ctx clean --all' can currently be used.")
def export_headers( depmgr, headers, headerDir ): if not os.path.exists( headerDir ): os.makedirs( headerDir ) infoMessage("Exporting headers", 1) for header in headers: src = depmgr.getFullPathname ( header ) if src != None: dst = os.path.join( headerDir, header ) infoMessage("%s -> %s"%(src, dst), 2) if not os.path.abspath(dst) == os.path.abspath(src): shutil.copyfile( src, dst ) else: warningMessage("Unable to locate header '%s' for export"%(header))
def export_headers( depmgr, headers, headerDir, cview ): if not os.path.exists( headerDir ): os.makedirs( headerDir ) #infoMessage("Exporting headers", 1) for header in headers: header_found = False src = depmgr.getFullPathname ( header ) dst = os.path.join( headerDir, header ) if src != None: infoMessage("%s -> %s"%(src, dst), 2) if not os.path.abspath(dst) == os.path.abspath(src): shutil.copyfile( src, dst ) header_found = True else: header_extensions = [ '.h','.hpp', ] module_paths = cview.getItemPaths('modules') for module_path in module_paths: if not os.path.isdir( module_path ): continue diritems = os.listdir( module_path ) for modname in diritems: if not os.path.isdir( os.path.join(module_path, modname) ): continue moddir = os.path.join(module_path, modname) for hdrcand in os.listdir( moddir ): if hdrcand != header: continue root, ext = os.path.splitext( hdrcand ) if header_extensions.count( ext ) != 0: src = os.path.join( moddir, hdrcand) shutil.copyfile( src , dst ) header_found = True # infoMessage("Exporting header: %s (from %s)"%(os.path.basename(src), os.path.dirname(src))) if not header_found: warningMessage("Unable to locate header '%s' for export"%(header))
def cmd_parse( args ): import string infoMessage("Receiving export data from Contexo...", 1) package = ctx_export.CTXExportData() package.receive() # Reads pickled export data from stdin infoMessage("Received export data:", 4) for item in package.export_data.keys(): infoMessage("%s: %s"%(item, str(package.export_data[item])), 4) # Retrieve build config from session bc_file = package.export_data['SESSION'].getBCFile() build_params = bc_file.getBuildParams() debugmode = bool( not args.release ) tests = package.export_data['TESTS'] # # Add module paths/repositories as include directories # modTags = list() incPaths = list() # the preprocessor define COMPILING_MOD_ is a legacy definition, # initially created to make sure private headers were not included in a # project. # this is kept to build legacy products if args.legacy_compiling_mod: depRoots = package.export_data['PATHS']['MODULES'] for depRoot in depRoots: incPathCandidates = os.listdir( depRoot ) for cand in incPathCandidates: path = os.path.join(depRoot, cand) if contexo.ctx_cmod.isContexoCodeModule( path ): rawMod = contexo.ctx_cmod.CTXRawCodeModule(path) modTags.append( 'COMPILING_MOD_' + string.upper( rawMod.getName() ) ) # # Collect additional include paths and additional library paths # def getPathsFromOption(option): user_paths = list() if os.path.isdir( option ): user_paths.append(option) elif not os.path.isfile( option ): userErrorExit("Cannot find option file or directory'%s'"%option) else: file = open( option, "r" ) for line in file.readlines(): line = line.strip() user_paths += line.split(";") file.close() user_paths = filter(lambda x: x.strip(" ") != '',user_paths) dirname = os.path.abspath(os.path.dirname(filename)) return map (lambda path: os.path.join(dirname, path), user_paths) if args.additional_includes != None: filename = args.additional_includes user_includepaths = getPathsFromOption(filename) #dirname = os.path.dirname(filename) for inc in user_includepaths: incPaths.append(inc) #print >>sys.stderr, 'incPaths %s' %incPaths libPaths = list() if args.additional_libdir != None: filename = args.additional_libdir user_librarypaths = getPathsFromOption(filename) libPaths += user_librarypaths # Additional dependencies libNames = list() user_libnames = list() if args.additional_dependencies != None: filename = args.additional_dependencies user_libnames = getPathsFromOption(filename) libNames += user_libnames # # Determin if we're exporting components or modules, and do some related # sanity checks # comp_export = bool( package.export_data['COMPONENTS'] != None ) if comp_export: #Exporting components if args.mirror_components == True and args.project_name != None: warningMessage("Ignoring option --project-name (-pn) when option --mirror-components (-mc) is used") args.project_name = None else: # Exporting modules if args.mirror_components == True: warningMessage("Ignoring option --mirror-components (-mc) when exporting modules") args.mirror_components = False if package.export_data['MODULES'] == None: userErrorExit( "No components or modules specified for export.") project_name = args.project_name if project_name == None and args.mirror_components == False: project_name = default_projname # strip vcproj extension if user included it. if project_name != None and project_name[ -7: ].lower() == '.vcproj': project_name = project_name[0:-7] # # If exporting components and the user specified --mirror-components we # create one vcproj per component library, otherwise we create one large # library of all code modules. # vcprojList = list() # list of dict['PROJNAME':string, 'LIBNAME':string, 'MODULELIST':listof( see doc of make_libvcproj7 ) ] # Regardless if we export components or modules, all modules are located in export_data['MODULES'] depMgr = package.export_data['DEPMGR'] module_map = create_module_mapping_from_module_list( package.export_data['MODULES'], depMgr) if comp_export and args.mirror_components: for comp in package.export_data['COMPONENTS']: for library, modules in comp.libraries.iteritems(): lib_modules = [ mod for mod in module_map if mod['MODNAME'] in modules ] vcprojList.append( { 'PROJNAME': library, 'LIBNAME': library, 'MODULELIST': lib_modules } ) else: # Module export OR component export without mirroring component structure vcprojList.append( {'PROJNAME': project_name, 'LIBNAME': project_name, 'MODULELIST': module_map } ) # # Generate the projects # if not os.path.exists( args.output ): os.makedirs( args.output ) guidDict = dict() for proj in vcprojList: #codeModules = listof dictionaries: { MODNAME: string, SOURCES: list(paths), PRIVHDRS: list(paths), PUBHDRS: list(paths), PRIVHDRDIR: string, TESTSOURCES:list } guidDict[proj['PROJNAME']] = contexo.ctx_msvc.make_libvcproj8( proj['PROJNAME'], build_params.cflags, build_params.prepDefines + modTags, proj['MODULELIST'], proj['LIBNAME'] + '.lib', debugmode, tests, incPaths, args.output, args.platform, proj['PROJNAME'], args.configuration_type, libNames, libPaths ) # # Handle external project if specified # external_vcproj = None if args.external_vcproj != None: external_vcproj = contexo.ctx_msvc.get_info_vcproj8( os.path.abspath( args.external_vcproj ) ) external_vcproj['DEBUG'] = debugmode attrs = list() attrs.append( dict({ "DEBUG":debugmode, "TOOL":"VCCLCompilerTool", "KEY":"AdditionalIncludeDirectories", "VALUE":";".join(incPaths) })) attrs.append( dict({ "DEBUG":debugmode, "TOOL":"VCLinkerTool", "KEY":"AdditionalLibraryDirectories", "VALUE":";".join(libPaths) })) contexo.ctx_msvc.update_vcproj8(external_vcproj['FILENAME'],attrs) # # Create solution if specified # if args.solution != None: slnProjects = list() for proj in vcprojList: slnProjects.append( { 'PROJNAME': proj['PROJNAME'], 'PROJGUID': guidDict[proj['PROJNAME']], 'DEBUG': debugmode } ) contexo.ctx_msvc.make_solution8( args.solution, args.output, slnProjects, external_vcproj, args.platform ) # # The End # infoMessage("Export done.", 1)
def cmd_parse( args ): import string infoMessage("Receiving export data from Contexo...", 1) package = ctx_export.CTXExportData() package.receive() # Reads pickled export data from stdin infoMessage("Received export data:", 4) for item in package.export_data.keys(): infoMessage("%s: %s"%(item, str(package.export_data[item])), 4) # Retrieve build config from session bc_file = package.export_data['SESSION'].getBCFile() build_params = bc_file.getBuildParams() #TODO? debugmode = bool( not args.release ) # # Add module paths/repositories as include directories # modTags = list() incPaths = list() depRoots = package.export_data['PATHS']['MODULES'] depMgr = package.export_data['DEPMGR'] for depRoot in depRoots: incPathCandidates = os.listdir( depRoot ) for cand in incPathCandidates: path = os.path.join(depRoot, cand) if contexo.ctx_cmod.isContexoCodeModule( path ): rawMod = contexo.ctx_cmod.CTXRawCodeModule(path) incPaths.append( path ) # Only include private headers for projects containing the specified module #incPaths.append( os.path.join(rawMod.getRootPath(), rawMod.getPrivHeaderDir()) ) modTags.append( 'COMPILING_MOD_' + string.upper( rawMod.getName() ) ) # # Determine if we're exporting components or modules, and do some related # sanity checks # comp_export = bool( package.export_data['COMPONENTS'] != None ) if comp_export: #Exporting components pass else: # Exporting modules userErrorExit( "No components specified. Currently no support for module-export.") # Regardless if we export components or modules, all modules are located in export_data['MODULES'] module_map = create_module_mapping_from_module_list( package.export_data['MODULES'].values() ) allSources = [] # Used to find a common path. allCtxMods = {} staticLibs = [] if comp_export: for comp in package.export_data['COMPONENTS']: for library, modules in comp.libraries.iteritems(): ctxMods = [ mod for mod in module_map if mod['MODNAME'] in modules ] staticLibs.append( { 'PROJNAME': library, 'LIBNAME': library, 'MODULELIST': ctxMods } ) for ctxMod in ctxMods: allSources.extend(ctxMod["SOURCES"]) if not allCtxMods.has_key(ctxMod['MODNAME']): allCtxMods[ctxMod['MODNAME']] = [] allCtxMods[ctxMod['MODNAME']].append(comp) for ctxModName, comps in allCtxMods.iteritems(): if len(comps) > 1: warningMessage("Contexo module, '%s' specified in multiple .comp-files:" % (ctxModName)) for comp in comps: warningMessage(" %s." % (comp.path)) # Basic argument checks if args.ndk == None and args.mydroid == None: userErrorExit("Must specify either --ndk or --mydroid.") elif args.ndk <> None and args.mydroid <> None: userErrorExit("Specified both --ndk and --mydroid.") elif args.ndk <> None: if not os.path.isdir(args.ndk): userErrorExit("'%s' specified by --ndk does not exist or is not a directory." % (args.ndk)) else: if not os.path.isdir(args.mydroid): userErrorExit("'%s' specified by --mydroid does not exist or is not a directory." % (args.mydroid)) if args.app == None: userErrorExit("--app not specified.") if args.arm_mode <> None and not args.arm_mode in ["arm", "thumb"]: userErrorExit("Illegal arm mode '%s', specified with --arm-mode." % (args.arm_mode)) if args.abs_sub <> None: if (len(args.abs_sub) % 2 != 0): userErrorExit("--abs-sub: number of arguments must be a 2-multiple.") global absPathSub absPathSub = args.abs_sub if args.rel_sub <> None: if (len(args.rel_sub) % 2 != 0): userErrorExit("--rel-sub: number of arguments must be a 2-multiple.") global relPathSub relPathSub = args.rel_sub # This will be used as LOCAL_PATH for all (android) modules. # By using this path we ensure that no paths contain any "..". # (They would mess up the android build system.) localPath = lowestCommonPath(allSources) # Returns a path to be used in a makefile. def getDstPath(*pathComps): if args.project <> None: if not os.path.isabs(args.project): return os.path.join(os.getcwd(), args.project, *pathComps).replace("\\", "/") else: return os.path.join(args.project, *pathComps).replace("\\", "/") elif args.ndk <> None: return os.path.join(args.ndk, "apps", args.app, "project", *pathComps).replace("\\", "/") else: return os.path.join(args.mydroid, args.app, *pathComps).replace("\\", "/") # Returns a path that locates where to actually put a file. def getOutPath(*pathComps): if args.output <> None: if not os.path.isabs(args.output): return os.path.join(os.getcwd(), args.output, "apps", args.app, "project", *pathComps).replace("\\", "/") else: return os.path.join(args.output, "apps", args.app, "project", *pathComps).replace("\\", "/") else: return getDstPath(*pathComps) if args.ndk <> None: # Determine location of the Application.mk. if args.output == None: applicationDir = os.path.join(args.ndk, "apps", args.app) else: if not os.path.isabs(args.output): applicationDir = os.path.join(os.getcwd(), args.output, "apps", args.app).replace("\\", "/") else: applicationDir = os.path.join(args.output, "apps", args.app).replace("\\", "/") libPath = args.mk_path else: # Source tree build, determine location of the main Android.mk. if args.output == None: applicationDir = os.path.join(args.mydroid, args.app) else: if not os.path.isabs(args.output): applicationDir = os.path.join(os.getcwd(), args.output, args.app).replace("\\", "/") else: applicationDir = os.path.join(args.output, args.app).replace("\\", "/") libPath = "" # Determine if anything is to be omitted. if args.no <> None: argOmits = [no.lower() for no in args.no] for omit in argOmits: if not omits.has_key(omit): userErrorExit("'%s' is not a valid argument to --no." % (omit)) else: omits[omit] = True if args.mydroid <> None and args.project == None: omits["top"] = True # We generate one makefile per library. # This variable could be possible to change via commandline. # However, it's more practical to subdivide into several # makefiles. If one of them is changed all others needn't be rebuilt. allInOne = False sharedObjLib = None if args.shared <> None: if len(args.shared) == 0: userErrorExit("No libraries specifed by --shared.") partsOfShared = [] for name in args.shared: for libMod in staticLibs: if libMod["LIBNAME"] == name: break else: userErrorExit("Contexo library '%s', specified by --shared not found in export." % (name)) del staticLibs[staticLibs.index(libMod)] partsOfShared.append(libMod) name = args.shared[0] if args.shared_name == None else args.shared_name sharedObjLib = { 'PROJNAME': name, 'LIBNAME': name, 'MODULELIST': [], 'SHAREDOBJECT' : True } for part in partsOfShared: sharedObjLib['MODULELIST'].extend(part['MODULELIST']) else: if args.ldlibs <> None: warningMessage("Ignoring option --ldlibs since --shared was not specified.") if args.shared_name <> None: warningMessage("Ignoring option --shared-name since --shared was not specified.") staticRelPath = "static" sharedRelPath = "shared" mkFileVerbosity = 1 if not omits["static"] and len(staticLibs) > 0: if not allInOne: for staticLib in staticLibs: dirName = staticRelPath + "_" + staticLib['LIBNAME'] lclDstDir = getDstPath(libPath, dirName) lclOutDir = getOutPath(libPath, dirName) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") content = moduleMk(staticLib, build_params, staticLibs, None, depMgr, lclDstDir, args, localPath=localPath) createFile(mkFileName, content, args) infoMessage("Created %s" % (mkFileName), mkFileVerbosity) else: lclDstDir = getDstPath(libPath, staticRelPath) lclOutDir = getOutPath(libPath, staticRelPath) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") file = open(mkFileName, "wt") i = 0 for staticLib in staticLibs: file.write(moduleMk(staticLib, build_params, staticLibs, None, depMgr, lclDstDir, args, localPath=localPath)) file.write("#" * 60 + "\n") i += 1 file.close() infoMessage("Created %s" % (mkFileName), mkFileVerbosity) if sharedObjLib <> None and not omits["shared"]: lclDstDir = getDstPath(libPath, sharedRelPath) lclOutDir = getOutPath(libPath, sharedRelPath) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") content = moduleMk(sharedObjLib, build_params, staticLibs, None, depMgr, lclDstDir, args, localPath=localPath) createFile(mkFileName, content, args) if args.static_libs == None and len(staticLibs) > 0: warningMessage("Computed link order is very likely not accurate.") warningMessage("See %s." % (mkFileName)) infoMessage("Created %s" % (mkFileName), mkFileVerbosity) if args.prebuilt <> None and not omits["prebuilt"]: name = "prebuilt" lclDstDir = getDstPath(libPath, name) lclOutDir = getOutPath(libPath, name) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") content = prebuiltMk(args) createFile(mkFileName, content, args) if not omits["top"]: if not os.path.isdir(getOutPath(libPath)): os.makedirs(getOutPath(libPath)) topMkFileName = getOutPath(libPath, "Android.mk") createFile(topMkFileName, "include $(call all-subdir-makefiles)", args) if not omits["app"]: if not os.path.isdir(applicationDir): os.makedirs(applicationDir) outData = [] if args.ndk <> None: appMkFileName = os.path.join(applicationDir, "Application.mk") libNames = [staticLib['LIBNAME'] for staticLib in staticLibs] if sharedObjLib <> None: libNames.append(sharedObjLib['LIBNAME']) outData.append("APP_MODULES := %s\n" % (" ".join(libNames))) if args.project <> None: outData.append("APP_PROJECT_PATH := %s\n" % (absPath(getDstPath()))) else: outData.append("APP_PROJECT_PATH := $(call my-dir)/project\n") if bc_file.dbgmode: outData.append("APP_OPTIM := debug\n") if args.vars_app <> None: outData.append(writeVars(args.vars_app, "--vars-app")) else: appMkFileName = os.path.join(applicationDir, "Android.mk") if args.project <> None: outData.append("include $(call all-makefiles-under,%s)\n" % (absPath(getDstPath()))) else: outData.append("include $(call all-subdir-makefiles)\n") content = "".join(outData) createFile(appMkFileName, content, args) # # The End # infoMessage("Export done.", 1)
def deprecated_tolerate_missing_headers_warning(args): if args.tolerate_missing_headers: warningMessage('--tolerate-missing-headers is deprecated and redunant. The default is to ignore missing headers and let the compiler abort compilation if necessary. To get the old behaviour where contexo aborts when headers are missing: use the \'--fail-on-missing-headers\' option.')
def deprecated_nra_warning( args ): if args.no_remote_repo_access == True: warningMessage("--no-repo-access is deprecated. remote access will always be performed when running 'ctx view update' and 'ctx view validate'. At other times, there will be no network communication and .rspecs will be cached.")
def deprecated_repo_validation_warning(args): if args.repo_validation: warningMessage('--repo-validation is deprecated. Please run \'ctx view validate\' manually to validate the view.')
def cmd_build(args): launch_path = os.path.abspath('.') view_dir = get_view_dir(args.view) obj_dir = view_dir + os.sep + '.ctx/obj' # test if not absolute path if args.output[0] != '/' and args.output[0] != '\\' and args.output[1:3] != ':\\': lib_output = os.path.join(view_dir,args.output) else: lib_output = args.output lib_dirs = map(os.path.abspath, args.libdirs) from contexo import ctx_cmod from contexo import ctx_base from contexo import ctx_envswitch from contexo.ctx_depmgr import CTXDepMgr from contexo.ctx_export import CTXExportData envLayout = None oldEnv = None if args.env != None: envLayout = EnvironmentLayout( cfgFile, args.env ) oldEnv = switchEnvironment( envLayout, True ) absIncDirs = map(os.path.abspath, args.incdirs) # Prepare all deprecated_nra_warning( args ) deprecated_repo_validation_warning(args) cview = ctx_view.CTXView( view_dir, validate=False ) bc = getBuildConfiguration( cview, args ) bc.buildParams.incPaths.extend( absIncDirs ) #TODO: accessing 'private' data? bc.buildParams.ldDirs.extend(lib_dirs) bc.buildParams.ldLibs.extend(args.libs) archPath = list() archPath = bc.getArchPath() deprecated_tolerate_missing_headers_warning(args) depmgr = CTXDepMgr ( codeModulePaths = cview.getItemPaths('modules'), failOnMissingHeaders = args.fail_on_missing_headers, archPath = bc.getArchPath(), additionalIncDirs = absIncDirs, legacyCompilingMod = args.legacy_compiling_mod, legacyDuplicateSources = args.legacy_duplicate_sources, globalOutputDir = obj_dir, bc = bc ) session = ctx_base.CTXBuildSession( bc ) session.setDependencyManager( depmgr ) items = expand_list_files( cview, args.items ) # Make sure we have only one type of item to export #TODO:make a more robust recognition than file extention for .comp component_build = True for item in items: if item.endswith( '.comp' ): if component_build == False: userErrorExit("The operation can either work on a list of components OR a list of modules, not both.") else: component_build = False # Register build configuration in log handler ctx_log.ctxlogSetBuildConfig( bc.getTitle(), bc.getCompiler().cdefTitle, bc.getBuildParams().cflags, bc.getBuildParams().prepDefines, "N/A" ) outputPath = lib_output bin_dir = os.path.join( outputPath, args.bindir ) header_dir = os.path.join( outputPath, args.headerdir ) objs = list() ## TODO: place this in CTXCompiler where it belongs when the spaghetti code is gone ## changing working directory to .ctx/obj/[BUILDCONFIGNAME] dest_wd = os.path.join(obj_dir, bc.getTitle()) try: os.makedirs(dest_wd) except: pass old_path = os.path.abspath('') os.chdir(dest_wd) # Process components if component_build: infoMessage("Building components...", 1) components = create_components( items, cview.getItemPaths('comp'), obj_dir, launch_path ) allmods = set() for comp in components: for library, modules in comp.libraries.items(): mods = expand_list_files( cview, modules ) depmgr.addCodeModules( mods, args.tests ) allmods |= set(modules) depMods = depmgr.getModuleDependencies(allmods) depmgr.emptyCodeModules() if len(depMods - set(allmods)) > 0: for module in depMods - set(allmods): warningMessage('The module \"'+module+'\" was not specified to be built in any specified .comp file, but at least one of its headers were included in another module, linker errors may arise') for comp in components: ctx_log.ctxlogBeginComponent( comp.name ) # Build component modules. for library, modules in comp.libraries.items(): modules = expand_list_files( cview, modules ) depmgr.addCodeModules( modules, args.tests ) args.library_name = library infoMessage('args: %s'%args, 6) objs += buildmodules( depmgr, session, modules, args, bin_dir, session.bc.getTitle(), args.library_name) if (args.all_headers): header_path = os.path.join(lib_output, args.headerdir ) export_public_module_headers( depmgr, modules, header_path ) depmgr.emptyCodeModules() export_headers( depmgr, comp.publicHeaders, header_dir, cview ) ctx_log.ctxlogEndComponent() #Process modules else: infoMessage("Building modules...", 1) depmgr.addCodeModules( items, args.tests ) if args.deps: print >>sys.stderr, "Dependencies for:", print >>sys.stderr, items print >>sys.stderr, depmgr.getCodeModulesWithDependencies() objs += buildmodules( depmgr, session, items, args, outputPath, bc.getTitle(), libraryName=args.library_name) export_public_module_headers( depmgr, items, header_dir ) if args.executable_name: session.linkExecutable(objs, bin_dir, args.executable_name) # Write log if requested if args.logfile != None: logfilepath = os.path.join( lib_output, args.logfile ) logpath = os.path.normpath(os.path.dirname( logfilepath )) if len(logpath) and not os.path.isdir(logpath): os.makedirs( logpath ) ctx_log.ctxlogWriteToFile( logfilepath, appendToExisting=False ) os.chdir(old_path) # Restore environment if args.env != None: switchEnvironment( oldEnv, False )
def cmd_buildcomp(args): launch_path = os.path.abspath('.') view_dir = get_view_dir(args.view) obj_dir = view_dir + os.sep + '.ctx/obj' if args.output[0] == '/' or args.output[0] == '\\' or args.output[1:3] == ':\\': lib_output = args.output else: # relative to view root lib_output = os.path.join(view_dir,args.output) from contexo import ctx_cmod from contexo import ctx_base from contexo import ctx_envswitch from contexo.ctx_depmgr import CTXDepMgr absIncDirs = map(os.path.abspath, args.incdirs) # Switch to specified environment oldEnv = None if args.env != None: envLayout = EnvironmentLayout( cfgFile, args.env ) oldEnv = switchEnvironment( envLayout, True ) if args.logfile != None: ctx_log.ctxlogStart() # Prepare all deprecated_nra_warning( args ) deprecated_repo_validation_warning(args) cview = ctx_view.CTXView( view_dir, validate=False ) components = expand_list_files( cview, args.components ) bc = getBuildConfiguration( cview, args ) bc.buildParams.incPaths.extend( absIncDirs ) #TODO: accessing 'private' data? deprecated_tolerate_missing_headers_warning(args) depmgr = CTXDepMgr ( codeModulePaths = cview.getItemPaths('modules'), failOnMissingHeaders = args.fail_on_missing_headers, archPath = bc.getArchPath(), legacyCompilingMod = args.legacy_compiling_mod, legacyDuplicateSources = args.legacy_duplicate_sources, globalOutputDir = obj_dir, bc = bc ) session = ctx_base.CTXBuildSession( bc ) session.setDependencyManager( depmgr ) # Register build configuration in log handler ctx_log.ctxlogSetBuildConfig( bc.getTitle(), bc.getCompiler().cdefTitle, bc.getBuildParams().cflags, bc.getBuildParams().prepDefines, "N/A" ) ## TODO: place this in CTXCompiler where it belongs when the spaghetti code is gone ## changing working directory to .ctx/obj/[BUILDCONFIGNAME] dest_wd = os.path.join(obj_dir, bc.getTitle()) try: os.makedirs(dest_wd) except: pass old_path = os.path.abspath('') os.chdir(dest_wd) deleteModuleSources = set() # Process components components = create_components( components, cview.getItemPaths('comp'), obj_dir, launch_path ) infoMessage("Building components...", 1) allmods = set() for comp in components: for library, modules in comp.libraries.items(): mods = expand_list_files( cview, modules ) depmgr.addCodeModules( mods, args.tests ) allmods |= set(modules) depMods = depmgr.getModuleDependencies(allmods) depmgr.emptyCodeModules() if len(depMods - set(allmods)) > 0: for module in depMods - set(allmods): warningMessage('The module \"'+module+'\" was not specified to be built in any specified .comp file, but at least one of its headers were included in another module, linker errors may arise') for comp in components: ctx_log.ctxlogBeginComponent( comp.name ) lib_dir = os.path.join( lib_output, args.libdir ) header_dir = os.path.join( lib_output, args.headerdir ) # Build component modules. for library, modules in comp.libraries.items(): modules = expand_list_files( cview, modules ) depmgr.addCodeModules( modules, args.tests ) args.lib = library infoMessage('args: %s'%args, 6) buildmodules( depmgr, session, modules, args, lib_dir, session.bc.getTitle(), libraryName = args.lib) if args.deletesources == True: for module in modules: modPath = depmgr.resolveCodeModulePath(module) deleteModuleSources.add(modPath) depmgr.emptyCodeModules() export_headers( depmgr, comp.publicHeaders, header_dir, cview ) ctx_log.ctxlogEndComponent() # Write log if requested if args.logfile != None: logfilepath = os.path.join( lib_output, args.logfile ) logpath = os.path.normpath(os.path.dirname( logfilepath )) if len(logpath) and not os.path.isdir(logpath): os.makedirs( logpath ) ctx_log.ctxlogWriteToFile( logfilepath, appendToExisting=False ) os.chdir(old_path) # Restore environment if args.env != None: switchEnvironment( oldEnv, False ) if args.deletesources == True: modPath = depmgr.resolveCodeModulePath(module) for modpath in deleteModuleSources: try: srcdir = os.path.join(modpath, 'src') shutil.rmtree(srcdir) infoMessage("Removing source directory: " + srcdir, 1) except: pass try: incdir = os.path.join(modpath, 'inc') shutil.rmtree(incdir) infoMessage("Removing private include directory: " + incdir, 1) except: pass try: testdir = os.path.join(modpath, 'test') shutil.rmtree(testdir) infoMessage("Removing test source directory: " + testdir, 1) except: pass
makefile.write(objfile+" ") makefile.write("\n") makefile.write("\t$(AR) r $@") for objfile in objectfiles: makefile.write(" " + objfile) makefile.write("\n") makefile.write("\t$(RANLIB) $@\n") for headerFile in headerFiles: if headerDict.has_key(headerFile): makefile.write("\t$(EXPORT_CMD) "+headerDict[headerFile]+ " " + os.path.join("$(HDRDIR)", headerFile) + "\n") else: warningMessage('Headerfile '+headerFile+' could not be located') makefile.write("\n") makefile.write("\n") makefile.write("### Object definitions\n") for mod in module_map: for srcFile in mod['SOURCES']: objfile = os.path.basename(srcFile)[:-2]+".o" makefile.write(os.path.join("$(OBJDIR)", objfile) + ": " + srcFile) for hdr in mod['DEPHDRS']: makefile.write(" " + hdr) makefile.write("\n") if srcFile[-4:] == '.cpp': makefile.write("\t$(CXX) $(CXXFLAGS) $(ADDFLAGS)")
def cmd_parse( args ): import string infoMessage("Receiving export data from Contexo...", 1) package = ctx_export.CTXExportData() package.receive() # Reads pickled export data from stdin infoMessage("Received export data:", 4) for item in package.export_data.keys(): infoMessage("%s: %s"%(item, str(package.export_data[item])), 4) # Retrieve build config from session bc_file = package.export_data['SESSION'].getBCFile() build_params = bc_file.getBuildParams() #TODO? debugmode = bool( not args.release ) # # Add module paths/repositories as include directories # modTags = list() incPaths = list() depRoots = package.export_data['PATHS']['MODULES'] depMgr = package.export_data['DEPMGR'] for depRoot in depRoots: incPathCandidates = os.listdir( depRoot ) for cand in incPathCandidates: path = os.path.join(depRoot, cand) if contexo.ctx_cmod.isContexoCodeModule( path ): rawMod = contexo.ctx_cmod.CTXRawCodeModule(path) incPaths.append( path ) # Only include private headers for projects containing the specified module #incPaths.append( os.path.join(rawMod.getRootPath(), rawMod.getPrivHeaderDir()) ) modTags.append( 'COMPILING_MOD_' + string.upper( rawMod.getName() ) ) # # Determine if we're exporting components or modules, and do some related # sanity checks # comp_export = bool( package.export_data['COMPONENTS'] != None ) if comp_export: #Exporting components pass else: # Exporting modules userErrorExit( "No components specified. Currently no support for module-export.") # Regardless if we export components or modules, all modules are located in export_data['MODULES'] module_map = create_module_mapping_from_module_list( package.export_data['MODULES'].values() ) staticLibs = [] if comp_export: for comp in package.export_data['COMPONENTS']: for library, modules in comp.libraries.iteritems(): ctxMods = [ mod for mod in module_map if mod['MODNAME'] in modules ] staticLibs.append( { 'PROJNAME': library, 'LIBNAME': library, 'MODULELIST': ctxMods } ) if args.ndk == None: userErrorExit("--ndk not specified.") if not os.path.isdir(args.ndk): userErrorExit("'%s' specified by --ndk does not exist or is not a directory." % (args.ndk)) if args.app == None: userErrorExit("--app not specified.") if args.abs_sub <> None: if (len(args.abs_sub) % 2 != 0): userErrorExit("--abs-sub: number of arguments must be a 2-multiple.") global absPathSub absPathSub = args.abs_sub if args.rel_sub <> None: if (len(args.rel_sub) % 2 != 0): userErrorExit("--rel-sub: number of arguments must be a 2-multiple.") global relPathSub relPathSub = args.rel_sub # Set up paths. def getDstPath(*pathComps): if args.project <> None: if not os.path.isabs(args.project): return os.path.join(os.getcwd(), args.project, *pathComps).replace("\\", "/") else: return os.path.join(args.project, *pathComps).replace("\\", "/") else: return os.path.join(args.ndk, "apps", args.app, "project").replace("\\", "/") def getOutPath(*pathComps): if args.output <> None: if not os.path.isabs(args.output): return os.path.join(os.getcwd(), args.output, "apps", args.app, "project", *pathComps).replace("\\", "/") else: return os.path.join(args.output, "apps", args.app, "project", *pathComps).replace("\\", "/") else: return getDstPath(*pathComps) if args.output == None: applicationDir = os.path.join(args.ndk, "apps", args.app) else: if not os.path.isabs(args.output): applicationDir = os.path.join(os.getcwd(), args.output, "apps", args.app).replace("\\", "/") else: applicationDir = os.path.join(args.output, "apps", args.app).replace("\\", "/") #projectPath = "project" #libPath = os.path.join(projectPath, args.mk_path) libPath = args.mk_path # Determine if anything is to be omitted. omits = {"static" : False, "shared" : False, "top" : False, "app" : False} if args.no <> None: argOmits = [no.lower() for no in args.no] for omit in argOmits: if not omits.has_key(omit): userErrorExit("'%s' is not a valid argument to --no." % (omit)) else: omits[omit] = True # # Generate the makefile # # if not os.path.exists( outDir ): # os.makedirs( outDir ) # There were some problems when one makefile per comp was created, (with the android build). # I guess it should be possible to do it that way. # However this way has proved to work. # So, we set allInOne to True. allInOne = True sharedObjLib = None if args.shared <> None: if len(args.shared) == 0: userErrorExit("No libraries specifed by --shared.") partsOfShared = [] for name in args.shared: for libMod in staticLibs: if libMod["LIBNAME"] == name: break else: userErrorExit("Contexo library '%s', specified by --shared not found in export." % (name)) del staticLibs[staticLibs.index(libMod)] partsOfShared.append(libMod) name = args.shared[0] if args.shared_name == None else args.shared_name sharedObjLib = { 'PROJNAME': name, 'LIBNAME': name, 'MODULELIST': [], 'SHAREDOBJECT' : True } for part in partsOfShared: sharedObjLib['MODULELIST'].extend(part['MODULELIST']) else: if args.ldlibs <> None: warningMessage("Ignoring option --ldlibs since --shared was not specified.") if args.shared_name <> None: warningMessage("Ignoring option --shared-name since --shared was not specified.") ldlibs = args.ldlibs staticRelPath = "static" sharedRelPath = "shared" mkFileVerbosity = 1 if not omits["static"] and len(staticLibs) > 0: if not allInOne: for staticLib in staticLibs: lclDstDir = getDstPath(libPath, staticLib['LIBNAME']) lclOutDir = getOutPath(libPath, staticLib['LIBNAME']) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") file = open(mkFileName, "wt") file.write(moduleMk(staticLib, build_params, staticLibs, None, depMgr, lclDstDir)) file.close() infoMessage("Created %s" % (mkFileName), mkFileVerbosity) else: lclDstDir = getDstPath(libPath, staticRelPath) lclOutDir = getOutPath(libPath, staticRelPath) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") file = open(mkFileName, "wt") i = 0 for staticLib in staticLibs: file.write(moduleMk(staticLib, build_params, staticLibs, None, depMgr, lclDstDir, i == 0)) file.write("#" * 60 + "\n") i += 1 file.close() infoMessage("Created %s" % (mkFileName), mkFileVerbosity) if sharedObjLib <> None and not omits["shared"]: lclDstDir = getDstPath(libPath, sharedRelPath) lclOutDir = getOutPath(libPath, sharedRelPath) if not os.path.exists(lclOutDir): os.makedirs(lclOutDir) mkFileName = os.path.join(lclOutDir, "Android.mk") file = open(mkFileName, "wt") file.write(moduleMk(sharedObjLib, build_params, staticLibs, None, depMgr, lclDstDir, localPath=True, ldlibs=ldlibs, staticLibs=args.static_libs)) file.close() if args.static_libs == None: warningMessage("Computed link order is very likely not accurate.") warningMessage("See %s." % (mkFileName)) infoMessage("Created %s" % (mkFileName), mkFileVerbosity) if not omits["top"]: topMkFileName = getOutPath(libPath, "Android.mk") file = open(topMkFileName, "wt") file.write("include $(call all-subdir-makefiles)") file.close() if not omits["app"]: appMkFileName = os.path.join(applicationDir, "Application.mk") file = open(appMkFileName, "wt") libNames = [staticLib['LIBNAME'] for staticLib in staticLibs] if sharedObjLib <> None: libNames.append(sharedObjLib['LIBNAME']) file.write("APP_PROJECT_PATH := $(call my-dir)/project\n") file.write("APP_MODULES := %s\n" % (" ".join(libNames))) if args.project <> None: file.write("APP_PROJECT_PATH := %s" % (absPath(getDstPath()))) if bc_file.dbgmode: file.write("APP_OPTIM := debug\n") file.close() # # The End # infoMessage("Export done.", 1)