Пример #1
0
// GetImportLibName
//------------------------------------------------------------------------------
void LinkerNode::GetImportLibName( const AString & args, AString & importLibName ) const
{
    // split to individual tokens
    Array< AString > tokens;
    args.Tokenize( tokens );

    const AString * const end = tokens.End();
    for ( const AString * it = tokens.Begin(); it != end; ++it )
    {
        if ( LinkerNode::IsStartOfLinkerArg_MSVC( *it, "IMPLIB:" ) )
        {
            const char * impStart = it->Get() + 8;
            const char * impEnd = it->GetEnd();

            // if token is exactly /IMPLIB: then value is next token
            if ( impStart == impEnd )
            {
                ++it;
                // handle missing next value
                if ( it == end )
                {
                    return; // we just pretend it doesn't exist and let the linker complain
                }

                impStart = it->Get();
                impEnd = it->GetEnd();
            }

            Args::StripQuotes( impStart, impEnd, importLibName );
        }
    }
}
Пример #2
0
// GetExtraOutputPaths
//------------------------------------------------------------------------------
void FunctionObjectList::GetExtraOutputPaths( const AString & args, AString & pdbPath, AString & asmPath ) const
{
    // split to individual tokens
    Array< AString > tokens;
    args.Tokenize( tokens );

    const AString * const end = tokens.End();
    for ( const AString * it = tokens.Begin(); it != end; ++it )
    {
        if ( ObjectNode::IsStartOfCompilerArg_MSVC( *it, "Fd" ) )
        {
            GetExtraOutputPath( it, end, "Fd", pdbPath );
            continue;
        }

        if ( ObjectNode::IsStartOfCompilerArg_MSVC( *it, "Fa" ) )
        {
            GetExtraOutputPath( it, end, "Fa", asmPath );
            continue;
        }
    }
}
Пример #3
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 );
        }
    }
}
Пример #4
0
// GetOtherLibraries
//------------------------------------------------------------------------------
bool LinkerNode::GetOtherLibraries( NodeGraph & nodeGraph,
                                    const BFFIterator & iter,
                                    const Function * function,
                                    const AString & args,
                                    Dependencies & otherLibraries,
                                    bool msvc ) const
{
    // split to individual tokens
    Array< AString > tokens;
    args.Tokenize( tokens );

    bool ignoreAllDefaultLibs = false;
    Array< AString > defaultLibsToIgnore( 8, true );
    Array< AString > defaultLibs( 16, true );
    Array< AString > libs( 16, true );
    Array< AString > dashlLibs( 16, true );
    Array< AString > libPaths( 16, true );
    Array< AString > envLibPaths( 32, true );

    // extract lib path from system if present
    AStackString< 1024 > libVar;
    if ( Env::GetEnvVariable( "LIB", libVar ) )
    {
        libVar.Tokenize( envLibPaths, ';' );
    }

    const AString * const end = tokens.End();
    for ( const AString * it = tokens.Begin(); it != end; ++it )
    {
        const AString & token = *it;

        // MSVC style
        if ( msvc )
        {
            // /NODEFAULTLIB
            if ( LinkerNode::IsLinkerArg_MSVC( token, "NODEFAULTLIB" ) )
            {
                ignoreAllDefaultLibs = true;
                continue;
            }

            // /NODEFAULTLIB:
            if ( GetOtherLibsArg( "NODEFAULTLIB:", defaultLibsToIgnore, it, end, false, msvc ) )
            {
                continue;
            }

            // /DEFAULTLIB:
            if ( GetOtherLibsArg( "DEFAULTLIB:", defaultLibs, it, end, false, msvc ) )
            {
                continue;
            }

            // /LIBPATH:
            if ( GetOtherLibsArg( "LIBPATH:", libPaths, it, end, true, msvc ) ) // true = canonicalize path
            {
                continue;
            }

            // some other linker argument?
            if ( token.BeginsWith( '/' ) || token.BeginsWith( '-' ) )
            {
                continue;
            }
        }

        // GCC/SNC style
        if ( !msvc )
        {
            // We don't need to check for this, as there is no default lib passing on
            // the cmd line.
            // -nodefaultlibs
            //if ( token == "-nodefaultlibs" )
            //{
            //  ignoreAllDefaultLibs = true;
            //  continue;
            //}

            // -L (lib path)
            if ( GetOtherLibsArg( "L", libPaths, it, end, false, msvc ) )
            {
                continue;
            }

            // -l (lib)
            if ( GetOtherLibsArg( "l", dashlLibs, it, end, false, msvc ) )
            {
                continue;
            }

            // some other linker argument?
            if ( token.BeginsWith( '-' ) )
            {
                continue;
            }
        }

        // build time substitution?
        if ( token.BeginsWith( '%' ) ||     // %1
             token.BeginsWith( "'%" ) ||    // '%1'
             token.BeginsWith( "\"%" ) )    // "%1"
        {
            continue;
        }

        // anything left is an input to the linker
        AStackString<> libName;
        Args::StripQuotes( token.Get(), token.GetEnd(), libName );
        if ( token.IsEmpty() == false )
        {
            libs.Append( libName );
        }
    }

    // filter default libs
    if ( ignoreAllDefaultLibs )
    {
        // filter all default libs
        defaultLibs.Clear();
    }
    else
    {
        // filter specifically listed default libs
        const AString * const endI = defaultLibsToIgnore.End();
        for ( const AString * itI = defaultLibsToIgnore.Begin(); itI != endI; ++itI )
        {
            const AString * const endD = defaultLibs.End();
            for ( AString * itD = defaultLibs.Begin(); itD != endD; ++itD )
            {
                if ( itI->CompareI( *itD ) == 0 )
                {
                    defaultLibs.Erase( itD );
                    break;
                }
            }
        }
    }

    if ( !msvc )
    {
        // convert -l<name> style libs to lib<name>.a
        const AString * const endDL = dashlLibs.End();
        for ( const AString * itDL = dashlLibs.Begin(); itDL != endDL; ++itDL )
        {
            AStackString<> libName;
            libName += "lib";
            libName += *itDL;
            libName += ".a";
            libs.Append( libName );
        }
    }

    // any remaining default libs are treated the same as libs
    libs.Append( defaultLibs );

    // use Environment libpaths if found (but used after LIBPATH provided ones)
    libPaths.Append( envLibPaths );

    // convert libs to nodes
    const AString * const endL = libs.End();
    for ( const AString * itL = libs.Begin(); itL != endL; ++itL )
    {
        bool found = false;

        // is the file a full path?
        if ( ( itL->GetLength() > 2 ) && ( (*itL)[ 1 ] == ':' ) )
        {
            // check file exists in current location
            if ( !GetOtherLibrary( nodeGraph, iter, function, otherLibraries, AString::GetEmpty(), *itL, found ) )
            {
                return false; // GetOtherLibrary will have emitted error
            }
        }
        else
        {
            // check each libpath
            const AString * const endP = libPaths.End();
            for ( const AString * itP = libPaths.Begin(); itP != endP; ++itP )
            {
                if ( !GetOtherLibrary( nodeGraph, iter, function, otherLibraries, *itP, *itL, found ) )
                {
                    return false; // GetOtherLibrary will have emitted error
                }

                if ( found )
                {
                    break;
                }

                // keep searching lib paths...
            }
        }

        // file does not exist on disk, and there is no rule to build it
        // Don't complain about this, because:
        //  a) We may be parsing rules on another OS (i.e. parsing Linux rules on Windows)
        //  b) User may have filtered some libs for platforms they don't care about (i.e. libs
        //     for PS4 on a PC developer's machine on a cross-platform team)
        // If the file is actually needed, the linker will emit an error during link-time.
    }

    return true;
}
Пример #5
0
// DetermineFlags
//------------------------------------------------------------------------------
/*static*/ uint32_t LinkerNode::DetermineFlags( const AString & linkerType, const AString & linkerName, const AString & args )
{
    uint32_t flags = DetermineLinkerTypeFlags( linkerType, linkerName );

    if ( flags & LINK_FLAG_MSVC )
    {
        // Parse args for some other flags
        Array< AString > tokens;
        args.Tokenize( tokens );

        bool debugFlag = false;
        bool incrementalFlag = false;
        bool incrementalNoFlag = false;
        bool optREFFlag = false;
        bool optICFFlag = false;
        bool optLBRFlag = false;
        bool orderFlag = false;

        const AString * const end = tokens.End();
        for ( const AString * it=tokens.Begin(); it!=end; ++it )
        {
            const AString & token = *it;
            if ( IsLinkerArg_MSVC( token, "DLL" ) )
            {
                flags |= LinkerNode::LINK_FLAG_DLL;
                continue;
            }

            if ( IsLinkerArg_MSVC( token, "DEBUG" ) )
            {
                debugFlag = true;
                continue;
            }

            if ( IsLinkerArg_MSVC( token, "INCREMENTAL" ) )
            {
                incrementalFlag = true;
                continue;
            }

            if ( IsLinkerArg_MSVC( token, "INCREMENTAL:NO" ) )
            {
                incrementalNoFlag = true;
                continue;
            }

            if ( IsLinkerArg_MSVC( token, "WX" ) )
            {
                flags |= LinkerNode::LINK_FLAG_WARNINGS_AS_ERRORS_MSVC;
                continue;
            }

            if ( IsStartOfLinkerArg_MSVC( token, "OPT" ) )
            {
                if ( token.FindI( "REF" ) )
                {
                    optREFFlag = true;
                }

                if ( token.FindI( "ICF" ) )
                {
                    optICFFlag = true;
                }

                if ( token.FindI( "LBR" ) )
                {
                    optLBRFlag = true;
                }

                continue;
            }

            if ( IsStartOfLinkerArg_MSVC( token, "ORDER" ) )
            {
                orderFlag = true;
                continue;
            }
        }

        // Determine incremental linking status
        bool usingIncrementalLinking = false; // false by default

        // these options enable incremental linking
        if ( debugFlag || incrementalFlag )
        {
            usingIncrementalLinking = true;
        }

        // these options disable incremental linking
        if ( incrementalNoFlag || optREFFlag || optICFFlag || optLBRFlag || orderFlag )
        {
            usingIncrementalLinking = false;
        }

        if ( usingIncrementalLinking )
        {
            flags |= LINK_FLAG_INCREMENTAL;
        }
    }
    else
    {
        // Parse args for some other flags
        Array< AString > tokens;
        args.Tokenize( tokens );

        const AString * const end = tokens.End();
        for ( const AString * it=tokens.Begin(); it!=end; ++it )
        {
            const AString & token = *it;
            if ( ( token == "-shared" ) || ( token == "-dynamiclib" ) || ( token == "--oformat=prx" ) )
            {
                flags |= LinkerNode::LINK_FLAG_DLL;
                continue;
            }
        }
    }

    return flags;
}