Exemple #1
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult ExecNode::DoBuild( Job * job )
{
    // If the workingDir is empty, use the current dir for the process
    const char * workingDir = m_WorkingDir.IsEmpty() ? nullptr : m_WorkingDir.Get();

    AStackString<> fullArgs( m_Arguments );
    fullArgs.Replace( "%1", m_SourceFile->GetName().Get() );
    fullArgs.Replace( "%2", GetName().Get() );

    EmitCompilationMessage( fullArgs );

    // spawn the process
    Process p;
    bool spawnOK = p.Spawn( m_Executable->GetName().Get(),
                            fullArgs.Get(),
                            workingDir,
                            FBuild::Get().GetEnvironmentString() );

    if ( !spawnOK )
    {
        FLOG_ERROR( "Failed to spawn process for '%s'", GetName().Get() );
        return NODE_RESULT_FAILED;
    }

    // capture all of the stdout and stderr
    AutoPtr< char > memOut;
    AutoPtr< char > memErr;
    uint32_t memOutSize = 0;
    uint32_t memErrSize = 0;
    p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );

    ASSERT( !p.IsRunning() );
    // Get result
    int result = p.WaitForExit();

    // did the executable fail?
    if ( result != m_ExpectedReturnCode )
    {
        // something went wrong, print details
        Node::DumpOutput( job, memOut.Get(), memOutSize );
        Node::DumpOutput( job, memErr.Get(), memErrSize );

        FLOG_ERROR( "Execution failed (error %i) '%s'", result, GetName().Get() );
        return NODE_RESULT_FAILED;
    }

    // update the file's "last modified" time
    m_Stamp = FileIO::GetFileLastWriteTime( m_Name );
    return NODE_RESULT_OK;
}
Exemple #2
0
	/*static*/ bool ReflectionInfo::WriteDefinitions()
	{
		uint32_t numProblems = 0;

		const ReflectionInfo * ri = s_FirstReflectionInfo;
		for ( ; ri != nullptr; ri = ri->m_Next )
		{
			// ignore abstract classes
			if ( ri->IsAbstract() )
			{
				continue;
			}

			// Serialize a default instance to a MemoryStream 
			MemoryStream ms;
			{
				// Create and serialize default instance
				if ( ri->IsObject() )
				{
					RefObject * object = ri->CreateObject();
					{
						TextWriter tw( ms );
						tw.Write( object );
					}
					FDELETE( object );
				}
				else
				{
					ASSERT( ri->IsStruct() )
					Struct * str = ri->CreateStruct();
					{
						TextWriter tw( ms );
						tw.Write( str, ri );
					}
					FDELETE( str );
				}
			}

			AStackString<> fileName; 
			fileName.Format( "..\\Data\\Reflection\\.Definitions\\%s.definition", ri->GetTypeName() );

			// avoid writing file if not changed

			// Try to open existing file
			FileStream f;
			if ( f.Open( fileName.Get(), FileStream::READ_ONLY ) )
			{
				// read content
				const uint64_t fileSize = f.GetFileSize();
				if ( fileSize == ms.GetSize() )
				{
					AutoPtr< char > mem( (char *)Alloc( (size_t)fileSize ) );
					if ( f.Read( mem.Get(), (size_t)fileSize ) == fileSize )
					{
						if ( memcmp( mem.Get(), ms.GetData(), (size_t)fileSize ) == 0 )
						{
							continue; // definition has not changed
						}
					}
				}
				f.Close();
			}

			// Definition changed - try to save it

			int result = 0;
			AutoPtr< char > memOut;
			AutoPtr< char > memErr;
			uint32_t memOutSize;
			uint32_t memErrSize;

			// existing definition?
			if ( FileIO::FileExists( fileName.Get() ) )
			{
				// existing - need to open for edit?
				if ( FileIO::GetReadOnly( fileName ) )
				{
					AStackString<> args( "edit " );
					args += fileName;
					Process p;
					if ( p.Spawn( "p4", args.Get(), nullptr, nullptr ) )
					{
						p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );
						result = p.WaitForExit();
					}
				}
			}
			else
			{
				// new - open for add
				AStackString<> args( "add " );
				args += fileName;
				Process p;
				if ( p.Spawn( "p4", args.Get(), nullptr, nullptr ) )
				{
					p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );
					result = p.WaitForExit();
				}
			}

			if ( result == 0 )
			{ 
				if ( f.Open( fileName.Get(), FileStream::WRITE_ONLY ) )
				{
					if ( f.Write( ms.GetData(), ms.GetSize() ) == ms.GetSize() )
					{
						continue; // all ok!
					}
				}
			}

			// PROBLEM!
			OUTPUT( "Error writing definition '%s'\n", fileName.Get() );
			if ( result != 0 )
			{
				OUTPUT( "Perforce error: %s\n", memErr.Get() );
			}
			++numProblems;
		}
		if ( numProblems > 0 )
		{
			FATALERROR( "Problem writing %u definition(s).\n", numProblems );
		}
		return ( numProblems == 0 );
	}
