2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 01:12:13 +00:00

Speed up module imports.

* jam_src/builtins.c: New builtins IMPORT_MODULE and IMPORTED_MODULES.
  jam_src/rules.c: (bindrule): Refactor. (lookup_rule): New function.

* kernel/modules.jam: Make use of IMPORT_MODULE.


[SVN r19422]
This commit is contained in:
Vladimir Prus
2003-08-04 08:45:41 +00:00
parent d5900569b6
commit 262fff312e
20 changed files with 358 additions and 30 deletions

View File

@@ -215,6 +215,18 @@ load_builtins()
bind_builtin( "SEARCH_FOR_TARGET",
builtin_search_for_target, 0, args );
}
{
char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
bind_builtin( "IMPORT_MODULE",
builtin_import_module, 0, args );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "IMPORTED_MODULES",
builtin_imported_modules, 0, args );
}
}
/*
@@ -846,6 +858,47 @@ builtin_search_for_target( PARSE *parse, FRAME *frame )
return list_new( L0, t->name );
}
LIST *builtin_import_module( PARSE *parse, FRAME *frame )
{
LIST* arg1 = lol_get( frame->args, 0 );
LIST* arg2 = lol_get( frame->args, 1 );
module_t* m = arg2 ? bindmodule(arg2->string) : root_module();
for(;arg1; arg1 = arg1->next) {
char* s = arg1->string;
char** ss = &s;
if (!m->imported_modules)
m->imported_modules = hashinit( sizeof(char*), "imported");
hashenter(m->imported_modules, (HASHDATA**)&ss);
}
return L0;
}
static void add_module_name( void* r_, void* result_ )
{
char** r = (char**)r_;
LIST** result = (LIST**)result_;
*result = list_new( *result, copystr( *r ) );
}
LIST *builtin_imported_modules( PARSE *parse, FRAME *frame )
{
LIST *arg0 = lol_get( frame->args, 0 );
LIST *result = L0;
module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
if ( source_module->rules )
hashenumerate( source_module->imported_modules, add_module_name, &result );
return result;
}
static void lol_build( LOL* lol, char** elements )
{
LIST* l = L0;

View File

@@ -33,6 +33,8 @@ LIST *builtin_backtrace( PARSE *parse, FRAME *args );
LIST *builtin_pwd( PARSE *parse, FRAME *args );
LIST *builtin_update( PARSE *parse, FRAME *args );
LIST *builtin_search_for_target( PARSE *parse, FRAME *args );
LIST *builtin_import_module( PARSE *parse, FRAME *args );
LIST *builtin_imported_modules( PARSE *parse, FRAME *frame );
void backtrace( FRAME *frame );

View File

@@ -50,6 +50,7 @@ module_t* bindmodule( char* name )
m->name = newstr( m->name );
m->variables = 0;
m->rules = 0;
m->imported_modules = 0;
}
string_free( &s );
return m;

View File

@@ -11,6 +11,7 @@ struct module_t
char* name;
struct hash* rules;
struct hash* variables;
struct hash* imported_modules;
};
typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */

View File

