Example #1
0
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
Example #2
0
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
Example #3
0
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.")
Example #4
0
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))
Example #5
0
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))
Example #6
0
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)
Example #7
0
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)
Example #8
0
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.')
Example #9
0
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.")
Example #10
0
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.')
Example #11
0
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 )
Example #12
0
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
Example #13
0
                        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)")
Example #14
0
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)