Exemple #3
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult TestNode::DoBuild( Job * job )
{
	// If the workingDir is empty, use the current dir for the process
	const char * workingDir = m_TestWorkingDir.IsEmpty() ? nullptr : m_TestWorkingDir.Get();

	EmitCompilationMessage( workingDir );

	// spawn the process
	Process p;
	bool spawnOK = p.Spawn( GetTestExecutable()->GetName().Get(),
							m_TestArguments.Get(),
							workingDir,
							FBuild::Get().GetEnvironmentString() );

	if ( !spawnOK )
	{
		FLOG_ERROR( "Failed to spawn process for '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// capture all of the stdout and stderr
	AutoPtr< char > memOut;
	AutoPtr< char > memErr;
	uint32_t memOutSize = 0;
	uint32_t memErrSize = 0;
	bool timedOut = !p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize, m_TestTimeOut );
	if ( timedOut )
	{
		FLOG_ERROR( "Test timed out after %u ms (%s)", m_TestTimeOut, m_TestExecutable.Get() );
		return NODE_RESULT_FAILED;
	}

	ASSERT( !p.IsRunning() );
	// Get result
	int result = p.WaitForExit();
	if ( result != 0 )
	{
		// something went wrong, print details
		Node::DumpOutput( job, memOut.Get(), memOutSize );
		Node::DumpOutput( job, memErr.Get(), memErrSize );
	}

	// write the test output (saved for pass or fail)
	FileStream fs;
	if ( fs.Open( GetName().Get(), FileStream::WRITE_ONLY ) == false )
	{
		FLOG_ERROR( "Failed to open test output file '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}
	if ( ( memOut.Get() && ( fs.Write( memOut.Get(), memOutSize ) != memOutSize ) ) ||
		 ( memErr.Get() && ( fs.Write( memErr.Get(), memErrSize ) != memErrSize ) ) )
	{
		FLOG_ERROR( "Failed to write test output file '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}
	fs.Close();

	// did the test fail?
	if ( result != 0 )
	{
		FLOG_ERROR( "Test failed (error %i) '%s'", result, GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// test passed 
	// we only keep the "last modified" time of the test output for passed tests
	m_Stamp = FileIO::GetFileLastWriteTime( m_Name );
	return NODE_RESULT_OK;
}
Exemple #4
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult LibraryNode::DoBuild( Job * UNUSED( job ) )
{
	// delete library before creation (so ar.exe will not merge old symbols)
	if ( FileIO::FileExists( GetName().Get() ) )
	{
		FileIO::FileDelete( GetName().Get() );
	}

	// Format compiler args string
	Args fullArgs;
	if ( !BuildArgs( fullArgs ) )
	{
		return NODE_RESULT_FAILED; // BuildArgs will have emitted an error
	}

	// use the exe launch dir as the working dir
	const char * workingDir = nullptr;

	const char * environment = FBuild::Get().GetEnvironmentString();

	EmitCompilationMessage( fullArgs );

	// spawn the process
	Process p;
	bool spawnOK = p.Spawn( m_LibrarianPath.Get(),
							fullArgs.GetFinalArgs().Get(),
							workingDir,
							environment );

	if ( !spawnOK )
	{
		FLOG_ERROR( "Failed to spawn process for Library creation for '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// capture all of the stdout and stderr
	AutoPtr< char > memOut;
	AutoPtr< char > memErr;
	uint32_t memOutSize = 0;
	uint32_t memErrSize = 0;
	p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );

	ASSERT( !p.IsRunning() );
	// Get result
	int result = p.WaitForExit();

	if ( result != 0 )
	{
		if ( memOut.Get() ) { FLOG_ERROR_DIRECT( memOut.Get() ); }
		if ( memErr.Get() ) { FLOG_ERROR_DIRECT( memErr.Get() ); }
	}

	// did the executable fail?
	if ( result != 0 )
	{
		FLOG_ERROR( "Failed to build Library (error %i) '%s'", result, GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// record time stamp for next time
	m_Stamp = FileIO::GetFileLastWriteTime( m_Name );
	ASSERT( m_Stamp );

	return NODE_RESULT_OK;
}
Exemple #5
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult LinkerNode::DoBuild( Job * UNUSED( job ) )
{
    DoPreLinkCleanup();

    // Make sure the implib output directory exists
    if (m_ImportLibName.IsEmpty() == false)
    {
        AStackString<> cleanPath;
        NodeGraph::CleanPath(m_ImportLibName, cleanPath);

        if (EnsurePathExistsForFile(cleanPath) == false)
        {
            // EnsurePathExistsForFile will have emitted error
            return NODE_RESULT_FAILED;
        }
    }

    // Format compiler args string
    Args fullArgs;
    if ( !BuildArgs( fullArgs ) )
    {
        return NODE_RESULT_FAILED; // BuildArgs will have emitted an error
    }

    // use the exe launch dir as the working dir
    const char * workingDir = nullptr;

    const char * environment = FBuild::Get().GetEnvironmentString();

    EmitCompilationMessage( fullArgs );

    // we retry if linker crashes
    uint32_t attempt( 0 );

    for (;;)
    {
        ++attempt;

        // spawn the process
        Process p;
        bool spawnOK = p.Spawn( m_Linker.Get(),
                                fullArgs.GetFinalArgs().Get(),
                                workingDir,
                                environment );

        if ( !spawnOK )
        {
            FLOG_ERROR( "Failed to spawn process '%s' for %s creation for '%s'", m_Linker.Get(), GetDLLOrExe(), GetName().Get() );
            return NODE_RESULT_FAILED;
        }

        // capture all of the stdout and stderr
        AutoPtr< char > memOut;
        AutoPtr< char > memErr;
        uint32_t memOutSize = 0;
        uint32_t memErrSize = 0;
        p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );

        ASSERT( !p.IsRunning() );
        // Get result
        int result = p.WaitForExit();

        // did the executable fail?
        if ( result != 0 )
        {
            // did the linker have an ICE (LNK1000)?
            if ( GetFlag( LINK_FLAG_MSVC ) && ( result == 1000 ) && ( attempt == 1 ) )
            {
                FLOG_WARN( "FBuild: Warning: Linker crashed (LNK1000), retrying '%s'", GetName().Get() );
                continue; // try again
            }

            if ( memOut.Get() )
            {
                m_BuildOutputMessages.Append( memOut.Get(), memOutSize );
                FLOG_ERROR_DIRECT( memOut.Get() );
            }

            if ( memErr.Get() )
            {
                m_BuildOutputMessages.Append( memErr.Get(), memErrSize );
                FLOG_ERROR_DIRECT( memErr.Get() );
            }

            // some other (genuine) linker failure
            FLOG_ERROR( "Failed to build %s (error %i) '%s'", GetDLLOrExe(), result, GetName().Get() );
            return NODE_RESULT_FAILED;
        }
        else
        {
            break; // success!
        }
    }

    // post-link stamp step
    if ( m_LinkerStampExe )
    {
        EmitStampMessage();

        Process stampProcess;
        bool spawnOk = stampProcess.Spawn( m_LinkerStampExe->GetName().Get(),
                                           m_LinkerStampExeArgs.Get(),
                                           nullptr,     // working dir
                                           nullptr );   // env
        if ( spawnOk == false )
        {
            FLOG_ERROR( "Failed to spawn process '%s' for '%s' stamping of '%s'", m_LinkerStampExe->GetName().Get(), GetDLLOrExe(), GetName().Get() );
            return NODE_RESULT_FAILED;
        }

        // capture all of the stdout and stderr
        AutoPtr< char > memOut;
        AutoPtr< char > memErr;
        uint32_t memOutSize = 0;
        uint32_t memErrSize = 0;
        stampProcess.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );
        ASSERT( !stampProcess.IsRunning() );

        // Get result
        int result = stampProcess.WaitForExit();

        // did the executable fail?
        if ( result != 0 )
        {
            if ( memOut.Get() ) { FLOG_ERROR_DIRECT( memOut.Get() ); }
            if ( memErr.Get() ) { FLOG_ERROR_DIRECT( memErr.Get() ); }
            FLOG_ERROR( "Failed to stamp %s '%s' (error %i - '%s')", GetDLLOrExe(), GetName().Get(), result, m_LinkerStampExe->GetName().Get() );
            return NODE_RESULT_FAILED;
        }

        // success!
    }

    // record time stamp for next time
    m_Stamp = FileIO::GetFileLastWriteTime( m_Name );
    ASSERT( m_Stamp );

    return NODE_RESULT_OK;
}
Exemple #6
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult CSNode::DoBuild( Job * job )
{
	// Format compiler args string
	Args fullArgs;
	if ( !BuildArgs( fullArgs ) )
	{
		return NODE_RESULT_FAILED; // BuildArgs will have emitted an error
	}

	// use the exe launch dir as the working dir
	const char * workingDir = nullptr;

	const char * environment = FBuild::Get().GetEnvironmentString();

	EmitCompilationMessage( fullArgs );

	// spawn the process
	Process p;
	if ( p.Spawn( m_CompilerPath.Get(), fullArgs.GetFinalArgs().Get(),
				  workingDir, environment ) == false )
	{
		FLOG_ERROR( "Failed to spawn process to build '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// capture all of the stdout and stderr
	AutoPtr< char > memOut;
	AutoPtr< char > memErr;
	uint32_t memOutSize = 0;
	uint32_t memErrSize = 0;
	p.ReadAllData( memOut, &memOutSize, memErr, &memErrSize );

	// Get result
	ASSERT( !p.IsRunning() );
	int result = p.WaitForExit();
	bool ok = ( result == 0 );

	if ( !ok )
	{
		// something went wrong, print details
		Node::DumpOutput( job, memOut.Get(), memOutSize );
		Node::DumpOutput( job, memErr.Get(), memErrSize );
		goto failed;
	}

	if ( !FileIO::FileExists( m_Name.Get() ) )
	{
		FLOG_ERROR( "Object missing despite success for '%s'", GetName().Get() );
		return NODE_RESULT_FAILED;
	}

	// record new file time
	m_Stamp = FileIO::GetFileLastWriteTime( m_Name );

	return NODE_RESULT_OK;

failed:
	FLOG_ERROR( "Failed to build Object (error %i) '%s'", result, GetName().Get() );

	return NODE_RESULT_FAILED;
}