def getAdditionalLibraryDirectories(make, cfg, output_path): list = '' paths = make.getAcrossDependencies(cfg['deps'], 'lib_path', cfg['ctx']) if paths != None: for path in paths: list += api.getRelativePath(path, output_path, 'windows') + ';' return list + '%(AdditionalLibraryDirectories)'
def getAdditionalIncludes(make, cfg, output_path): list = '' includes = make.getAcrossDependencies(cfg['deps'], 'include_path', cfg['ctx']) if includes != None: for include in includes: list += api.getRelativePath(include, output_path, 'windows') + ';' return list + '%(AdditionalIncludeDirectories)'
def outputCustomFileClDirective(base, f, make, project, file, output_path): base(f, make, project, file, output_path) ext = api.getFileExt(file['name']) if ext == '.h': for cfg in project['configurations']: if isQtSupportedTarget(cfg['ctx']['target']): basename = os.path.basename(file['name']) f.write(' <AdditionalInputs ' + vs2010.getCondition(cfg) + '>$(QTDIR)\\bin\\moc.exe;%(FullPath)</AdditionalInputs>\n') f.write(' <Message ' + vs2010.getCondition(cfg) + '>Moc%27ing ' + basename + '...</Message>\n') f.write(' <Outputs ' + vs2010.getCondition(cfg) + '>.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>\n') f.write(' <Command ' + vs2010.getCondition(cfg) + '>"$(QTDIR)\\bin\\moc.exe" "%(FullPath)" -o ".\\GeneratedFiles\\$(ConfigurationName)\\moc_%(Filename).cpp" ') defines = vs2010.getDefines(make, cfg) def_list = defines.split(';') for define in def_list: if define != '%(PreprocessorDefinitions)': f.write('-D' + define + ' ') includes = vs2010.getAdditionalIncludes(make, cfg, output_path) inc_list = includes.split(';') for inc in inc_list: if inc != '%(AdditionalIncludeDirectories)': if inc.startswith('..\\'): f.write('"-I.\\..\\..\\' + inc + '" ') else: f.write('"-I' + inc + '" ') # PCH support use_pch = make.get('use_pch', cfg['ctx']) if use_pch: f.write('"-f' + use_pch[0] + '" ') # end command f.write('"-f' + file['name'] + '"') f.write('</Command>\n') elif ext == '.qrc': for cfg in project['configurations']: if isQtSupportedTarget(cfg['ctx']['target']): qrc_name = 'qrc_' + os.path.splitext(os.path.basename(file['name']))[0] + '.cpp' f.write(' <Message ' + vs2010.getCondition(cfg) + '>Rcc%27ing %(Filename)%(Extension)...</Message>\n') f.write(' <Command ' + vs2010.getCondition(cfg) + '>"$(QTDIR)\\bin\\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\\GeneratedFiles\\' + qrc_name + '</Command>\n') resources = make.get('qt_res', cfg['ctx']) if resources: f.write(' <AdditionalInputs ' + vs2010.getCondition(cfg) + '>%(FullPath);') for res in resources: f.write(api.getRelativePath(res, output_path, 'windows') + ';') f.write('%(AdditionalInputs)</AdditionalInputs>\n') f.write(' <Outputs ' + vs2010.getCondition(cfg) + '>.\\GeneratedFiles\\' + qrc_name + ';%(Outputs)</Outputs>\n') f.write(' <SubType>Designer</SubType>\n') elif ext == '.ui': f.write(' <FileType>Document</FileType>\n') for cfg in project['configurations']: if isQtSupportedTarget(cfg['ctx']['target']): f.write(' <AdditionalInputs ' + vs2010.getCondition(cfg) + '>$(QTDIR)\\bin\\uic.exe;%(AdditionalInputs)</AdditionalInputs>\n') f.write(' <Message ' + vs2010.getCondition(cfg) + '>Uic%27ing %(Identity)...</Message>\n') f.write(' <Outputs ' + vs2010.getCondition(cfg) + '>.\\GeneratedFiles\\ui_%(Filename).h;%(Outputs)</Outputs>\n') f.write(' <Command ' + vs2010.getCondition(cfg) + '>"$(QTDIR)\\bin\\uic.exe" -o ".\\GeneratedFiles\\ui_%(Filename).h" "%(FullPath)"</Command>\n')
def outputCompilationUnitBuildDirective(f, make, ctx, cflags, prj, unit, output_path): f.write('\t' + getCompilationUnitCommand(unit, ctx) + ' $(' + get_project_cflags_varname(prj) + ') ' + getCompilationUnitCFlags(unit, cflags, ctx) + ' -o ' + unit['obj'] + ' ' + api.getRelativePath(unit['file'], output_path) + '\n')
def getOutputFilename(file, output_path): return api.getRelativePath(file, output_path)
def outputProject(f, build_env, make, ctx, prj, projects, output_path): f.write("# Project '" + prj['name'] + "' object files.\n") # project cflags f.write(get_project_cflags_varname(prj) + ' = $(GLOBAL_CFLAGS) ') cflags = make.get('cflags', ctx) outputProjectCFlags(f, ctx, cflags) if len(prj['includes']) > 0 or len(prj['defines']) > 0: for include in prj['includes']: f.write('-I' + api.getRelativePath(include, output_path) + ' ') for define in prj['defines']: f.write('-D' + define + ' ') f.write('\n\n') # project prerequesites rules prj_req_rules = [] if prj['obj_path']: # object output path prj_req_rules.append(prj['obj_path']) if prj['bin_path']: # binary output path prj_req_rules.append(prj['bin_path']) # prepare links def getProject(name): for project in projects: if project['name'] == name: return project return None prj['plinks'] = [] prj['llinks'] = [] links = make.getLinksAcrossDependencies(prj['deps'], prj['ctx']) for link in links: link_prj = getProject(link) # is it a workspace project? if link_prj: if link_prj['type'] == 'staticlib': prj['plinks'].append(link_prj) else: prj['llinks'].append(link) # compilation unit rule targets for unit in prj['units']: f.write(unit['obj'] + ': ') for dep in unit['deps']: f.write(api.getRelativePath(dep, output_path) + ' ') # directories are order-only prerequisites (right of the pipe, in a typical braindead GNU bullying way) f.write('| ' + ' '.join(prj_req_rules) + ' ') f.write('\n') outputCompilationUnitBuildDirective(f, make, ctx, cflags, prj, unit, output_path) f.write('\n') # project dependencies f.write(prj['obj'] + ': ') if prj['plinks']: for plink in prj['plinks']: f.write(plink['obj'] + ' ') for unit in prj['units']: f.write(unit['obj'] + ' ') f.write('\n') outputProjectBuildDirective(f, make, ctx, prj, output_path) # f.write('\n')
def outputProject(f, make, project, projects, output_path): # skip project if project['pflags'] != None and 'skip_build' in project['pflags']: return ctx = project['ctx'] deps = make.getDependencies(ctx) global_ctx = ctx.clone({'project': '@Exclude'}) # everything not in a project specific context f.write('# Begin project ' + ctx['project'] + '\n') f.write('#-------------------------------\n') f.write('include $(CLEAR_VARS)\n\n') f.write('LOCAL_MODULE := ' + ctx['project'] + '\n') # project cflags cflags = '' local_defines = api.substractLists(make.getAcrossDependencies(deps, 'define', ctx), make.get('define', global_ctx)) if len(local_defines) > 0: for define in local_defines: cflags += '-D' + define + ' ' local_cflags = api.substractLists(make.get('cflags', ctx), make.get('cflags', global_ctx)) gflags = convertCFlags(local_cflags) for f in gflags: cflags += f + ' ' if local_cflags != None: if 'short-commands' in local_cflags: f.write('LOCAL_SHORT_COMMANDS := true\n') if 'use-neon' in local_cflags: f.write('LOCAL_ARM_NEON := true\n') if cflags != '': f.write('LOCAL_CFLAGS := ' + cflags + '\n') # includes includes = make.getAcrossDependencies(deps, 'include_path', ctx) if includes != None: f.write('LOCAL_C_INCLUDES := ') for include in includes: f.write(api.getRelativePath(include, output_path) + ' ') f.write('\n') # output files f.write('LOCAL_SRC_FILES := \\\n') files = make.get('files', ctx) skip_files = make.get('skip_files', ctx) skip_files = [api.getRelativePath(file, output_path) for file in skip_files] if skip_files != None else [] if files != None: for file in files: ext = os.path.splitext(file)[1].lower() if ext in ['.c', '.cpp']: rel_path = api.getRelativePath(file, output_path) if rel_path not in skip_files: f.write(rel_path + ' \\\n') f.write('\n') # linkage if project['type'] != 'staticlib': l_static = '' l_shared = '' l_ldlibs = '' links = make.getLinksAcrossDependencies(deps, ctx) for link in links: prj = getProject(link, projects) # is it a workspace project? if prj != None: if prj['type'] == 'staticlib': l_static = l_static + prj['name'] + ' ' elif prj['type'] == 'dynamiclib': l_shared = l_shared + prj['name'] + ' ' else: l_ldlibs = l_ldlibs + '-l' + link + ' ' if l_static != '': f.write('LOCAL_STATIC_LIBRARIES := ' + l_static + '\n') if l_shared != '': f.write('LOCAL_SHARED_LIBRARIES := ' + l_shared + '\n') if l_ldlibs != '': f.write('LOCAL_LDLIBS := ' + l_ldlibs + '\n') if l_static != '' or l_shared != '' or l_ldlibs != '': f.write('\n') # some formatting doesn't hurt # output project type f.write('include $(' + api.translate(project['type'], {'staticlib': 'BUILD_STATIC_LIBRARY', 'dynamiclib': 'BUILD_SHARED_LIBRARY', 'executable': 'BUILD_EXECUTABLE'}, None) + ')\n') f.write('\n')
def outputProject(make, project, projects, output_path): project_ctx = project['ctx'] api.log("Output project '" + project['name'] + "'", 1) f = open(output_path + '/' + project['name'] + '.vcxproj', 'w') f.write('<?xml version="1.0" encoding="utf-8"?>\n') f.write('<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n') # configurations f.write(' <ItemGroup Label="ProjectConfigurations">\n') for cfg in project['configurations']: cfg['qualified_name'] = cfg['name'] + '|' + cfg['vsplatform'] f.write(' <ProjectConfiguration Include="' + cfg['qualified_name'] + '">\n') f.write(' <Configuration>' + cfg['name'] + '</Configuration>\n') f.write(' <Platform>' + cfg['vsplatform'] + '</Platform>\n') f.write(' </ProjectConfiguration>\n') f.write(' </ItemGroup>\n') # global properties f.write(' <PropertyGroup Label="Globals">\n') f.write(' <ProjectGuid>{' + project['guid'] + '}</ProjectGuid>\n') f.write(' <RootNamespace>' + project['name'] + '</RootNamespace>\n') f.write(' <Keyword>' + getProjectKeyword(make, project_ctx) + '</Keyword>\n') f.write(' </PropertyGroup>\n') # store a few commonly used values directly in the configuration for cfg in project['configurations']: cfg['deps'] = make.getDependencies(cfg['ctx']) cfg['links'] = make.getLinksAcrossDependencies(cfg['deps'], cfg['ctx']) cfg['type'] = make.getBestMatch('type', cfg['ctx']) cfg['cflags'] = make.get('cflags', cfg['ctx']) cfg['pflags'] = make.get('pflags', cfg['ctx']) # build the project link list across all configurations (we'll disable unused ones on a per project basis in the solution) project['all_link'] = None for cfg in project['configurations']: project['all_link'] = api.appendToList(project['all_link'], cfg['links']) if project['all_link'] != None: project['all_link'] = list(set(project['all_link'])) # cpp default properties f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n') # general project properties for cfg in project['configurations']: f.write(' <PropertyGroup ' + getCondition(cfg) + ' Label="Configuration">\n') outputGeneralProjectProperty(f, make, project, cfg) f.write(' </PropertyGroup>\n') # cpp extension settings f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n') f.write(' <ImportGroup Label="ExtensionSettings">\n') f.write(' </ImportGroup>\n') # default props for cfg in project['configurations']: f.write(' <ImportGroup Label="PropertySheets" ' + getCondition(cfg) + '>\n') f.write(' <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />\n') f.write(' </ImportGroup>\n') # user macros f.write(' <PropertyGroup Label="UserMacros" />\n') # binary output for cfg in project['configurations']: f.write(' <PropertyGroup ' + getCondition(cfg) + '>\n') f.write(' <OutDir>' + getBinaryPath(make, cfg) + '</OutDir>\n') f.write(' <IntDir>' + getIntermediatePath(make, cfg) + '</IntDir>\n') target_name = make.getBestMatch('target_name', cfg['ctx']) if not target_name: target_name = getBinaryName(project['name'], cfg['type'], cfg['ctx']['target']) suffix = make.getBestMatch('bin_suffix', cfg['ctx']) if suffix: target_name += suffix target_ext = make.getBestMatch('bin_ext', cfg['ctx']) if not target_ext: target_ext = getBinaryExt(cfg['type'], cfg['ctx']['target']) f.write(' <TargetName>' + target_name + '</TargetName>\n') f.write(' <TargetExt>' + target_ext + '</TargetExt>\n') f.write(' </PropertyGroup>\n') # compiler / linker properties for cfg in project['configurations']: ctx = cfg['ctx'] suffix = make.get('bin_suffix', ctx) f.write(' <ItemDefinitionGroup ' + getCondition(cfg) + '>\n') # compiler cflags = cfg['cflags'] outDir = '$(OutDir)' if 'debug' in cfg['cflags'] else '$(IntDir)' f.write(' <ClCompile>\n') f.write(' <PrecompiledHeader>NotUsing</PrecompiledHeader>\n') f.write(' <WarningLevel>' + getWarningLevel(cflags) + '</WarningLevel>\n') f.write(' <PreprocessorDefinitions>' + getDefines(make, cfg) + '</PreprocessorDefinitions>\n') f.write(' <AdditionalIncludeDirectories>' + getAdditionalIncludes(make, cfg, output_path) + '</AdditionalIncludeDirectories>\n') f.write(' <DebugInformationFormat>' + getDebugInformation(cflags) + '</DebugInformationFormat>\n') f.write(' <ProgramDataBaseFileName>'+ outDir + getPDBName(project['name'], suffix) + '.pdb</ProgramDataBaseFileName>\n') f.write(' <Optimization>' + getOptimization(cflags) + '</Optimization>\n') f.write(' <ExceptionHandling>' + getUseExceptions(cflags) + '</ExceptionHandling>\n') f.write(' <RuntimeTypeInfo>' + getUseRTTI(cflags) + '</RuntimeTypeInfo>\n') f.write(' <FloatingPointModel>' + getFloatingPointModel(cflags) + '</FloatingPointModel>\n') if 'omit-frame-pointers' in cflags: f.write(' <OmitFramePointers>true</OmitFramePointers>\n') f.write(' <RuntimeLibrary>' + getRuntimeLibrary(make, cfg) + '</RuntimeLibrary>\n') f.write(' <MultiProcessorCompilation>' + getMultiProcessorCompilation(cflags) + '</MultiProcessorCompilation>\n') f.write(' <MinimalRebuild>' + getMinimalRebuild(cflags) + '</MinimalRebuild>\n') additionalClOptions = getAdditionalClOptions(make, cfg) if additionalClOptions != None: f.write(' <AdditionalOptions>' + additionalClOptions + ' %(AdditionalOptions)</AdditionalOptions>\n') align_dict = {'struct-member-align-1': 1, 'struct-member-align-2': 2, 'struct-member-align-4': 4, 'struct-member-align-8': 8, 'struct-member-align-16': 16} for key in align_dict.keys(): if key in cflags: f.write(' <StructMemberAlignment>' + str(align_dict[key]) + 'Bytes</StructMemberAlignment>\n') break if 'x64' not in ctx['arch'] and 'use-sse2' in cflags: f.write(' <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\n') outputPrecompiledHeaderTags(f, make, cfg) f.write(' </ClCompile>\n') f.write(' <Link>\n') f.write(' <SubSystem>' + getSubSystem(make, cfg) + '</SubSystem>\n') f.write(' <AdditionalDependencies>' + getAdditionalDependencies(make, cfg, projects) + '</AdditionalDependencies>\n') f.write(' <AdditionalLibraryDirectories>' + getAdditionalLibraryDirectories(make, cfg, output_path) +'</AdditionalLibraryDirectories>\n') f.write(' <GenerateDebugInformation>' + ('True' if ('debug' in cfg['cflags'] or 'debug-info' in cfg['cflags']) else 'False') + '</GenerateDebugInformation>\n') ModuleDefFile = getModuleDefinitionFile(make, cfg); if (ModuleDefFile != None): f.write(' <ModuleDefinitionFile>' + ModuleDefFile + '</ModuleDefinitionFile>\n') additionalLinkOptions = getAdditionalLinkOptions(make, cfg) if additionalLinkOptions != None: f.write(' <AdditionalOptions>' + additionalLinkOptions + ' %(AdditionalOptions)</AdditionalOptions>\n') UACExecutionLevel = getUACExecutionLevel(make, cfg) if UACExecutionLevel != None: f.write(' <UACExecutionLevel>' + UACExecutionLevel + '</UACExecutionLevel>\n') outputAdditionalLinkTags(f, make, cfg) f.write(' </Link>\n') f.write(' <Lib>\n') additionalLibDependencies = getAdditionalLibDependencies(make, cfg) if additionalLibDependencies != None: f.write(' <AdditionalDependencies>' + additionalLibDependencies + '</AdditionalDependencies>\n') LibTargetMachine = getLibTargetMachine(make, cfg) if LibTargetMachine != None: f.write(' <TargetMachine>' + LibTargetMachine + '</TargetMachine>\n') f.write(' </Lib>\n') PreBuildEventCommand = getPreBuildEventCommand(make, cfg) PreBuildEventMessage = getPreBuildEventMessage(make, cfg) if (PreBuildEventCommand != None): f.write(' <PreBuildEvent>\n') f.write(' <Command>' + PreBuildEventCommand + '</Command>\n') if (PreBuildEventMessage != None): f.write(' <Message>' + PreBuildEventMessage + '</Message>\n') f.write(' </PreBuildEvent>\n') PreLinkEventCommand = getPreLinkEventCommand(make, cfg) PreLinkEventMessage = getPreLinkEventMessage(make, cfg) if (PreLinkEventCommand != None): f.write(' <PreLinkEvent>\n') f.write(' <Command>' + PreLinkEventCommand + '</Command>\n') if (PreLinkEventMessage != None): f.write(' <Message>' + PreLinkEventMessage + '</Message>\n') f.write(' </PreLinkEvent>\n') PostBuildEventCommand = getPostBuildEventCommand(make, cfg) PostBuildEventMessage = getPostBuildEventMessage(make, cfg) if (PostBuildEventCommand != None): f.write(' <PostBuildEvent>\n') f.write(' <Command>' + PostBuildEventCommand + '</Command>\n') if (PostBuildEventMessage != None): f.write(' <Message>' + PostBuildEventMessage + '</Message>\n') f.write(' </PostBuildEvent>\n') f.write(' </ItemDefinitionGroup>\n') # source files project['files'] = [] for cfg in project['configurations']: # grab across all configurations cfg['files'] = make.get('files', cfg['ctx']) if cfg['files']: cfg['files'] = [getSolutionFileName(file, output_path) for file in cfg['files']] project['files'].extend(cfg['files']) project['files'] = list(set(project['files'])) project['files'] = [{'name': file, 'skip_cfg': [], 'bigobj_cfg': [], 'nopch_cfg': []} for file in project['files']] if len(project['files']) == 0: api.warning("No files added to project '" + project['name'] + "' in context " + str(project_ctx), 1) # skipped configurations per file def getProjectFile(name): for file in project['files']: if file['name'] == name: return file return None for cfg in project['configurations']: skips = make.get('skip_files', cfg['ctx']) if skips: for skip in skips: file = getProjectFile(getSolutionFileName(skip, output_path)) if file: file['skip_cfg'].append(cfg) for file in project['files']: for cfg in project['configurations']: if file['name'] not in cfg['files']: file['skip_cfg'].append(cfg) # PCH creation per configuration for cfg in project['configurations']: create_pch = make.get('create_pch', cfg['ctx']) cfg['create_pch'] = api.getRelativePath(create_pch[0], output_path, 'windows') if create_pch != None else '' # big obj per file for cfg in project['configurations']: nopchs = make.get('big_obj', cfg['ctx']) if nopchs: for nopch in nopchs: file = getProjectFile(getSolutionFileName(nopch, output_path)) if file: file['bigobj_cfg'].append(cfg) for file in project['files']: for cfg in project['configurations']: if file['name'] not in cfg['files']: file['bigobj_cfg'].append(cfg) # no pch per file for cfg in project['configurations']: nopchs = make.get('no_pch', cfg['ctx']) if nopchs: for nopch in nopchs: file = getProjectFile(getSolutionFileName(nopch, output_path)) if file: file['nopch_cfg'].append(cfg) for file in project['files']: for cfg in project['configurations']: if file['name'] not in cfg['files']: file['nopch_cfg'].append(cfg) # distribute over file categories distributeProjectFiles(make, project, output_path) # output include files f.write(' <ItemGroup>\n') for file in project['include_files']: openIncludeFileClDirective(f, project, file, output_path) outputIncludeFileClDirective(f, make, project, file, output_path) closeIncludeFileClDirective(f, project, file, output_path) f.write(' </ItemGroup>\n') # output compilation units f.write(' <ItemGroup>\n') for file in project['source_files']: openCompileFileClDirective(f, project, file, output_path) outputCompileFileClDirective(f, make, project, file, output_path) outputPCHDirective(f, project, file) outputBigObjDirective(f, project, file) outputNoPchDirective(f, file) outputExcludeFileFromBuildDirective(f, file) closeCompileFileClDirective(f, project, file, output_path) f.write(' </ItemGroup>\n') # output resource compilation f.write(' <ItemGroup>\n') for file in project['resource_files']: f.write(' <ResourceCompile Include=\"' + file['name'] + '\" />\n') f.write(' </ItemGroup>\n') # output custom units f.write(' <ItemGroup>\n') for file in project['custom_files']: openCustomFileClDirective(f, project, file, output_path) outputCustomFileClDirective(f, make, project, file, output_path) outputPCHDirective(f, project, file) outputBigObjDirective(f, project, file) outputNoPchDirective(f, file) outputExcludeFileFromBuildDirective(f, file) closeCustomFileClDirective(f, project, file, output_path) f.write(' </ItemGroup>\n') # project dependencies common_links = copy.deepcopy(project['all_link']) # links common to all configurations for cfg in project['configurations']: if cfg['links'] != None: common_links = [link for link in common_links if link in cfg['links']] for cfg in project['configurations']: # links specific to this configuration if cfg['links'] != None: cfg['cfg_links'] = [link for link in cfg['links'] if link not in common_links] if common_links and len(common_links) > 0: f.write(' <ItemGroup>\n') for link in common_links: prj = getProject(projects, link) if prj != None: f.write(' <ProjectReference Include="' + prj['name'] +'.vcxproj">\n') f.write(' <Project>{' + prj['guid'] +'}</Project>\n') f.write(' </ProjectReference>\n') f.write(' </ItemGroup>\n') for cfg in project['configurations']: if 'cfg_links' in cfg and len(cfg['cfg_links']) > 0: f.write(' <ItemGroup ' + getCondition(cfg) + '>\n') for link in cfg['cfg_links']: prj = getProject(projects, link) if prj != None: f.write(' <ProjectReference Include="' + prj['name'] +'.vcxproj">\n') f.write(' <Project>{' + prj['guid'] +'}</Project>\n') f.write(' </ProjectReference>\n') f.write(' </ItemGroup>\n') # extensions f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n') f.write(' <ImportGroup Label="ExtensionTargets">\n') f.write(' </ImportGroup>\n') f.write(' <ProjectExtensions>\n') outputProjectExtensionTag(f, make, project) f.write(' </ProjectExtensions>\n') # project done, next! f.write('</Project>\n')
def getSolutionFileName(file, output_path): return api.getRelativePath(file, output_path, 'windows')