@@ -705,15 +705,59 @@ RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindli
return local;
}
RULE *bindrule( char *rulename, module_t* m )
/* Looks for a rule in the specified module, and returns it, if found.
First checks if the rule is present in the module's rule table.
Second, if name of the rule is in the form name1.name2 and name1 is in
the list of imported modules, look in module 'name1' for rule 'name2'.
*/
RULE *lookup_rule( char *rulename, module_t *m, int local_only )
{
RULE rule, *r = &rule;
RULE rule, *r = &rule, *result = 0;
module_t* original_module = m;
r->name = rulename;
if ( m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
return r;
else
return enter_rule( rulename, root_module() );
if (m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
result = r;
else if (!local_only && m->imported_modules) {
/* Try splitting the name into module and rule. */
char *p = strchr(r->name, '.') ;
if (p) {
*p = '\0';
/* Now, r->name keeps the module name, and p+1 keeps the rule name. */
if (hashcheck( m->imported_modules, (HASHDATA **)&r))
{
result = lookup_rule(p+1, bindmodule(rulename), 1);
}
*p = '.';
}
}
if (result)
{
if (local_only && !result->exported)
result = 0;
}
return result;
}
RULE *bindrule( char *rulename, module_t* m)
{
RULE *result;
result = lookup_rule(rulename, m, 0);
if (!result)
result = lookup_rule(rulename, root_module(), 0);
/* We've only one caller, 'evaluate_rule', which will complain about
calling underfined rule. We could issue the error
here, but we don't have necessary information, such as frame.
*/
if (!result)
result = enter_rule( rulename, root_module() );
return result;
}
RULE* import_rule( RULE* source, module_t* m, char* name )

View File

@@ -215,6 +215,18 @@ load_builtins()
bind_builtin( "SEARCH_FOR_TARGET",
builtin_search_for_target, 0, args );
}
{
char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
bind_builtin( "IMPORT_MODULE",
builtin_import_module, 0, args );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "IMPORTED_MODULES",
builtin_imported_modules, 0, args );
}
}
/*
@@ -846,6 +858,47 @@ builtin_search_for_target( PARSE *parse, FRAME *frame )
return list_new( L0, t->name );
}
LIST *builtin_import_module( PARSE *parse, FRAME *frame )
{
LIST* arg1 = lol_get( frame->args, 0 );
LIST* arg2 = lol_get( frame->args, 1 );
module_t* m = arg2 ? bindmodule(arg2->string) : root_module();
for(;arg1; arg1 = arg1->next) {
char* s = arg1->string;
char** ss = &s;
if (!m->imported_modules)
m->imported_modules = hashinit( sizeof(char*), "imported");
hashenter(m->imported_modules, (HASHDATA**)&ss);
}
return L0;
}
static void add_module_name( void* r_, void* result_ )
{
char** r = (char**)r_;
LIST** result = (LIST**)result_;
*result = list_new( *result, copystr( *r ) );
}
LIST *builtin_imported_modules( PARSE *parse, FRAME *frame )
{
LIST *arg0 = lol_get( frame->args, 0 );
LIST *result = L0;
module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
if ( source_module->rules )
hashenumerate( source_module->imported_modules, add_module_name, &result );
return result;
}
static void lol_build( LOL* lol, char** elements )
{
LIST* l = L0;

View File

@@ -33,6 +33,8 @@ LIST *builtin_backtrace( PARSE *parse, FRAME *args );
LIST *builtin_pwd( PARSE *parse, FRAME *args );
LIST *builtin_update( PARSE *parse, FRAME *args );
LIST *builtin_search_for_target( PARSE *parse, FRAME *args );
LIST *builtin_import_module( PARSE *parse, FRAME *args );
LIST *builtin_imported_modules( PARSE *parse, FRAME *frame );
void backtrace( FRAME *frame );

View File

@@ -50,6 +50,7 @@ module_t* bindmodule( char* name )
m->name = newstr( m->name );
m->variables = 0;
m->rules = 0;
m->imported_modules = 0;
}
string_free( &s );
return m;

View File

@@ -11,6 +11,7 @@ struct module_t
char* name;
struct hash* rules;
struct hash* variables;
struct hash* imported_modules;
};
typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */

View File

