예제 #1
0
// ExtractIntellisenseOptions
//------------------------------------------------------------------------------
/*static*/ void ProjectGeneratorBase::ExtractIntellisenseOptions( const AString & compilerArgs,
                                                                  const char * option,
                                                                  const char * alternateOption,
                                                                  Array< AString > & outOptions,
                                                                  bool escapeQuotes )
{
    ASSERT( option );
    Array< AString > tokens;
    compilerArgs.Tokenize( tokens );

    const size_t optionLen = AString::StrLen( option );
    const size_t alternateOptionLen = alternateOption ? AString::StrLen( alternateOption ) : 0;

    for ( size_t i=0; i<tokens.GetSize(); ++i )
    {
        AString & token = tokens[ i ];

        // strip quotes around token, e.g:    "-IFolder/Folder"
        if ( token.BeginsWith( '"' ) && token.EndsWith( '"' ) )
        {
            token.Assign( token.Get() + 1, token.GetEnd() - 1 );
        }

        AStackString<> optionBody;

        // Handle space between option and payload
        if ( ( token == option ) || ( token == alternateOption ) )
        {
            // Handle an incomplete token at the end of list
            if ( i == ( tokens.GetSize() - 1 ) )
            {
                break;
            }

            // Use next token
            optionBody = tokens[ i + 1 ];
        }
        else if ( token.BeginsWith( option ) )
        {
            // use everything after token
            optionBody.Assign( token.Get() + optionLen );
        }
        else if ( alternateOption && token.BeginsWith( alternateOption ) )
        {
            // use everything after token
            optionBody.Assign( token.Get() + alternateOptionLen );
        }

        // Strip quotes around body (e.g. -I"Folder/Folder")
        if ( optionBody.BeginsWith( '"' ) && optionBody.EndsWith( '"' ) )
        {
            optionBody.Trim( 1, 1 );
        }

        // Did we find something?
        if ( optionBody.IsEmpty() == false )
        {
            if ( escapeQuotes )
            {
                optionBody.Replace( "\"", "\\\"" );
            }
            outOptions.Append( optionBody );
        }
    }
}
예제 #2
0
// GetPrecompiledHeaderNode
//------------------------------------------------------------------------------
bool FunctionObjectList::GetPrecompiledHeaderNode( NodeGraph & nodeGraph,
                                                   const BFFIterator & iter,
                                                   CompilerNode * compilerNode,
                                                   const BFFVariable * compilerOptions,
                                                   const Dependencies & compilerForceUsing,
                                                   ObjectNode * & precompiledHeaderNode,
                                                   bool deoptimizeWritableFiles,
                                                   bool deoptimizeWritableFilesWithToken,
                                                   bool allowDistribution,
                                                   bool allowCaching,
                                                   const AString& compilerOutputExtension ) const
{
    const BFFVariable * pchInputFile = nullptr;
    const BFFVariable * pchOutputFile = nullptr;
    const BFFVariable * pchOptions = nullptr;
    if ( !GetString( iter, pchInputFile, ".PCHInputFile" ) ||
         !GetString( iter, pchOutputFile, ".PCHOutputFile" ) ||
         !GetString( iter, pchOptions, ".PCHOptions" ) )
    {
        return false;
    }

    precompiledHeaderNode = nullptr;

    AStackString<> pchObjectName;

    if ( pchInputFile )
    {
        if ( !pchOutputFile || !pchOptions )
        {
            Error::Error_1300_MissingPCHArgs( iter, this );
            return false;
        }

        Node * pchInputNode = nodeGraph.FindNode( pchInputFile->GetString() );
        if ( pchInputNode )
        {
            // is it a file?
            if ( pchInputNode->IsAFile() == false )
            {
                Error::Error_1103_NotAFile( iter, this, "PCHInputFile", pchInputNode->GetName(), pchInputNode->GetType() );
                return false;
            }
        }
        else
        {
            // Create input node
            pchInputNode = nodeGraph.CreateFileNode( pchInputFile->GetString() );
        }

        if ( nodeGraph.FindNode( pchOutputFile->GetString() ) )
        {
            Error::Error_1301_AlreadyDefinedPCH( iter, this, pchOutputFile->GetString().Get() );
            return false;
        }

        uint32_t pchFlags = ObjectNode::DetermineFlags( compilerNode, pchOptions->GetString(), true, false );
        if ( pchFlags & ObjectNode::FLAG_MSVC )
        {
            // sanity check arguments
            bool foundYcInPCHOptions = false;
            bool foundFpInPCHOptions = false;

            // Find /Fo option to obtain pch object file name
            Array< AString > pchTokens;
            pchOptions->GetString().Tokenize( pchTokens );
            for ( const AString & token : pchTokens )
            {
                if ( ObjectNode::IsStartOfCompilerArg_MSVC( token, "Fo" ) )
                {
                    // Extract filename (and remove quotes if found)
                    pchObjectName = token.Get() + 3;
                    pchObjectName.Trim( pchObjectName.BeginsWith( '"' ) ? 1 : 0, pchObjectName.EndsWith( '"' ) ? 1 : 0 );

                    // Auto-generate name?
                    if ( pchObjectName == "%3" )
                    {
                        // example 'PrecompiledHeader.pch' to 'PrecompiledHeader.pch.obj'
                        pchObjectName = pchOutputFile->GetString();
                        pchObjectName += compilerOutputExtension;
                    }
                }
                else if ( ObjectNode::IsStartOfCompilerArg_MSVC( token, "Yc" ) )
                {
                    foundYcInPCHOptions = true;
                }
                else if ( ObjectNode::IsStartOfCompilerArg_MSVC( token, "Fp" ) )
                {
                    foundFpInPCHOptions = true;
                }
            }

            // PCH must have "Create PCH" (e.g. /Yc"PrecompiledHeader.h")
            if ( foundYcInPCHOptions == false )
            {
                Error::Error_1302_MissingPCHCompilerOption( iter, this, "Yc", "PCHOptions" );
                return false;
            }
            // PCH must have "Precompiled Header to Use" (e.g. /Fp"PrecompiledHeader.pch")
            if ( foundFpInPCHOptions == false )
            {
                Error::Error_1302_MissingPCHCompilerOption( iter, this, "Fp", "PCHOptions" );
                return false;
            }
            // PCH must have object output option (e.g. /Fo"PrecompiledHeader.obj")
            if ( pchObjectName.IsEmpty() )
            {
                Error::Error_1302_MissingPCHCompilerOption( iter, this, "Fo", "PCHOptions" );
                return false;
            }

            // Check Compiler Options
            bool foundYuInCompilerOptions = false;
            bool foundFpInCompilerOptions = false;
            Array< AString > compilerTokens;
            compilerOptions->GetString().Tokenize( compilerTokens );
            for ( const AString & token : compilerTokens )
            {
                if ( ObjectNode::IsStartOfCompilerArg_MSVC( token, "Yu" ) )
                {
                    foundYuInCompilerOptions = true;
                }
                else if ( ObjectNode::IsStartOfCompilerArg_MSVC( token, "Fp" ) )
                {
                    foundFpInCompilerOptions = true;
                }
            }

            // Object using the PCH must have "Use PCH" option (e.g. /Yu"PrecompiledHeader.h")
            if ( foundYuInCompilerOptions == false )
            {
                Error::Error_1302_MissingPCHCompilerOption( iter, this, "Yu", "CompilerOptions" );
                return false;
            }
            // Object using the PCH must have "Precompiled header to use" (e.g. /Fp"PrecompiledHeader.pch")
            if ( foundFpInCompilerOptions == false )
            {
                Error::Error_1302_MissingPCHCompilerOption( iter, this, "Fp", "CompilerOptions" );
                return false;
            }
        }

        precompiledHeaderNode = nodeGraph.CreateObjectNode( pchOutputFile->GetString(),
                                                     pchInputNode,
                                                     compilerNode,
                                                     pchOptions->GetString(),
                                                     AString::GetEmpty(),
                                                     nullptr,
                                                     pchFlags,
                                                     compilerForceUsing,
                                                     deoptimizeWritableFiles,
                                                     deoptimizeWritableFilesWithToken,
                                                     allowDistribution,
                                                     allowCaching,
                                                     nullptr, AString::GetEmpty(), 0 ); // preprocessor args not supported
        precompiledHeaderNode->m_PCHObjectFileName = pchObjectName;
    }

    return true;
}