예제 #1
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 = Misc.DirSaver()
     os.chdir(projInst.dirName)
     if os.path.isabs(fileName):
         fileName = os.path.relpath(fileName)
     mkFile = '%s.mk' % projInst.GetBase()
     bwd = projBldConfIns.GetIntermediateDirectory() or '.'
     # 展开所有变量
     bwd = ExpandAllVariables(bwd, wspIns, projName, projBldConfIns.name)
     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
예제 #2
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 = Misc.DirSaver()
        os.chdir(projInst.dirName)

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

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

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

        # 重建流程
        text = ''
        text += '##\n'
        text += '## Auto generated by Builder "%s" of Videm\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 += '''\
# Generate and include dependencies if we can
ifeq ($(shell test -d $(OutDir) && echo yes || echo no),yes)
  ifeq ($(shell test -f $(word 1,$(Depends)) && echo yes || echo no),yes)
    include $(Depends)
  endif
endif
'''
            text += '\n'
            text += '.PHONY: $(PHONY)\n'
        #### 内建构建处理完毕

        #absProjMakefile = 'test.mk'
        # 写到文件
        tmpf = 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