Example #1
0
def ExpandAllVariables(expression, workspace, projName, projConfName = '', 
                       fileName = ''):
    '''展开所有变量,所有变量引用的形式都会被替换
    会展开脱字符(`)的表达式,但是,不展开 $(shell ) 形式的表达式

    先展开内部的变量,再展开环境变量,最后展开 `` 的表达式
    只作一次展开,不会递归展开

    expression      - 需要展开的表达式, 可为空
    workspace       - 工作区实例, 可为空
    projName        - 项目名字, 可为空
    projConfName    - 项目构建设置名称, 可为空
    fileName        - 文件名字, 要求为绝对路径, 可为空

    RETURN          - 展开后的表达式'''
    from EnvVarSettings import EnvVarSettingsST

    exp = expression
    # 先展开内置宏
    exp = ExpandAllInterMacros(exp, workspace, projName, projConfName, fileName)
    # 再展开环境变量
    exp = EnvVarSettingsST.Get().ExpandVariables(exp, trim=True)
    # 最后展开``
    exp = ExpandBacktick(exp)
    # 最最后处理转义的 '$'
    return exp.replace('$$', '$')
Example #2
0
 def __GetDefaultBldCmd(self, projNames, wspConfName):
     '''projNames 可以是单个项目名称的字符串'''
     wspIns = VLWorkspaceST.Get()
     self.Exports(projNames, wspConfName)
     blderCmd = self.command
     blderCmd = EnvVarSettingsST.Get().ExpandVariables(blderCmd)
     wspMakefile = '%s_wsp.mk' % wspIns.GetName()
     return 'cd %s && %s %s' % (EscStr4MkSh(
         wspIns.dirName), blderCmd, EscStr4MkSh(wspMakefile))
Example #3
0
def ExpandAllVariables_SList(exprList, workspace, projName, projConfName = '',
                             fileName = ''):
    '''批量展开,经常用到'''
    from EnvVarSettings import EnvVarSettingsST
    # 先批量展开内部宏
    exprList = ExpandAllInterMacros(exprList, workspace, projName,
                                    projConfName, fileName)
    result = []
    for exp in exprList:
        # 再展开环境变量
        exp = EnvVarSettingsST.Get().ExpandVariables(exp, trim=True)
        # 最后展开``
        exp = ExpandBacktick(exp)
        # 最最后处理转义的 '$'
        result.append(exp.replace('$$', '$'))
    return result
