Beispiel #1
0
 def GetProjectBuildConfig(self, projName, wspConfName=''):
     matrix = VLWorkspaceST.Get().GetBuildMatrix()
     if not wspConfName:
         wspConfName = matrix.GetSelectedConfigurationName()
     projConfName = matrix.GetProjectSelectedConf(wspConfName, projName)
     projInst = VLWorkspaceST.Get().FindProjectByName(projName)
     projBldConfIns = VLWorkspaceST.Get().GetProjBuildConf(
         projName, projConfName)
     return projBldConfIns
Beispiel #2
0
def test():
    assert SplitStrBySemicolon('abc;def') == ['abc', 'def']
    assert SplitStrBySemicolon(';abc;def') == ['abc', 'def']
    assert SplitStrBySemicolon('abc;def;') == ['abc', 'def']
    assert SplitStrBySemicolon('abc;;d;ef;') == ['abc;d', 'ef']

    from BuilderManager import BuilderManagerST
    import json
    assert SplitStrBySemicolon("snke;;;snekg;") == ['snke;', 'snekg']
    print SmclStr2MkStr("s n'\"\"'ke;;;snekg;")
    ins = VLWorkspaceST.Get()
    ins.OpenWorkspace("CxxParser/CxxParser.vlworkspace")
    print ins.projects

    return
    bm = BuilderManagerST.Get()
    #blder = BuilderGnuMake(
    #BuildSettingsST.Get().GetBuilderByName(
    #"GNU makefile for g++/gcc").ToDict())
    blder = bm.GetActiveBuilderInstance()
    bs = BuildSettingsST.Get()
    #print bs.ToDict()
    #print bs.GetCompilerByName('gnu g++')
    print blder.Exports(['CxxParser'])
    #print blder.GenerateMakefile('CxxParser', 'mindll')
    #print '=' * 78
    #print blder.GenerateMakefile('CxxParser', 'Debug')
    print blder.GetPrepFileCmd('CxxParser', 'main.cpp', 'Debug')
    print blder.GetCmplFileCmd('CxxParser', 'main.cpp', 'Debug')
    print blder.GetBuildCommand('CxxParser')
    print blder.GetCleanCommand('CxxParser')
    print blder.GetBatchBuildCommand(['CxxParser'])
    print blder.GetBatchCleanCommand(['CxxParser'])
    print json.dumps(blder.ToDict())
Beispiel #3
0
 def __GetPrpOrObjCmd(self, projName, fileName, wspConfName='', t='prp'):
     wspIns = VLWorkspaceST.Get()
     wspConfName = wspConfName \
             or wspIns.GetBuildMatrix().GetSelectedConfigurationName()
     self.Exports(projName, wspConfName)
     projInst = wspIns.FindProjectByName(projName)
     projBldConfIns = self.GetProjectBuildConfig(projName, wspConfName)
     cmplName = projBldConfIns.GetCompilerType()
     cmpl = BuildSettingsST.Get().GetCompilerByName(cmplName)
     if projBldConfIns.IsCustomBuild():
         return ''
     if not cmpl:  # 编译器实例总会可能是空的
         return 'echo "%s is not a valid complier!"'
     ds = Globals.DirSaver()
     os.chdir(projInst.dirName)
     if os.path.isabs(fileName):
         fileName = os.path.relpath(fileName)
     mkFile = '%s.mk' % projName
     bwd = projBldConfIns.GetIntermediateDirectory() or '.'
     # 展开所有 VimLite 内置变量
     bwd = Globals.ExpandAllInterVariables(bwd, wspIns, projName,
                                           wspConfName)
     if t == 'prp':  # 预处理目标
         fn = os.path.splitext(fileName)[0] + cmpl.prpExt
     else:  # 对象目标,用于编译文件
         fn = os.path.splitext(fileName)[0] + cmpl.objExt
     tgt = '%s/%s' % (bwd, fn)
     cmd = 'cd %s && make -f %s %s ' % (EscStr4MkSh(
         projInst.dirName), EscStr4MkSh(mkFile), EscStr4MkSh(tgt))
     return cmd
