Extract WINE resources at compile-time
svn path=/branches/xmlbuildsystem/; revision=15280
|
@ -229,6 +229,7 @@ include tools/tools.mak
|
|||
-include makefile.auto
|
||||
|
||||
PREAUTO := \
|
||||
$(BIN2RES_TARGET) \
|
||||
$(BUILDNO_H) \
|
||||
$(BUGCODES_H) \
|
||||
$(BUGCODES_RC) \
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
<define name="DBG" value="1" />
|
||||
<property name="DBG_OR_KDBG" value="true" />
|
||||
</if>
|
||||
<if property="DBG" value="0">
|
||||
<compilerflag>-O2</compilerflag>
|
||||
<compilerflag>-Wno-strict-aliasing</compilerflag>
|
||||
<compilerflag>-ftracer</compilerflag>
|
||||
<compilerflag>-momit-leaf-frame-pointer</compilerflag>
|
||||
<compilerflag>-mpreferred-stack-boundary=2</compilerflag>
|
||||
</if>
|
||||
<if property="KDBG" value="1">
|
||||
<define name="KDBG" value="1" />
|
||||
<property name="DBG_OR_KDBG" value="true" />
|
||||
|
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 742 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 766 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 766 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 21 KiB |
|
@ -35,14 +35,25 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#define DIR_SEPARATOR "\\"
|
||||
#else
|
||||
#define DIR_SEPARATOR "/"
|
||||
#endif
|
||||
|
||||
extern int mkstemps(char *template, int suffix_len);
|
||||
|
||||
int process_resources(const char* input_file_name, const char* specific_file_name,
|
||||
const char* relative_path,
|
||||
int inserting, int force_processing, int verbose);
|
||||
|
||||
static const char* help =
|
||||
"Usage: bin2res [OPTIONS] <rsrc.rc>\n"
|
||||
" -a archive binaries into the <rsrc.rc> file\n"
|
||||
" -x extract binaries from the <rsrc.rc> file\n"
|
||||
" -i <filename> archive the named file into the <rsrc.rc> file\n"
|
||||
" -o <filename> extract the named file from the <rsrc.rc> file\n"
|
||||
" -b <path> assume resources are relative to this base path\n"
|
||||
" -f force processing of older resources\n"
|
||||
" -v causes the command to be verbous during processing\n"
|
||||
" -h print this help screen and exit\n"
|
||||
|
@ -127,9 +138,62 @@ const char* parse_marker(const char *line, time_t* last_updated)
|
|||
return res_file_name;
|
||||
}
|
||||
|
||||
int process_resources(const char* input_file_name, const char* specific_file_name,
|
||||
const char* parse_include(const char *line)
|
||||
{
|
||||
static char include_filename[PATH_MAX], *rpos, *wpos;
|
||||
|
||||
if (!(rpos = strstr(line, "#"))) return 0;
|
||||
for (rpos += 1; *rpos && isspace(*rpos); rpos++) /**/;
|
||||
if (!(rpos = strstr(line, "include"))) return 0;
|
||||
for (rpos += 7; *rpos && isspace(*rpos); rpos++) /**/;
|
||||
for (; *rpos && (*rpos == '"' || *rpos == '<'); rpos++) /**/;
|
||||
for (wpos = include_filename; *rpos && !(*rpos == '"' || *rpos == '<'); ) *wpos++ = *rpos++;
|
||||
if (!(rpos = strstr(include_filename, ".rc"))) return 0;
|
||||
*wpos = 0;
|
||||
|
||||
return include_filename;
|
||||
}
|
||||
|
||||
char* get_filename_with_full_path(char* output, const char* filename, const char* relative_path)
|
||||
{
|
||||
if (relative_path != NULL && relative_path[0] != 0)
|
||||
{
|
||||
strcpy(output, relative_path);
|
||||
strcat(output, DIR_SEPARATOR);
|
||||
strcat(output, filename);
|
||||
}
|
||||
else
|
||||
strcpy(output, filename);
|
||||
return output;
|
||||
}
|
||||
|
||||
void process_includes(const char* input_file_name, const char* specific_file_name,
|
||||
const char* relative_path,
|
||||
int inserting, int force_processing, int verbose)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
char buffer[2048];
|
||||
const char *include_file_name;
|
||||
FILE *fin;
|
||||
int c;
|
||||
|
||||
if (!(fin = fopen(input_file_name, "r"))) return;
|
||||
for (c = EOF; fgets(buffer, sizeof(buffer), fin); c = EOF)
|
||||
{
|
||||
if (!(include_file_name = parse_include(buffer))) continue;
|
||||
if ( verbose ) printf ( "Processing included file %s\n", include_file_name);
|
||||
process_resources(get_filename_with_full_path(filename, include_file_name, relative_path),
|
||||
specific_file_name, relative_path,
|
||||
inserting, force_processing, verbose);
|
||||
}
|
||||
fclose(fin);
|
||||
}
|
||||
|
||||
int process_resources(const char* input_file_name, const char* specific_file_name,
|
||||
const char* relative_path,
|
||||
int inserting, int force_processing, int verbose)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
char buffer[2048], tmp_file_name[PATH_MAX];
|
||||
const char *res_file_name;
|
||||
time_t rc_last_update, res_last_update;
|
||||
|
@ -169,7 +233,8 @@ int process_resources(const char* input_file_name, const char* specific_file_nam
|
|||
if (inserting) fputc(c, ftmp);
|
||||
if (c == EOF) break;
|
||||
|
||||
if (!(fres = fopen(res_file_name, inserting ? "rb" : "wb"))) break;
|
||||
if (!(fres = fopen(get_filename_with_full_path(filename, res_file_name, relative_path),
|
||||
inserting ? "rb" : "wb"))) break;
|
||||
if (inserting)
|
||||
{
|
||||
if (!insert_hexdump(ftmp, fres)) break;
|
||||
|
@ -201,6 +266,11 @@ int process_resources(const char* input_file_name, const char* specific_file_nam
|
|||
}
|
||||
else unlink(tmp_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
process_includes(input_file_name, specific_file_name, relative_path,
|
||||
inserting, force_processing, verbose);
|
||||
}
|
||||
|
||||
return c == EOF;
|
||||
}
|
||||
|
@ -211,8 +281,9 @@ int main(int argc, char **argv)
|
|||
int force_overwrite = 0, verbose = 0;
|
||||
const char* input_file_name = 0;
|
||||
const char* specific_file_name = 0;
|
||||
const char* relative_path = 0;
|
||||
|
||||
while((optc = getopt(argc, argv, "axi:o:fhv")) != EOF)
|
||||
while((optc = getopt(argc, argv, "axi:o:b:fhv")) != EOF)
|
||||
{
|
||||
switch(optc)
|
||||
{
|
||||
|
@ -229,6 +300,10 @@ int main(int argc, char **argv)
|
|||
if (convert_dir && convert_dir != optc) usage();
|
||||
convert_dir = optc;
|
||||
break;
|
||||
case 'b':
|
||||
if (relative_path) usage();
|
||||
relative_path = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
force_overwrite = 1;
|
||||
break;
|
||||
|
@ -249,7 +324,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (!convert_dir) usage();
|
||||
|
||||
if (!process_resources(input_file_name, specific_file_name,
|
||||
if (!process_resources(input_file_name, specific_file_name, relative_path,
|
||||
convert_dir == 'a', force_overwrite, verbose))
|
||||
{
|
||||
perror("Processing failed");
|
||||
|
|
|
@ -42,6 +42,9 @@ $(BIN2RES_INT_)mkstemps.o: $(BIN2RES_BASE_)mkstemps.c | $(BIN2RES_INT)
|
|||
$(ECHO_CC)
|
||||
${host_gcc} $(BIN2RES_HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
.PHONY: bin2res
|
||||
bin2res: $(BIN2RES_TARGET)
|
||||
|
||||
.PHONY: bin2res_clean
|
||||
bin2res_clean: $(BIN2RES_TARGET)
|
||||
-@$(rm) $(BIN2RES_TARGET) $(BIN2RES_OBJECTS) 2>$(NUL)
|
||||
|
|
|
@ -131,7 +131,7 @@ Directory::ReplaceVariable ( string name,
|
|||
return path;
|
||||
}
|
||||
|
||||
string
|
||||
/* static */ string
|
||||
Directory::GetEnvironmentVariablePathOrDefault ( const string& name,
|
||||
const string& defaultValue )
|
||||
{
|
||||
|
@ -142,21 +142,21 @@ Directory::GetEnvironmentVariablePathOrDefault ( const string& name,
|
|||
return defaultValue;
|
||||
}
|
||||
|
||||
string
|
||||
/* static */ string
|
||||
Directory::GetIntermediatePath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
|
||||
"obj-i386" );
|
||||
}
|
||||
|
||||
string
|
||||
/* static */ string
|
||||
Directory::GetOutputPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
|
||||
"output-i386" );
|
||||
}
|
||||
|
||||
string
|
||||
/* static */ string
|
||||
Directory::GetInstallPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
|
||||
|
@ -355,6 +355,7 @@ MingwBackend::Process ()
|
|||
GenerateInstallTarget ();
|
||||
GenerateDirectoryTargets ();
|
||||
GenerateDirectories ();
|
||||
UnpackWineResources ();
|
||||
CheckAutomaticDependencies ();
|
||||
CloseMakefile ();
|
||||
}
|
||||
|
@ -637,6 +638,22 @@ MingwBackend::GenerateXmlBuildFilesMacro() const
|
|||
fprintf ( fMakefile, "\n" );
|
||||
}
|
||||
|
||||
string
|
||||
MingwBackend::GetBin2ResExecutable ()
|
||||
{
|
||||
return NormalizeFilename ( Directory::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
|
||||
}
|
||||
|
||||
void
|
||||
MingwBackend::UnpackWineResources ()
|
||||
{
|
||||
printf ( "Unpacking WINE resources..." );
|
||||
WineResource wineResource ( ProjectNode,
|
||||
GetBin2ResExecutable () );
|
||||
wineResource.UnpackResources ( verbose );
|
||||
printf ( "done\n" );
|
||||
}
|
||||
|
||||
void
|
||||
MingwBackend::CheckAutomaticDependencies ()
|
||||
{
|
||||
|
|
|
@ -37,17 +37,17 @@ public:
|
|||
std::string EscapeSpaces ( std::string path );
|
||||
void CreateRule ( FILE* f,
|
||||
const std::string& parent );
|
||||
static std::string GetIntermediatePath ();
|
||||
static std::string GetOutputPath ();
|
||||
static std::string GetInstallPath ();
|
||||
private:
|
||||
bool mkdir_p ( const char* path );
|
||||
std::string ReplaceVariable ( std::string name,
|
||||
std::string value,
|
||||
std::string path );
|
||||
std::string GetEnvironmentVariable ( const std::string& name );
|
||||
std::string GetEnvironmentVariablePathOrDefault ( const std::string& name,
|
||||
static std::string GetEnvironmentVariablePathOrDefault ( const std::string& name,
|
||||
const std::string& defaultValue );
|
||||
std::string GetIntermediatePath ();
|
||||
std::string GetOutputPath ();
|
||||
std::string GetInstallPath ();
|
||||
void ResolveVariablesInPath ( char* buf,
|
||||
std::string path );
|
||||
bool CreateDirectory ( std::string path );
|
||||
|
@ -90,6 +90,8 @@ private:
|
|||
std::string GetBuildToolDependencies () const;
|
||||
void GenerateInitTarget () const;
|
||||
void GenerateXmlBuildFilesMacro() const;
|
||||
std::string GetBin2ResExecutable ();
|
||||
void UnpackWineResources ();
|
||||
void CheckAutomaticDependencies ();
|
||||
bool IncludeDirectoryTarget ( const std::string& directory ) const;
|
||||
bool TryToDetectThisCompiler ( const std::string& compiler );
|
||||
|
|
|
@ -1848,7 +1848,7 @@ MingwModuleHandler::GenerateImportLibraryTargetIfNeeded ()
|
|||
deps[i].c_str () );
|
||||
|
||||
fprintf ( fMakefile, " | %s\n",
|
||||
GetDirectory ( GetTargetFilename ( module, NULL ) ).c_str () );
|
||||
GetDirectory ( GetImportLibraryFilename ( module, NULL ) ).c_str () );
|
||||
|
||||
fprintf ( fMakefile, "\t$(ECHO_DLLTOOL)\n" );
|
||||
|
||||
|
@ -2236,33 +2236,9 @@ MingwWin32DLLModuleHandler::MingwWin32DLLModuleHandler (
|
|||
void
|
||||
MingwWin32DLLModuleHandler::Process ()
|
||||
{
|
||||
GenerateExtractWineDLLResourcesTarget ();
|
||||
GenerateWin32DLLModuleTarget ();
|
||||
}
|
||||
|
||||
void
|
||||
MingwWin32DLLModuleHandler::GenerateExtractWineDLLResourcesTarget ()
|
||||
{
|
||||
fprintf ( fMakefile, ".PHONY: %s_extractresources\n\n",
|
||||
module.name.c_str () );
|
||||
fprintf ( fMakefile, "%s_extractresources: $(BIN2RES_TARGET)\n",
|
||||
module.name.c_str () );
|
||||
const vector<File*>& files = module.non_if_data.files;
|
||||
for ( size_t i = 0; i < files.size (); i++ )
|
||||
{
|
||||
File& file = *files[i];
|
||||
string extension = GetExtension ( file.name );
|
||||
if ( extension == ".rc" || extension == ".RC" )
|
||||
{
|
||||
string resource = NormalizeFilename ( file.name );
|
||||
fprintf ( fMakefile, "\t$(ECHO_BIN2RES)\n" );
|
||||
fprintf ( fMakefile, "\t@:echo ${bin2res} -f -x %s\n",
|
||||
resource.c_str () );
|
||||
}
|
||||
}
|
||||
fprintf ( fMakefile, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ()
|
||||
{
|
||||
|
|
|
@ -291,7 +291,6 @@ public:
|
|||
virtual HostType DefaultHost() { return HostFalse; }
|
||||
virtual void Process ();
|
||||
private:
|
||||
void GenerateExtractWineDLLResourcesTarget ();
|
||||
void GenerateWin32DLLModuleTarget ();
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ class If;
|
|||
class CompilerFlag;
|
||||
class LinkerFlag;
|
||||
class Property;
|
||||
class WineResource;
|
||||
class AutomaticDependency;
|
||||
class Bootstrap;
|
||||
class CDFile;
|
||||
|
@ -421,6 +422,26 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class WineResource
|
||||
{
|
||||
public:
|
||||
const Project& project;
|
||||
std::string bin2res;
|
||||
|
||||
WineResource ( const Project& project,
|
||||
std::string bin2res );
|
||||
~WineResource ();
|
||||
void UnpackResources ( bool verbose );
|
||||
private:
|
||||
bool IsSpecFile ( const File& file );
|
||||
bool IsWineModule ( const Module& module );
|
||||
bool IsResourceFile ( const File& file );
|
||||
std::string GetResourceFilename ( const Module& module );
|
||||
void UnpackResourcesInModule ( Module& module,
|
||||
bool verbose );
|
||||
};
|
||||
|
||||
|
||||
class SourceFile
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -123,6 +123,7 @@ RBUILD_COMMON_SOURCES = \
|
|||
project.cpp \
|
||||
ssprintf.cpp \
|
||||
stubbedcomponent.cpp \
|
||||
wineresource.cpp \
|
||||
XML.cpp \
|
||||
)
|
||||
|
||||
|
@ -261,6 +262,10 @@ $(RBUILD_INT_)stubbedcomponent.o: $(RBUILD_BASE_)stubbedcomponent.cpp $(RBUILD_H
|
|||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)wineresource.o: $(RBUILD_BASE_)wineresource.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)XML.o: $(RBUILD_BASE_)XML.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
@ -335,7 +340,6 @@ $(RBUILD_TESTS_INT_)alltests.o: $(RBUILD_TESTS_BASE_)alltests.cpp $(RBUILD_HEADE
|
|||
|
||||
|
||||
.PHONY: rbuild_test
|
||||
|
||||
rbuild_test: $(RBUILD_TEST_TARGET)
|
||||
$(ECHO_TEST)
|
||||
$(Q)$(RBUILD_TEST_TARGET)
|
||||
|
|
100
reactos/tools/rbuild/wineresource.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include "pch.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "rbuild.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
WineResource::WineResource ( const Project& project,
|
||||
string bin2res )
|
||||
: project ( project ),
|
||||
bin2res ( bin2res )
|
||||
{
|
||||
}
|
||||
|
||||
WineResource::~WineResource ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WineResource::IsSpecFile ( const File& file )
|
||||
{
|
||||
string extension = GetExtension ( file.name );
|
||||
if ( extension == ".spec" || extension == ".SPEC" )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WineResource::IsWineModule ( const Module& module )
|
||||
{
|
||||
const vector<File*>& files = module.non_if_data.files;
|
||||
for ( size_t i = 0; i < files.size (); i++ )
|
||||
{
|
||||
if ( IsSpecFile ( *files[i] ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WineResource::IsResourceFile ( const File& file )
|
||||
{
|
||||
string extension = GetExtension ( file.name );
|
||||
if ( extension == ".rc" || extension == ".RC" )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
string
|
||||
WineResource::GetResourceFilename ( const Module& module )
|
||||
{
|
||||
const vector<File*>& files = module.non_if_data.files;
|
||||
for ( size_t i = 0; i < files.size (); i++ )
|
||||
{
|
||||
if ( IsResourceFile ( *files[i] ) )
|
||||
return files[i]->name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
WineResource::UnpackResources ( bool verbose )
|
||||
{
|
||||
for ( size_t i = 0; i < project.modules.size (); i++ )
|
||||
{
|
||||
if ( IsWineModule ( *project.modules[i] ) )
|
||||
{
|
||||
UnpackResourcesInModule ( *project.modules[i],
|
||||
verbose );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WineResource::UnpackResourcesInModule ( Module& module,
|
||||
bool verbose )
|
||||
{
|
||||
string resourceFilename = GetResourceFilename ( module );
|
||||
if ( resourceFilename.length () == 0 )
|
||||
return;
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
printf ( "Unpacking resources for %s",
|
||||
module.name.c_str () );
|
||||
}
|
||||
|
||||
string outputDirectory = GetDirectory ( module.GetPath () );
|
||||
string parameters = ssprintf ( "-b %s -f -x %s",
|
||||
NormalizeFilename ( outputDirectory ).c_str (),
|
||||
NormalizeFilename ( resourceFilename ).c_str () );
|
||||
string command = bin2res + " " + parameters;
|
||||
int exitcode = system ( command.c_str () );
|
||||
if ( exitcode != 0 )
|
||||
{
|
||||
throw InvocationFailedException ( command,
|
||||
exitcode );
|
||||
}
|
||||
}
|