@@ -705,15 +705,59 @@ RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindli
return local;
}
RULE *bindrule( char *rulename, module_t* m )
/* Looks for a rule in the specified module, and returns it, if found.
First checks if the rule is present in the module's rule table.
Second, if name of the rule is in the form name1.name2 and name1 is in
the list of imported modules, look in module 'name1' for rule 'name2'.
*/
RULE *lookup_rule( char *rulename, module_t *m, int local_only )
{
RULE rule, *r = &rule;
RULE rule, *r = &rule, *result = 0;
module_t* original_module = m;
r->name = rulename;
if ( m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
return r;
else
return enter_rule( rulename, root_module() );
if (m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
result = r;
else if (!local_only && m->imported_modules) {
/* Try splitting the name into module and rule. */
char *p = strchr(r->name, '.') ;
if (p) {
*p = '\0';
/* Now, r->name keeps the module name, and p+1 keeps the rule name. */
if (hashcheck( m->imported_modules, (HASHDATA **)&r))
{
result = lookup_rule(p+1, bindmodule(rulename), 1);
}
*p = '.';
}
}
if (result)
{
if (local_only && !result->exported)
result = 0;
}
return result;
}
RULE *bindrule( char *rulename, module_t* m)
{
RULE *result;
result = lookup_rule(rulename, m, 0);
if (!result)
result = lookup_rule(rulename, root_module(), 0);
/* We've only one caller, 'evaluate_rule', which will complain about
calling underfined rule. We could issue the error
here, but we don't have necessary information, such as frame.
*/
if (!result)
result = enter_rule( rulename, root_module() );
return result;
}
RULE* import_rule( RULE* source, module_t* m, char* name )

View File

@@ -296,16 +296,14 @@ rule import ( module-names + : rules-opt * : rename-opt * )
load $(m) : : $(search) ;
}
local all-rules = [ RULENAMES $(m) ] ;
# import all the rules with qualification
IMPORT $(m) : $(all-rules) : $(caller) : $(m).$(all-rules) ;
IMPORT_MODULE $(m) : $(caller) ;
if $(rules-opt)
{
local source-names ;
if $(rules-opt) = *
{
local all-rules = [ RULENAMES $(m) ] ;
source-names = $(all-rules) ;
}
else

View File

@@ -386,7 +386,7 @@ rule lib-target-class ( name : project
basic-target.__init__ $(name) : $(project)
: $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
IMPORT builtin : generators.construct : $(__name__) : generators.construct ;
import generators : construct : generators.construct ;
rule construct ( source-targets * : property-set )
{

View File

@@ -168,7 +168,7 @@ rule project-target ( name : project : requirements * : default-build * )
import path ;
import print ;
import property-set ;
IMPORT targets : set.difference : $(__name__) : set.difference ;
import set : difference : set.difference ;
abstract-target.__init__ $(name) : $(project) ;

View File

@@ -0,0 +1,65 @@
#!/usr/bin/python
# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
from BoostBuild import Tester, List
t = Tester(pass_toolset=0)
# Test that
t.write("code", """
module a {
rule r1 ( )
{
ECHO R1 ;
}
}
module a2 {
rule r2 ( )
{
ECHO R2 ;
}
}
IMPORT a2 : r2 : : a2.r2 ;
module b {
IMPORT_MODULE a : b ;
rule test
{
# Call rule visible via IMPORT_MODULE
a.r1 ;
# Call rule in global scope
a2.r2 ;
}
}
IMPORT b : test : : test ;
test ;
module c {
rule test
{
ECHO CTEST ;
}
}
IMPORT_MODULE c : ;
c.test ;
actions do-nothing { }
do-nothing all ;
""")
t.run_build_system("-fcode", stdout="""R1
R2
CTEST
""")
t.cleanup()

View File

@@ -63,7 +63,7 @@ def reorder_tests(tests, first_test):
critical_tests = ["unit_tests", "module_actions", "startup_v1", "startup_v2"]
critical_tests += ["core_d12", "core_typecheck", "core_delete_module",
"core_varnames"]
"core_varnames", "core_import_module"]
tests = [ "project_test1",
"project_test3",

View File

@@ -168,7 +168,7 @@ rule project-target ( name : project : requirements * : default-build * )
import path ;
import print ;
import property-set ;
IMPORT targets : set.difference : $(__name__) : set.difference ;
import set : difference : set.difference ;
abstract-target.__init__ $(name) : $(project) ;

View File

@@ -296,16 +296,14 @@ rule import ( module-names + : rules-opt * : rename-opt * )
load $(m) : : $(search) ;
}
local all-rules = [ RULENAMES $(m) ] ;
# import all the rules with qualification
IMPORT $(m) : $(all-rules) : $(caller) : $(m).$(all-rules) ;
IMPORT_MODULE $(m) : $(caller) ;
if $(rules-opt)
{
local source-names ;
if $(rules-opt) = *
{
local all-rules = [ RULENAMES $(m) ] ;
source-names = $(all-rules) ;
}
else

View File

@@ -0,0 +1,65 @@
#!/usr/bin/python
# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
from BoostBuild import Tester, List
t = Tester(pass_toolset=0)
# Test that
t.write("code", """
module a {
rule r1 ( )
{
ECHO R1 ;
}
}
module a2 {
rule r2 ( )
{
ECHO R2 ;
}
}
IMPORT a2 : r2 : : a2.r2 ;
module b {
IMPORT_MODULE a : b ;
rule test
{
# Call rule visible via IMPORT_MODULE
a.r1 ;
# Call rule in global scope
a2.r2 ;
}
}
IMPORT b : test : : test ;
test ;
module c {
rule test
{
ECHO CTEST ;
}
}
IMPORT_MODULE c : ;
c.test ;
actions do-nothing { }
do-nothing all ;
""")
t.run_build_system("-fcode", stdout="""R1
R2
CTEST
""")
t.cleanup()

View File

@@ -63,7 +63,7 @@ def reorder_tests(tests, first_test):
critical_tests = ["unit_tests", "module_actions", "startup_v1", "startup_v2"]
critical_tests += ["core_d12", "core_typecheck", "core_delete_module",
"core_varnames"]
"core_varnames", "core_import_module"]
tests = [ "project_test1",
"project_test3",

View File

@@ -386,7 +386,7 @@ rule lib-target-class ( name : project
basic-target.__init__ $(name) : $(project)
: $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
IMPORT builtin : generators.construct : $(__name__) : generators.construct ;
import generators : construct : generators.construct ;
rule construct ( source-targets * : property-set )
{