// Initialize //------------------------------------------------------------------------------ bool XCodeProjectNode::Initialize( NodeGraph & nodeGraph, const BFFIterator & iter, const Function * function ) { ProjectGeneratorBase::FixupAllowedFileExtensions( m_ProjectAllowedFileExtensions ); Dependencies dirNodes( m_ProjectInputPaths.GetSize() ); if ( !function->GetDirectoryListNodeList( nodeGraph, iter, m_ProjectInputPaths, m_ProjectInputPathsExclude, m_ProjectFilesToExclude, true, &m_ProjectAllowedFileExtensions, "ProjectInputPaths", dirNodes ) ) { return false; // GetDirectoryListNodeList will have emitted an error } // TODO:B use m_ProjectFiles instead of finding it again Dependencies fileNodes( m_ProjectFiles.GetSize() ); if ( !function->GetNodeList( nodeGraph, iter, ".ProjectFiles", fileNodes ) ) { return false; // GetNodeList will have emitted an error } ASSERT( m_StaticDependencies.IsEmpty() ); m_StaticDependencies.Append( dirNodes ); m_StaticDependencies.Append( fileNodes ); return true; }
// Commit //------------------------------------------------------------------------------ /*virtual*/ bool FunctionVCXProject::Commit( const BFFIterator & funcStartIter ) const { // required AStackString<> projectOutput; AStackString<> rootNamespace; AStackString<> projectGuid; AStackString<> defaultLanguage; AStackString<> applicationEnvironment; if ( !GetString( funcStartIter, projectOutput, ".ProjectOutput", true ) || !GetString( funcStartIter, rootNamespace, ".RootNamespace", false ) || !GetString( funcStartIter, projectGuid, ".ProjectGuid", false ) || !GetString( funcStartIter, defaultLanguage, ".DefaultLanguage", false ) || !GetString( funcStartIter, applicationEnvironment, ".ApplicationEnvironment", false ) ) { return false; } // optional inputs Array< AString > inputPaths; Array< AString > inputPathsExclude; if ( !GetStrings( funcStartIter, inputPaths, ".ProjectInputPaths", false ) || !GetStrings( funcStartIter, inputPathsExclude, ".ProjectInputPathsExclude", false ) ) { return false; } // project base Array< AString > basePaths; if ( !GetStrings( funcStartIter, basePaths, ".ProjectBasePath", false ) ) { return false; } CleanFolderPaths( basePaths ); // references Array< AString > references; Array< AString > projectReferences; if ( !GetStrings( funcStartIter, references, ".ProjectReferences", false ) || !GetStrings( funcStartIter, projectReferences, ".ProjectProjectReferences", false ) ) { return false; } // permitted file extensions Array< AString > allowedFileExtensions( 8, true ); if ( !GetStrings( funcStartIter, allowedFileExtensions, ".ProjectAllowedFileExtensions", false ) ) { return true; } if ( allowedFileExtensions.IsEmpty() ) { const char * extensions[] = { ".cpp", ".hpp", ".cxx",".hxx",".c",".h",".cc",".hh", ".cp",".hp",".cs",".inl",".bff",".rc",".resx",".m",".mm", ".cu", nullptr }; AStackString<> tmp; const char ** item = extensions; while ( *item ) { tmp.Assign( *item ); allowedFileExtensions.Append( tmp ); ++item; } } // files and filesToExclude Array< AString > files( 8, true ); Array< AString > filesToExclude( 8, true ); if ( !GetStrings( funcStartIter, files, ".ProjectFiles", false ) || !GetStrings( funcStartIter, filesToExclude, ".ProjectFilesToExclude", false ) ) { return false; } // filetypes Array< VSProjectFileType > fileTypes; const BFFVariable * projectFileTypes = BFFStackFrame::GetVar( ".ProjectFileTypes" ); if ( projectFileTypes ) { if ( projectFileTypes->IsArrayOfStructs() == false ) { Error::Error_1050_PropertyMustBeOfType( funcStartIter, this, ".ProjectFileTypes", projectFileTypes->GetType(), BFFVariable::VAR_ARRAY_OF_STRUCTS ); return false; } const Array< const BFFVariable * > & structs = projectFileTypes->GetArrayOfStructs(); const BFFVariable * const * end = structs.End(); for ( const BFFVariable ** it = structs.Begin(); it != end; ++it ) { const BFFVariable * s = *it; VSProjectFileType ft; // .FileType must be provided if ( !GetStringFromStruct( s, ".FileType", ft.m_FileType ) ) { // TODO:B custom error Error::Error_1101_MissingProperty( funcStartIter, this, AStackString<>( ".FileType" ) ); return false; } // .Pattern must be provided if ( !GetStringFromStruct( s, ".Pattern", ft.m_Pattern ) ) { // TODO:B custom error Error::Error_1101_MissingProperty( funcStartIter, this, AStackString<>( ".Pattern" ) ); return false; } fileTypes.Append( ft ); } } // path cleaning CleanFolderPaths( inputPaths ); // input paths CleanFolderPaths( inputPathsExclude ); // exclude paths CleanFilePaths( files ); // explicit files // per-config options VSProjectConfig baseConfig; // various options if ( !GetString( funcStartIter, baseConfig.m_BuildCommand, ".ProjectBuildCommand", false ) || !GetString( funcStartIter, baseConfig.m_RebuildCommand,".ProjectRebuildCommand", false ) || !GetString( funcStartIter, baseConfig.m_CleanCommand, ".ProjectCleanCommand", false ) || !GetString( funcStartIter, baseConfig.m_Output, ".Output", false ) || !GetString( funcStartIter, baseConfig.m_PreprocessorDefinitions, ".PreprocessorDefinitions", false ) || !GetString( funcStartIter, baseConfig.m_IncludeSearchPath, ".IncludeSearchPath", false ) || !GetString( funcStartIter, baseConfig.m_ForcedIncludes, ".ForcedIncludes", false ) || !GetString( funcStartIter, baseConfig.m_AssemblySearchPath, ".AssemblySearchPath", false ) || !GetString( funcStartIter, baseConfig.m_ForcedUsingAssemblies, ".ForcedUsingAssemblies", false ) || !GetString( funcStartIter, baseConfig.m_AdditionalOptions, ".AdditionalOptions", false ) || !GetString( funcStartIter, baseConfig.m_OutputDirectory, ".OutputDirectory", false ) || !GetString( funcStartIter, baseConfig.m_IntermediateDirectory, ".IntermediateDirectory", false ) || !GetString( funcStartIter, baseConfig.m_Xbox360DebuggerCommand,".Xbox360DebuggerCommand", false ) || !GetString( funcStartIter, baseConfig.m_LayoutDir, ".LayoutDir", false ) || !GetString( funcStartIter, baseConfig.m_LayoutExtensionFilter, ".LayoutExtensionFilter", false ) || !GetString( funcStartIter, baseConfig.m_DebuggerFlavor, ".DebuggerFlavor", false ) || !GetString( funcStartIter, baseConfig.m_AumidOverride, ".AumidOverride", false ) || !GetString( funcStartIter, baseConfig.m_PlatformToolset, ".PlatformToolset", false ) || !GetString( funcStartIter, baseConfig.m_DeploymentType, ".DeploymentType", false ) || !GetString( funcStartIter, baseConfig.m_DeploymentFiles, ".DeploymentFiles", false ) || !GetString( funcStartIter, baseConfig.m_LocalDebuggerCommandArguments, ".LocalDebuggerCommandArguments", false ) || !GetString( funcStartIter, baseConfig.m_LocalDebuggerWorkingDirectory, ".LocalDebuggerWorkingDirectory", false ) || !GetString( funcStartIter, baseConfig.m_LocalDebuggerCommand, ".LocalDebuggerCommand", false ) || !GetString( funcStartIter, baseConfig.m_LocalDebuggerEnvironment, ".LocalDebuggerEnvironment", false ) ) { return false; } // create configs Array< VSProjectConfig > configs( 16, true ); const BFFVariable * projectConfigs = BFFStackFrame::GetVar( ".ProjectConfigs" ); if ( projectConfigs ) { if ( projectConfigs->IsArrayOfStructs() == false ) { Error::Error_1050_PropertyMustBeOfType( funcStartIter, this, ".ProjectConfigs", projectConfigs->GetType(), BFFVariable::VAR_ARRAY_OF_STRUCTS ); return false; } const Array< const BFFVariable * > & structs = projectConfigs->GetArrayOfStructs(); const BFFVariable * const * end = structs.End(); for ( const BFFVariable ** it = structs.Begin(); it != end; ++it ) { const BFFVariable * s = *it; // start with the base configuration VSProjectConfig newConfig( baseConfig ); // .Platform must be provided if ( !GetStringFromStruct( s, ".Platform", newConfig.m_Platform ) ) { // TODO:B custom error Error::Error_1101_MissingProperty( funcStartIter, this, AStackString<>( ".Platform" ) ); return false; } // .Config must be provided if ( !GetStringFromStruct( s, ".Config", newConfig.m_Config ) ) { // TODO:B custom error Error::Error_1101_MissingProperty( funcStartIter, this, AStackString<>( ".Config" ) ); return false; } GetStringFromStruct( s, ".ProjectBuildCommand", newConfig.m_BuildCommand ); GetStringFromStruct( s, ".ProjectRebuildCommand", newConfig.m_RebuildCommand ); GetStringFromStruct( s, ".ProjectCleanCommand", newConfig.m_CleanCommand ); GetStringFromStruct( s, ".Output", newConfig.m_Output ); GetStringFromStruct( s, ".PreprocessorDefinitions", newConfig.m_PreprocessorDefinitions ); GetStringFromStruct( s, ".IncludeSearchPath", newConfig.m_IncludeSearchPath ); GetStringFromStruct( s, ".ForcedIncludes", newConfig.m_ForcedIncludes ); GetStringFromStruct( s, ".AssemblySearchPath", newConfig.m_AssemblySearchPath ); GetStringFromStruct( s, ".ForcedUsingAssemblies", newConfig.m_ForcedUsingAssemblies ); GetStringFromStruct( s, ".AdditionalOptions", newConfig.m_AdditionalOptions ); GetStringFromStruct( s, ".OutputDirectory", newConfig.m_OutputDirectory ); GetStringFromStruct( s, ".IntermediateDirectory", newConfig.m_IntermediateDirectory ); GetStringFromStruct( s, ".LayoutDir", newConfig.m_LayoutDir ); GetStringFromStruct( s, ".LayoutExtensionFilter", newConfig.m_LayoutExtensionFilter ); GetStringFromStruct( s, ".Xbox360DebuggerCommand", newConfig.m_Xbox360DebuggerCommand ); GetStringFromStruct( s, ".DebuggerFlavor", newConfig.m_DebuggerFlavor ); GetStringFromStruct( s, ".AumidOverride", newConfig.m_AumidOverride ); GetStringFromStruct( s, ".PlatformToolset", newConfig.m_PlatformToolset ); GetStringFromStruct( s, ".DeploymentType", newConfig.m_DeploymentType ); GetStringFromStruct( s, ".DeploymentFiles", newConfig.m_DeploymentFiles ); GetStringFromStruct( s, ".LocalDebuggerCommandArguments", newConfig.m_LocalDebuggerCommandArguments ); GetStringFromStruct( s, ".LocalDebuggerWorkingDirectory", newConfig.m_LocalDebuggerWorkingDirectory ); GetStringFromStruct( s, ".LocalDebuggerCommand", newConfig.m_LocalDebuggerCommand ); GetStringFromStruct( s, ".LocalDebuggerEnvironment", newConfig.m_LocalDebuggerEnvironment ); configs.Append( newConfig ); } } else { // no user specified configs, make some defaults // start from the default VSProjectConfig config( baseConfig ); // make the configs config.m_Platform = "Win32"; config.m_Config = "Debug"; configs.Append( config ); config.m_Config = "Release"; configs.Append( config ); config.m_Platform = "x64"; configs.Append( config ); config.m_Config = "Debug"; configs.Append( config ); } NodeGraph & ng = FBuild::Get().GetDependencyGraph(); // create all of the DirectoryListNodes we need Dependencies dirNodes( inputPaths.GetSize() ); if ( !GetDirectoryListNodeList( funcStartIter, inputPaths, Array< AString >(), Array< AString >(), true, nullptr, "ProjectInputPaths", dirNodes ) ) { return false; // GetDirectoryListNodeList will have emitted an error } // Check for existing node if ( ng.FindNode( projectOutput ) ) { Error::Error_1100_AlreadyDefined( funcStartIter, this, projectOutput ); return false; } VCXProjectNode * pn = ng.CreateVCXProjectNode( projectOutput, basePaths, dirNodes, inputPathsExclude, // TODO:B Remove this (handled by DirectoryListNode now) allowedFileExtensions, // TODO:B Remove this (handled by DirectoryListNode now) files, filesToExclude, rootNamespace, projectGuid, defaultLanguage, applicationEnvironment, configs, fileTypes, references, projectReferences ); ASSERT( pn ); return ProcessAlias( funcStartIter, pn ); }
// GetInputs //------------------------------------------------------------------------------ bool FunctionObjectList::GetInputs( const BFFIterator & iter, Dependencies & inputs ) const { NodeGraph & ng = FBuild::Get().GetDependencyGraph(); // do we want to build files via a unity blob? Array< AString > inputUnities; if ( !GetStrings( iter, inputUnities, ".CompilerInputUnity", false ) ) // not required { return false; } for ( const auto& unity : inputUnities ) { Node * n = ng.FindNode( unity ); if ( n == nullptr ) { Error::Error_1104_TargetNotDefined( iter, this, "CompilerInputUnity", unity ); return false; } if ( n->GetType() != Node::UNITY_NODE ) { Error::Error_1102_UnexpectedType( iter, this, "CompilerInputUnity", unity, n->GetType(), Node::UNITY_NODE ); return false; } inputs.Append( Dependency( n ) ); } // do we want to build a files in a directory? const BFFVariable * inputPath = BFFStackFrame::GetVar( ".CompilerInputPath" ); if ( inputPath ) { // get the optional pattern and recurse options related to InputPath Array< AString > patterns; if ( !GetStrings( iter, patterns, ".CompilerInputPattern", false ) ) { return false; // GetString will have emitted an error } if ( patterns.IsEmpty() ) { patterns.Append( AStackString<>( "*.cpp" ) ); } // recursive? default to true bool recurse = true; if ( !GetBool( iter, recurse, ".CompilerInputPathRecurse", true, false ) ) { return false; // GetBool will have emitted an error } // Support an exclusion path Array< AString > excludePaths; if ( !GetFolderPaths( iter, excludePaths, ".CompilerInputExcludePath", false ) ) { return false; // GetFolderPaths will have emitted an error } Array< AString > filesToExclude; if ( !GetStrings( iter, filesToExclude, ".CompilerInputExcludedFiles", false ) ) // not required { return false; // GetStrings will have emitted an error } CleanFileNames( filesToExclude ); // Input paths Array< AString > inputPaths; if ( !GetFolderPaths( iter, inputPaths, ".CompilerInputPath", false ) ) { return false; // GetFolderPaths will have emitted an error } Dependencies dirNodes( inputPaths.GetSize() ); if ( !GetDirectoryListNodeList( iter, inputPaths, excludePaths, filesToExclude, recurse, &patterns, "CompilerInputPath", dirNodes ) ) { return false; // GetDirectoryListNodeList will have emitted an error } inputs.Append( dirNodes ); } // do we want to build a specific list of files? if ( !GetNodeList( iter, ".CompilerInputFiles", inputs, false ) ) { // helper will emit error return false; } return true; }
// Commit //------------------------------------------------------------------------------ /*virtual*/ bool FunctionCSAssembly::Commit( NodeGraph & nodeGraph, const BFFIterator & funcStartIter ) const { // make sure all required variables are defined const BFFVariable * compiler; const BFFVariable * compilerOptions; const BFFVariable * compilerOutput; if ( !GetString( funcStartIter, compiler, ".Compiler", true ) || !GetString( funcStartIter, compilerOptions, ".CompilerOptions", true ) || !GetString( funcStartIter, compilerOutput, ".CompilerOutput", true ) ) { return false; } Dependencies staticDeps( 32, true ); // do we want to build a files in a directory? const BFFVariable * inputPath = BFFStackFrame::GetVar( ".CompilerInputPath" ); if ( inputPath ) { // get the optional pattern and recurse options related to InputPath Array< AString > patterns; if ( !GetStrings( funcStartIter, patterns, ".CompilerInputPattern", false ) ) { return false; // GetString will have emitted an error } if ( patterns.IsEmpty() ) { patterns.Append( AStackString<>( "*.cs" ) ); } // recursive? default to true bool recurse = true; if ( !GetBool( funcStartIter, recurse, ".CompilerInputPathRecurse", true, false ) ) { return false; // GetBool will have emitted an error } // Support an exclusion path Array< AString > excludePaths; if ( !GetFolderPaths( funcStartIter, excludePaths, ".CompilerInputExcludePath", false ) ) { return false; // GetFolderPaths will have emitted an error } Array< AString > filesToExclude(0, true); if ( !GetStrings( funcStartIter, filesToExclude, ".CompilerInputExcludedFiles", false ) ) // not required { return false; // GetStrings will have emitted an error } CleanFileNames( filesToExclude ); // Input paths Array< AString > inputPaths; if ( !GetFolderPaths( funcStartIter, inputPaths, ".CompilerInputPath", false ) ) { return false; // GetFolderPaths will have emitted an error } Dependencies dirNodes( inputPaths.GetSize() ); if ( !GetDirectoryListNodeList( nodeGraph, funcStartIter, inputPaths, excludePaths, filesToExclude, recurse, &patterns, "CompilerInputPath", dirNodes ) ) { return false; // GetDirectoryListNodeList will have emitted an error } staticDeps.Append( dirNodes ); } // do we want to build a specific list of files? if ( !GetNodeList( nodeGraph, funcStartIter, ".CompilerInputFiles", staticDeps, false ) ) { // helper will emit error return false; } if ( staticDeps.IsEmpty() ) { Error::Error_1006_NothingToBuild( funcStartIter, this ); return false; } // additional references? Dependencies extraRefs( 0, true ); if ( !GetNodeList( nodeGraph, funcStartIter, ".CompilerReferences", extraRefs, false ) ) { // helper function will have emitted an error return false; } // Pre-build dependencies Dependencies preBuildDependencies; if ( !GetNodeList( nodeGraph, funcStartIter, ".PreBuildDependencies", preBuildDependencies, false ) ) { return false; // GetNodeList will have emitted an error } // Create library node which depends on the single file or list if ( nodeGraph.FindNode( compilerOutput->GetString() ) ) { Error::Error_1100_AlreadyDefined( funcStartIter, this, compilerOutput->GetString() ); return false; } Node * csNode = nodeGraph.CreateCSNode( compilerOutput->GetString(), staticDeps, compiler->GetString(), compilerOptions->GetString(), extraRefs, preBuildDependencies ); // should we create an alias? return ProcessAlias( nodeGraph, funcStartIter, csNode ); }