Example #4
0
    def GenerateMakefile(self, projName, projConfName, force=False):
        '''此函数会跳过不必要的 Makefile 创建行为'''
        wspIns = VLWorkspaceST.Get()
        projInst = wspIns.FindProjectByName(projName)
        if not projInst or not projConfName:
            return False

        settings = projInst.GetSettings()
        projBldConfIns = wspIns.GetProjBuildConf(projName, projConfName)
        if not settings or not projBldConfIns:
            return False

        ds = Globals.DirSaver()
        os.chdir(projInst.dirName)

        absProjMakefile = os.path.join(projInst.dirName, projName + '.mk')
        # 如果已存在 makefile,且非强制,且项目文件没有修改,跳过
        if not force and not projInst.IsModified() \
           and os.path.exists(absProjMakefile):
            # 添加判断,比较项目文件与 makefile 的时间戳,
            # 只有 makefile 比项目文件新才跳过
            mkModTime = Globals.GetMTime(absProjMakefile)
            if mkModTime > Globals.GetMTime(projInst.GetFileName()):
                return True  # 无须重建,直接结束

        # 自定义构建的处理是不一样的
        isCustomBuild = projBldConfIns.IsCustomBuild()
        #isCustomBuild = True

        mkdir = 'gmkdir -p' if Globals.IsWindowsOS() else 'mkdir -p'

        # 重建流程
        text = ''
        text += '##\n'
        text += '## Auto generated by Builder "%s" of VimLite\n' % self.name
        text += '## Do not edit this file, any manual changes will be erased\n'
        text += '##\n'

        # 输出环境变量
        # 必须首先输出, 因为内部变量可能用到了环境变量
        text += '\n'
        text += '##\n'
        text += '## User defined environment variables\n'
        text += '##\n'
        for envVar in EnvVarSettingsST.Get().GetActiveEnvVars():
            #text += '%s := %s\n' % (envVar.GetKey(), envVar.GetValue())
            text += '%s\n' % (envVar.GetString().replace('=', ':=', 1))
        text += '\n'

        if isCustomBuild:  # 自定义构建的处理
            text += '## ===== Available Macros =====\n'
            text += self.CreateAvailableMacros(projInst, projBldConfIns)
            text += '\n'
            buildCmds = projBldConfIns.GetCustomBuildCmd()
            cleanCmds = projBldConfIns.GetCustomCleanCmd()
            workDir = projBldConfIns.GetCustomBuildWorkingDir()
            if not workDir:
                workDir = '.'
            cdCmd = 'cd $(WorkDir) && '
            text += '''\
## variables
MKDIR   := %s
WorkDir := %s
PHONY   := all clean DirSanity Build Clean Rebuild

## builtin targets
define BuildCommands
%s
endef

define CleanCommands
%s
endef

all: Build

clean: Clean

DirSanity:
\t@$(MKDIR) $(WorkDir)

Build: DirSanity
\t$(BuildCommands)

Clean: DirSanity
\t$(CleanCommands)

Rebuild: DirSanity
\t$(CleanCommands)
\t$(BuildCommands)

''' % (mkdir, EscStr4MkSh(workDir), cdCmd + buildCmds, cdCmd + cleanCmds)
            customTargets = projBldConfIns.GetCustomTargets()
            customTargetsText = ''
            for tgt, cmd in customTargets.iteritems():
                customTargetsText += 'PHONY += %s\n' % tgt
                customTargetsText += '%s: DirSanity\n' % tgt
                customTargetsText += '\t%s\n' % (cdCmd + cmd, )
                customTargetsText += '\n'
            text += customTargetsText
            text += '.PHONY: $(PHONY)'
        #### 自定义构建处理完毕
        else:  # 非自定义构建时的处理
            text += self.CreateConfigsVariables(projInst, projBldConfIns)

            # 如此实现批量添加包含路径即可
            text += '# auto\n'
            # 添加 CCXXFLAGS
            #text += 'CFLAGS    += $(CCXXFLAGS)\n'
            #text += 'CXXFLAGS  += $(CCXXFLAGS)\n'
            # CPPFLAGS 为 C 和 C++ 编译器共享
            text += 'CPPFLAGS  += $(foreach Dir,$(CmpIncPaths) $(IncPaths),$(IncPat))\n'
            # 预定义的宏
            text += 'CPPFLAGS  += $(foreach Mac,$(Macros),$(MacPat))\n'
            # 库文件搜索路径
            text += 'LDFLAGS   += $(foreach Lip,$(CmpLibPaths) $(LibPaths),$(LipPat))\n'
            # 链接的库
            text += 'LDFLAGS   += $(foreach Lib,$(Libraries),$(LibPat))\n'
            text += '\n'

            text += '# ###\n'
            # 源文件
            text += 'SourceFile = $<\n'
            # 对象文件
            text += 'ObjectFile = $(OutDir)/$(notdir $(basename $(SourceFile)))$(ObjExt)\n'
            # 输出的依赖文件
            text += 'DependFile = $(OutDir)/$(notdir $(basename $(SourceFile)))$(DepExt)\n'
            # 输出的预处理文件
            text += 'PrePrcFile = $(OutDir)/$(notdir $(basename $(SourceFile)))$(PrpExt)\n'
            text += '\n'

            t1, fileRules = self.CreateFileTargets(projInst, projBldConfIns)

            text += t1

            preBldCmd = ''
            postBldCmd = ''
            preCmds = [
                i for i in projBldConfIns.GetPreBuildCommands() if i.enabled
            ]
            if preCmds:
                preBldCmd += '\t@echo ===== Pre Build Commands Start... =====\n'
                preBldCmd += '\n'.join(['\t%s' % i.command
                                        for i in preCmds]) + '\n'
                preBldCmd += '\t@echo ===== Pre Build Commands Done. =====\n'
            postCmds = [
                i for i in projBldConfIns.GetPostBuildCommands() if i.enabled
            ]
            if postCmds:
                postBldCmd += '\t@echo ===== Post Build Commands Start... =====\n'
                postBldCmd += '\n'.join(['\t%s' % i.command
                                         for i in postCmds]) + '\n'
                postBldCmd += '\t@echo ===== Post Build Commands Done. =====\n'

            text += 'MKDIR = %s\n' % (mkdir, )

            # DirSanity -> PreBuild -> $(Objects) -> $(OutputFile) -> PostBuild
            # DirSanity 放到 all 的依赖列表的第一位,会跑得比较快,测试表明可用
            # NOTE: 如果作为 PreBuild 的依赖,则可能 $(Objects): PreBuild 会导致
            # 依赖查找,而先于 DirSanity 执行,最终会造成找不到 c 依赖文件而终止
            # $(Objects): | PreBuild 的 PreBuild 仅为了顺序,
            # 不会影响 $(Objects) 的重建
            text += '''\
PHONY = all clean PreBuild Building PostBuild DirSanity

# ===== Targets =====
all: DirSanity PostBuild

PostBuild: Building
%s

Building: $(OutputFile)

$(OutputFile): $(Objects)
ifeq ($(ProjectType),app)
\t$(LinkCmd)
endif
ifeq ($(ProjectType),so)
\t$(SoGenCmd)
endif
ifeq ($(ProjectType),ar)
\t$(ArGenCmd)
endif

$(Objects): | PreBuild

PreBuild:
%s

DirSanity:
\t@$(MKDIR) $(OutDir)
\t@$(MKDIR) $(dir $(OutputFile))

clean:
\t$(RM) $(PrePrcs)
\t$(RM) $(Depends)
\t$(RM) $(Objects)
\t$(RM) $(OutputFile)

''' % (postBldCmd, preBldCmd)

            text += fileRules

            # NOTE: include 的时候,如果文件不存在,会在本 Makefile 中查找以这个
            # 文件名为目标的规则,如果这个规则需要一些中间目录的话,就会出错,
            # 因为这个查找是先于任何规则的,即使 Makefile 的第一个规则就是创建
            # 中间目录也没有用
            #text += '#-include $(Depends)\n'
            #text += '-include $(OutDir)/*$(DepExt)\n' # 用这句才行,真不懂
            text += '''\
ifeq ($(shell test -d $(OutDir) && echo yes || echo no),yes)
-include $(Depends)
endif
'''
            text += '\n'
            text += '.PHONY: $(PHONY)\n'
        #### 内建构建处理完毕

        #absProjMakefile = 'test.mk'
        # 写到文件
        tmpf = Globals.TempFile()
        try:
            f = open(tmpf, "wb")
            f.write(text)
            f.close()
            shutil.move(tmpf, absProjMakefile)
        except:
            os.remove(tmpf)
            print '%s: save failed!' % absProjMakefile
            raise

        projInst.SetModified(False)
        #return text
        return True