Beispiel #4
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))
Beispiel #5
0
 def CreateAvailableMacros(self, projInst, projBldConfIns):
     '''内部定义的宏(变量),导出为 gnu make 的形式'''
     ws = VLWorkspaceST.Get()
     text = ''
     text += 'WorkspaceName          := %s\n' \
             % EscStr4MkSh(ws.GetName()) # 因为可能用在命令行中,所以需要转义
     text += 'WorkspacePath          := $(CURDIR)/%s\n' \
             % EscStr4MkSh(os.path.relpath(ws.dirName, projInst.dirName))
     text += 'ProjectName            := %s\n' \
             % EscStr4MkSh(projInst.GetName())
     text += 'ProjectPath            := $(CURDIR)\n'
     text += 'ConfigurationName      := %s\n' \
             % EscStr4MkSh(projBldConfIns.GetName())
     text += 'IntermediateDirectory  := %s\n' \
             % EscStr4MkSh(projBldConfIns.GetOutDir()) or '.'
     text += 'OutDir                 := %s\n' % '$(IntermediateDirectory)'
     text += 'User                   := %s\n' \
             % EscStr4MkSh(getpass.getuser())
     text += 'Date                   := %s\n' \
             % time.strftime('%Y-%m-%d', time.localtime())
     return text
Beispiel #6
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
Beispiel #7
0
    def Exports(self, projNames, wspConfName="", force=False):
        '''导出 Makefile 的接口,这个不算通用接口吧?!
        若 wspConfName 为空,即表示用当前选择的工作区设置'''
        if not projNames:
            return False

        if isinstance(projNames, str):
            projNames = [projNames]

        # 忽略不存在的项目
        removeList = []
        for projName in projNames:
            projInst = VLWorkspaceST.Get().FindProjectByName(projName)
            if not projInst:
                removeList.append(projName)
                print "%s not found" % projName
                continue

        matrix = VLWorkspaceST.Get().GetBuildMatrix()
        if not wspConfName:
            wspConfName = matrix.GetSelectedConfigurationName()
        else:
            force = True  # 不使用默认设置,就肯定要强制

        # 工作区的 Makefile
        wspMakefile = VLWorkspaceST.Get().GetName() + '_wsp.mk'
        # 转为绝对路径
        wspMakefile = os.path.join(VLWorkspaceST.Get().dirName, wspMakefile)

        text = ''
        text += 'PHONY := all clean\n\n'

        allTgtText = 'all:\n'
        cleanTgtText = 'clean:\n'
        customTgtText = ''

        for idx, projName in enumerate(projNames):
            # 项目设置名称
            projInst = VLWorkspaceST.Get().FindProjectByName(projName)
            if not projInst:
                continue
            projConfName = matrix.GetProjectSelectedConf(wspConfName, projName)
            # 项目设置实例
            projBldConfIns = VLWorkspaceST.Get().GetProjBuildConf(
                projName, projConfName)

            projMakefile = projName + ".mk"
            cddir = os.path.relpath(projInst.dirName,
                                    VLWorkspaceST.Get().dirName)

            envCmd = ''
            # FIXME: 找到办法把这个命令放到项目的 Makefile 前暂时这么做
            cmplName = projBldConfIns.GetCompilerType()
            cmpl = BuildSettingsST.Get().GetCompilerByName(cmplName)
            if cmpl and cmpl.envSetupCmd:
                envCmd = '%s && ' % cmpl.envSetupCmd

            # all 目标的命令部分
            allTgtText += \
                    '\t@echo "----------Building Project:[ %s - %s ]----------"\n'\
                    % (projName, projConfName)
            allTgtText += '\t@%scd %s && $(MAKE) -f %s $@\n' \
                    % (envCmd, EscStr4MkSh(cddir), EscStr4MkSh(projMakefile))

            # clean 目标的命令部分
            cleanTgtText += \
                    '\t@echo "----------Cleaning Project:[ %s - %s ]----------"\n'\
                    % (projName, projConfName)
            cleanTgtText += '\t@cd %s && $(MAKE) -f %s $@\n' \
                    % (EscStr4MkSh(cddir), EscStr4MkSh(projMakefile))

            # 第一个项目的时候,需要添加 Custom Build 目标,如果必要的话
            # 因为 Batch Build 是不支持特殊的 Custom Build 目标的
            if idx == 0 and projBldConfIns.IsCustomBuild():
                for k, v in projBldConfIns.GetCustomTargets().iteritems():
                    customTgtText += 'PHONY += %s\n' % k
                    customTgtText += '%s:\n' % k
                    customTgtText += '\t@cd %s && $(MAKE) -f %s $@\n' \
                            % (EscStr4MkSh(cddir), EscStr4MkSh(projMakefile))

            # 生成项目自身的 Makefile
            self.GenerateMakefile(projName, projConfName, force)

        text += allTgtText + "\n" + cleanTgtText + "\n" + customTgtText
        text += '\n'
        text += '.PHONY: $(PHONY)\n'

        tmpf = Globals.TempFile()
        try:
            f = open(tmpf, "wb")
            f.write(text)
            f.close()
            shutil.move(tmpf, wspMakefile)
        except:
            os.remove(tmpf)
            raise

        #return text
        return True