Example #5
0
def ExpandAllInterVariables(expression,
                            workspace,
                            projName,
                            projConfName='',
                            fileName='',
                            trim=False):
    '''展开所有内部变量

    expression      - 需要展开的表达式, 可为空
    workspace       - 工作区实例, 可为空
    projName        - 项目名字, 可为空
    projConfName    - 项目构建设置名称, 可为空
    fileName        - 文件名字, 要求为绝对路径, 可为空
    trim            - 是否用空字符展开没有定义的变量引用
    
    支持的变量有:
    $(User)
    $(Date)
    $(CodeLitePath)

    $(WorkspaceName)
    $(WorkspacePath)

    $(ProjectName)
    $(ProjectPath)
    $(ConfigurationName)
    $(IntermediateDirectory)    - 这个变量可能嵌套
    $(OutDir)                   - 这个变量可能嵌套

    $(ProjectFiles)
    $(ProjectFilesAbs)

    $(CurrentFileName)
    $(CurrentFileExt)
    $(CurrentFilePath)
    $(CurrentFileFullPath)
    '''
    from EnvVarSettings import EnvVarSettingsST

    if not '$' in expression:
        return expression

    dVariables = {}

    dVariables['User'] = getpass.getuser()
    dVariables['Date'] = time.strftime('%Y-%m-%d', time.localtime())
    dVariables['CodeLitePath'] = os.path.expanduser('~/.codelite')

    if workspace:
        dVariables['WorkspaceName'] = workspace.GetName()
        dVariables['WorkspacePath'] = workspace.dirName
        project = workspace.FindProjectByName(projName)
        if project:
            dVariables['ProjectName'] = project.GetName()
            dVariables['ProjectPath'] = project.dirName

            bldConf = workspace.GetProjBuildConf(project.GetName(),
                                                 projConfName)
            if bldConf:
                dVariables['ConfigurationName'] = bldConf.GetName()
                imd = bldConf.GetIntermediateDirectory()
                # 先展开中间目录的变量
                # 中间目录不能包含自身和自身的别名 $(OutDir)
                # 可包含的变量为此之前添加的变量
                imd = EnvVarSettingsST.Get().ExpandVariables(imd)
                imd = ExpandVariables(imd, dVariables)
                dVariables['IntermediateDirectory'] = imd
                dVariables['OutDir'] = imd

            # NOTE: 是必定包含忽略的文件的
            if '$(ProjectFiles)' in expression:
                dVariables['ProjectFiles'] = \
                        ' '.join([ '"%s"' % i for i in project.GetAllFiles()])
            if '$(ProjectFilesAbs)' in expression:
                dVariables['ProjectFilesAbs'] = \
                        ' '.join([ '"%s"' % i for i in project.GetAllFiles(True)])

    if fileName:
        dVariables['CurrentFileName'] = \
                os.path.splitext(os.path.basename(fileName))[0]
        dVariables['CurrentFileExt'] = \
                os.path.splitext(os.path.basename(fileName))[1][1:]
        dVariables['CurrentFilePath'] = \
                NormalizePath(os.path.dirname(fileName))
        dVariables['CurrentFileFullPath'] = NormalizePath(fileName)

    if dVariables.has_key('OutDir'):  # 这个变量由于由用户定义,所以可以嵌套变量
        imd = dVariables['OutDir']
        del dVariables['OutDir']
        del dVariables['IntermediateDirectory']
        imd = ExpandVariables(imd, dVariables, False)
        # 再展开环境变量
        imd = EnvVarSettingsST.Get().ExpandVariables(imd, True)
        dVariables['OutDir'] = imd
        dVariables['IntermediateDirectory'] = dVariables['OutDir']

    # 先这样展开,因为内部变量不允许覆盖,内部变量可以保证不嵌套变量
    expression = ExpandVariables(expression, dVariables, False)
    # 再展开环境变量, 因为内部变量不可能包含环境变量
    expression = EnvVarSettingsST.Get().ExpandVariables(expression, trim)

    return expression