diff --git a/Makefile b/Makefile
index 132318fe..8ed2f37b 100644
--- a/Makefile
+++ b/Makefile
@@ -123,7 +123,7 @@ endif
endif
ifneq ($(USE_CLANG),)
-WARNING_FLAGS += -Wno-misleading-indentation -Wno-unknown-warning-option -Wno-c2x-extensions -Wno-unused-function -Wno-c++2b-extensions
+WARNING_FLAGS += -Wno-misleading-indentation -Wno-unknown-warning-option -Wno-c2x-extensions -Wno-c++2b-extensions
endif
# this is the recommanded way to insert a , when calling functions
diff --git a/README.md b/README.md
index 70c90812..5ed71592 100644
--- a/README.md
+++ b/README.md
@@ -75,20 +75,20 @@ it has been tested with the dockers listed in the docker directory
- the relative positions of these 4 dirs must remain the same, i.e. they must stay in the same directory with the same names.
- specialization
- you can specialize the build process to better suit your needs :
- - this can be done by setting variables on the command line
- - for example, you can run : make CC=/my/gcc
- - PYTHON can be set to your preferred python. You will be told if it is not supported.
+ - this can be done by setting variables on the command line or in the environment
+ - for example, you can run : make CC=/my/gcc or CC=/my/gcc make
+ - PYTHON2 can be set to your preferred Python 2 (defaults to python2). You will be told if it is not supported.
+ - PYTHON can be set to your preferred Python 3 (defaults to python3). You will be told if it is not supported.
- CC can be set to your preferred compiler. You will be told if it is not supported.
- - LMAKE_OPT_LVL can be defined between 0 and 5 inclusive :
- - -O compiler option is given the provided value, up to 3
- - if 0, the -g flag is also provided
- - if 4 or above, -DNDEBUG is defined. There are *a lot* of assertions throughout the code, so it makes sens to run with -DNDEBUG.
- furthermore, a few essential assertions are left active, even with -DNDEBUG
- - if 5, no trace is generated
+ - LMAKE_OP can be defined as [0123][gG][dD][tT] (default is 3GDT)
+ - [0123] controls the -O option.
+ - [gG] controls the -g option : G passes it to enable debug, g does not.
+ - [dD] controls -DNDEBUG : D passes it to enable asserts, d does not.
+ - [tT] controls -DNO_TRACE : T does not pass it to enable traces, t passes it.
- the -j flag of make is automatically set to the number of processors, you may want to override this, though
- it is up to you to provide a suitable LD_LIBRARY_PATH value.
- it will be transferred as a default value for rules, to the extent it is necessary to provide lmake semantic (mostly this means we keep what is necessary to run python)
- - if you modify these variables, you should execute git clean as make will not detect this modification automatically
+ it will be transferred as a default value for rules, to the extent it is necessary to provide lmake semantic (mostly this means we keep what is necessary to run python).
+ - if you modify these variables, you should execute git clean as make will not detect such modifications automatically.
# coding rules
@@ -125,18 +125,17 @@ Names are suffixed with \_ if needed to suppress ambiguities
- words include standard name such as syscall names or libc functions
- special cases :
- abbrev | full-name
- |
ddate | disk date |
- dflag | dependency flag |
- filename | file name |
- lnk | symbolic link |
- ongoing | on going |
- pdate | process date |
- regexpr | regular expression |
- serdes | serialize, deserialize |
- tflag | target flag |
- wakeup | wake_up |
- wrt | with respect to |
+ abbrev | full-name
+ |
ddate | disk date |
+ dflag | dependency flag |
+ filename | file name |
+ lnk | symbolic link |
+ ongoing | on going |
+ pdate | process date |
+ regexpr | regular expression |
+ serdes | serialize, deserialize |
+ tflag | target flag |
+ wrt | with respect to |
## layout
diff --git a/TO_DO b/TO_DO
index 065c5613..c018ec46 100644
--- a/TO_DO
+++ b/TO_DO
@@ -14,7 +14,6 @@ items :
* missing some deps when reading elf
- it seems that libc.so is missing at least in some occasions
-* ld_audit does not seem to correctly bind symbols with ldopen on Ubuntu20
* reimplement hierarchical repositories
- add a sub_repositories entry to config
- map priorities to RuleIdx
@@ -28,7 +27,6 @@ items :
* LACK (not implemented but necessary for lmake semantic)
****************************************************************************************************
-* rework side_targets versus side_deps
* improve lshow -i
- generate info on nodes
* use Pdate (end of job) rather than Ddate (target date) to detect clash
@@ -74,6 +72,10 @@ items :
* ROBUSTNESS & MAINTENABILITY (fragile/difficult to read or maintain as long as not implemented)
****************************************************************************************************
+* support 64-bits id
+ - configure with NBits rather than types
+ - in store/file.hh, reserve address space after NBits instead of type
+ - first candidate would be deps, by far the most demanding
* add a warning when ids reach 15/16 of their limits
* implement noexcept/except everywhere pertinent
* use the Path struct instead of at/file
diff --git a/_lib/lmake/rules.src.py b/_lib/lmake/rules.src.py
index 21b93689..c52f5dcf 100644
--- a/_lib/lmake/rules.src.py
+++ b/_lib/lmake/rules.src.py
@@ -138,6 +138,10 @@ class _PyRule(Rule) :
mask_python_deps = False
def cmd() : # this will be executed before cmd() of concrete subclasses as cmd() are chained in case of inheritance
if gen_module_deps or mask_python_deps : # fast path :if nothing to do, do nothing
+ try : import lmake
+ except ModuleNotFoundError :
+ import sys
+ sys.path[0:0] = (_lmake_dir+'/lib',)
from lmake.import_machinery import fix_import
fix_import(gen_module_deps=gen_module_deps,mask_python_deps=mask_python_deps)
cmd.shell = '' # support shell cmd's that may launch python as a subprocess XXX : manage to execute fix_import()
diff --git a/src/app.hh b/src/app.hh
index 3defc35c..4d5cf957 100644
--- a/src/app.hh
+++ b/src/app.hh
@@ -15,8 +15,8 @@ extern ::string* g_lmake_dir ; // pointer to avoid init/fini order hazards,
extern ::string* g_root_dir ; // pointer to avoid init/fini order hazards, absolute , root of repository
extern ::string* g_exe_name ; // pointer to avoid init/fini order hazards, absolute , executable name for user messages
-/**/ void app_init( Bool3 chk_version_=Yes , bool cd_root=true ) ; // if chk_version_==Maybe, it is ok to initialize stored version
-static inline void app_init( bool cd_root ) { app_init(Yes,cd_root) ; }
+/**/ void app_init( Bool3 chk_version_=Yes , bool cd_root=true ) ; // if chk_version_==Maybe, it is ok to initialize stored version
+inline void app_init( bool cd_root ) { app_init(Yes,cd_root) ; }
void chk_version( bool may_init=false , ::string const& admin_dir=AdminDir ) ;
diff --git a/src/autodep/env.cc b/src/autodep/env.cc
index fc0ec571..5ff409b3 100644
--- a/src/autodep/env.cc
+++ b/src/autodep/env.cc
@@ -10,11 +10,11 @@ using namespace Disk ;
::ostream& operator<<( ::ostream& os , AutodepEnv const& ade ) {
os << "AutodepEnv(" ;
if (ade.active) {
- /**/ os << static_cast(ade) ;
- /**/ os <<','<< ade.service ;
- if ( ade.auto_mkdir ) os <<",auto_mkdir" ;
- if ( ade.ignore_stat) os <<",ignore_stat" ;
- if (!ade.disabled ) os <<",disabled" ;
+ /**/ os << static_cast(ade) ;
+ /**/ os <<','<< ade.service ;
+ if (ade.auto_mkdir ) os <<",auto_mkdir" ;
+ if (ade.ignore_stat) os <<",ignore_stat" ;
+ if (ade.disabled ) os <<",disabled" ;
}
return os <<')' ;
}
diff --git a/src/autodep/gather.cc b/src/autodep/gather.cc
index 1113c3fc..9dbf1310 100644
--- a/src/autodep/gather.cc
+++ b/src/autodep/gather.cc
@@ -476,6 +476,5 @@ void Gather::reorder(bool at_end) {
i_dst++ ;
}
accesses.resize(i_dst) ;
- if (at_end) access_map.clear() ; // safer not to leave outdated info
- else for( NodeIdx i=0 ; i static inline uintptr_t _la_symbind( Sym* sym , unsigned int /*ndx*/ , uintptr_t* /*ref_cook*/ , uintptr_t* def_cook , unsigned int* /*flags*/ , const char* sym_name ) {
+template uintptr_t _la_symbind( Sym* sym , unsigned int /*ndx*/ , uintptr_t* /*ref_cook*/ , uintptr_t* def_cook , unsigned int* /*flags*/ , const char* sym_name ) {
//
auditer() ; // force Audit static init
if (g_force_orig) goto Ignore ; // avoid recursion loop
diff --git a/src/autodep/ld_preload.cc b/src/autodep/ld_preload.cc
index 3d95edb0..51c60685 100644
--- a/src/autodep/ld_preload.cc
+++ b/src/autodep/ld_preload.cc
@@ -3,6 +3,6 @@
// This program is free software: you can redistribute/modify under the terms of the GPL-v3 (https://www.gnu.org/licenses/gpl-3.0.html).
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-static inline bool started() { return true ; }
+static bool started() { return true ; }
#include "ld.x.cc"
diff --git a/src/autodep/ld_preload_jemalloc.cc b/src/autodep/ld_preload_jemalloc.cc
index a168ecd5..00e8a760 100644
--- a/src/autodep/ld_preload_jemalloc.cc
+++ b/src/autodep/ld_preload_jemalloc.cc
@@ -8,7 +8,7 @@
// ensure malloc has been initialized (at least at first call to malloc) in case jemalloc is used with ld_preload to avoid malloc_init->open->malloc->malloc_init loop
static bool _g_started = false ;
-static inline bool started() { return _g_started ; }
+static bool started() { return _g_started ; }
#define LD_PRELOAD_JEMALLOC
#include "ld.x.cc"
diff --git a/src/autodep/ld_server.cc b/src/autodep/ld_server.cc
index 61236eb7..79b18757 100644
--- a/src/autodep/ld_server.cc
+++ b/src/autodep/ld_server.cc
@@ -8,7 +8,7 @@
thread_local bool AutodepLock::t_active = false ;
/**/ ::mutex AutodepLock::_s_mutex ;
-static inline bool started() { return AutodepLock::t_active ; } // no auto-start for server
+static bool started() { return AutodepLock::t_active ; } // no auto-start for server
#define IN_SERVER
#include "ld.x.cc"
diff --git a/src/autodep/record.cc b/src/autodep/record.cc
index adf59acc..73854f3f 100644
--- a/src/autodep/record.cc
+++ b/src/autodep/record.cc
@@ -173,9 +173,9 @@ Record::Mkdir::Mkdir( Record& r , Path&& path , ::string&& c ) : Solve{r,::move(
if (file_loc==FileLoc::Repo) r._report_guard( ::move(real) , ::move(c) ) ;
}
-static inline bool _do_stat (int flags) { return flags&O_PATH ; }
-static inline bool _do_read (int flags) { return !_do_stat(flags) && (flags&O_ACCMODE)!=O_WRONLY && !(flags&O_TRUNC) ; }
-static inline bool _do_write(int flags) { return !_do_stat(flags) && (flags&O_ACCMODE)!=O_RDONLY ; }
+static bool _do_stat (int flags) { return flags&O_PATH ; }
+static bool _do_read (int flags) { return !_do_stat(flags) && (flags&O_ACCMODE)!=O_WRONLY && !(flags&O_TRUNC) ; }
+static bool _do_write(int flags) { return !_do_stat(flags) && (flags&O_ACCMODE)!=O_RDONLY ; }
Record::Open::Open( Record& r , Path&& path , int flags , ::string&& c ) :
Solve{ r , ::move(path) , bool(flags&O_NOFOLLOW) , _do_read(flags) , true/*allow_tmp_map*/ , to_string(c,::hex,'.',flags) }
, do_write{_do_write(flags)}
diff --git a/src/autodep/syscall_tab.cc b/src/autodep/syscall_tab.cc
index 8e1eb9e6..808774ca 100644
--- a/src/autodep/syscall_tab.cc
+++ b/src/autodep/syscall_tab.cc
@@ -58,7 +58,7 @@ template static Record::Path _path( pid_t pid , uint64_t const* args )
// updating args is meaningful only when processing calls to the syscall function with ld_audit & ld_preload
// when autodep is ptrace, tmp mapping is not supported and such args updating is ignored as args have been copied from tracee and are not copied back to it
-template static inline void _update( uint64_t* args , Record::Path const& p ) {
+template void _update( uint64_t* args , Record::Path const& p ) {
SWEAR(p.has_at==At) ;
if (At) args[0 ] = p.at ;
/**/ args[At] = reinterpret_cast(p.file) ;
@@ -66,7 +66,7 @@ template static inline void _update( uint64_t* args , Record::Path cons
static constexpr int FlagAlways = -1 ;
static constexpr int FlagNever = -2 ;
-template static inline bool _flag( uint64_t args[6] , int flag ) {
+template bool _flag( uint64_t args[6] , int flag ) {
switch (FlagArg) {
case FlagAlways : return true ;
case FlagNever : return false ;
@@ -75,13 +75,13 @@ template static inline bool _flag( uint64_t args[6] , int flag ) {
}
// chdir
-template static inline void _entry_chdir( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_chdir( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
if (At) { Record::Chdir* cd = new Record::Chdir( r , {Fd(args[0]) } , comment ) ; ctx = cd ; }
else { Record::Chdir* cd = new Record::Chdir( r , {_path(pid,args+0)} , comment ) ; ctx = cd ; _update(args+0,*cd) ; }
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_chdir( void* ctx , Record& r , pid_t pid , int64_t res ) {
+static int64_t/*res*/ _exit_chdir( void* ctx , Record& r , pid_t pid , int64_t res ) {
if (!ctx) return res ;
Record::Chdir* cd = static_cast(ctx) ;
(*cd)(r,res,pid) ;
@@ -90,14 +90,14 @@ static inline int64_t/*res*/ _exit_chdir( void* ctx , Record& r , pid_t pid , in
}
// chmod
-template void static inline _entry_chmod( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_chmod( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Chmod* cm = new Record::Chmod( r , _path(pid,args+0) , args[1+At]&S_IXUSR , _flag(args,AT_SYMLINK_NOFOLLOW) , comment ) ;
ctx = cm ;
_update(args+0,*cm) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_chmod( void* ctx , Record& r , pid_t , int64_t res ) {
+static int64_t/*res*/ _exit_chmod( void* ctx , Record& r , pid_t , int64_t res ) {
if (!ctx) return res ;
Record::Chmod* cm = static_cast(ctx) ;
(*cm)(r,res) ;
@@ -106,7 +106,7 @@ static inline int64_t/*res*/ _exit_chmod( void* ctx , Record& r , pid_t , int64_
}
// creat
-static inline void _entry_creat( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+static void _entry_creat( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Open* o = new Record::Open( r , _path(pid,args+0) , O_WRONLY|O_CREAT|O_TRUNC , comment ) ;
ctx = o ;
@@ -118,7 +118,7 @@ static inline void _entry_creat( void* & ctx , Record& r , pid_t pid , uint64_t
// execve
// must be called before actual syscall execution as after execution, info is no more available
-template static inline void _entry_execve( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template static void _entry_execve( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Exec e{ r , _path(pid,args+0) , _flag(args,AT_SYMLINK_NOFOLLOW) , comment } ;
_update(args+0,e) ;
@@ -127,11 +127,11 @@ template static inline void _entry_execve( void* & /*ctx*/
// getcwd
// getcwd is only necessary if tmp is mapped (not in table with ptrace)
-static inline void _entry_getcwd( void* & ctx , Record& , pid_t , uint64_t args[6] , const char* /*comment*/ ) {
+static void _entry_getcwd( void* & ctx , Record& , pid_t , uint64_t args[6] , const char* /*comment*/ ) {
size_t* sz = new size_t{args[1]} ;
ctx = sz ;
}
-static inline int64_t/*res*/ _exit_getcwd( void* ctx , Record& , pid_t pid , int64_t res ) {
+static int64_t/*res*/ _exit_getcwd( void* ctx , Record& , pid_t pid , int64_t res ) {
if (!res ) return res ; // in case of error, man getcwd says buffer is undefined => nothing to do
if (!Record::s_has_tmp_view()) return res ; // no tmp mapping => nothing to do
SWEAR(pid==0,pid) ; // tmp mapping is not supported with ptrace (need to report fixed result to caller)
@@ -143,7 +143,7 @@ static inline int64_t/*res*/ _exit_getcwd( void* ctx , Record& , pid_t pid , int
}
// hard link
-template static inline void _entry_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Lnk* l = new Record::Lnk( r , _path(pid,args+0) , _path(pid,args+1+At) , _flag(args,AT_SYMLINK_NOFOLLOW) , comment ) ;
ctx = l ;
@@ -151,7 +151,7 @@ template static inline void _entry_lnk( void* & ctx , Recor
_update(args+2,l->dst) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_lnk( void* ctx , Record& r , pid_t /*pid */, int64_t res ) {
+static int64_t/*res*/ _exit_lnk( void* ctx , Record& r , pid_t /*pid */, int64_t res ) {
if (!ctx) return res ;
Record::Lnk* l = static_cast(ctx) ;
(*l)(r,res) ;
@@ -160,7 +160,7 @@ static inline int64_t/*res*/ _exit_lnk( void* ctx , Record& r , pid_t /*pid */,
}
// mkdir
-template static inline void _entry_mkdir( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_mkdir( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Mkdir m{ r , _path(pid,args+0) , comment } ;
_update(args+0,m) ;
@@ -168,7 +168,7 @@ template static inline void _entry_mkdir( void* & /*ctx*/ , Record& r ,
}
// open
-template static inline void _entry_open( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_open( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Open* o = new Record::Open( r , _path(pid,args+0) , args[1+At]/*flags*/ , comment ) ;
ctx = o ;
@@ -176,7 +176,7 @@ template static inline void _entry_open( void* & ctx , Record& r , pid_
}
catch (int) {}
}
-static inline int64_t/*res*/ _exit_open( void* ctx , Record& r , pid_t /*pid*/ , int64_t res ) {
+static int64_t/*res*/ _exit_open( void* ctx , Record& r , pid_t /*pid*/ , int64_t res ) {
if (!ctx) return res ;
Record::Open* o = static_cast(ctx) ;
(*o)( r , res ) ;
@@ -185,14 +185,14 @@ static inline int64_t/*res*/ _exit_open( void* ctx , Record& r , pid_t /*pid*/ ,
}
// read_lnk
-template static inline void _entry_read_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_read_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Readlnk* rl = new Record::Readlnk( r , _path(pid,args+0) , comment ) ;
ctx = rl ;
_update(args+0,*rl) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_read_lnk( void* ctx , Record& r , pid_t pid , int64_t res ) {
+static int64_t/*res*/ _exit_read_lnk( void* ctx , Record& r , pid_t pid , int64_t res ) {
if (!ctx) return res ;
Record::Readlnk* rl = static_cast(ctx) ;
SWEAR( pid==0 || !Record::s_has_tmp_view() , pid ) ; // tmp mapping is not supported with ptrace (need to report new value to caller)
@@ -202,7 +202,7 @@ static inline int64_t/*res*/ _exit_read_lnk( void* ctx , Record& r , pid_t pid ,
}
// rename
-template static inline void _entry_rename( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_rename( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
#ifdef RENAME_EXCHANGE
bool exchange = _flag(args,RENAME_EXCHANGE) ;
@@ -220,7 +220,7 @@ template static inline void _entry_rename( void* & ctx , Re
_update(args+2,rn->dst) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_rename( void* ctx , Record& r , pid_t /*pid*/ , int64_t res ) {
+static int64_t/*res*/ _exit_rename( void* ctx , Record& r , pid_t /*pid*/ , int64_t res ) {
if (!ctx) return res ;
Record::Rename* rn = static_cast(ctx) ;
(*rn)(r,res) ;
@@ -229,14 +229,14 @@ static inline int64_t/*res*/ _exit_rename( void* ctx , Record& r , pid_t /*pid*/
}
// symlink
-template static inline void _entry_sym_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_sym_lnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Symlnk* sl = new Record::Symlnk( r , _path(pid,args+1) , comment ) ;
ctx = sl ;
_update(args+1,*sl) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_sym_lnk( void* ctx , Record& r , pid_t , int64_t res ) {
+static int64_t/*res*/ _exit_sym_lnk( void* ctx , Record& r , pid_t , int64_t res ) {
if (!ctx) return res ;
Record::Symlnk* sl = static_cast(ctx) ;
(*sl)(r,res) ;
@@ -245,7 +245,7 @@ static inline int64_t/*res*/ _exit_sym_lnk( void* ctx , Record& r , pid_t , int6
}
// unlink
-template static inline void _entry_unlnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_unlnk( void* & ctx , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
bool rmdir = _flag(args,AT_REMOVEDIR) ;
Record::Unlnk* u = new Record::Unlnk( r , _path(pid,args+0) , rmdir , comment ) ;
@@ -253,7 +253,7 @@ template static inline void _entry_unlnk( void* & ctx , Rec
_update(args+0,*u) ;
} catch (int) {}
}
-static inline int64_t/*res*/ _exit_unlnk( void* ctx , Record& r , pid_t , int64_t res ) {
+static int64_t/*res*/ _exit_unlnk( void* ctx , Record& r , pid_t , int64_t res ) {
if (!ctx) return res ;
Record::Unlnk* u = static_cast(ctx) ;
(*u)(r,res) ;
@@ -262,7 +262,7 @@ static inline int64_t/*res*/ _exit_unlnk( void* ctx , Record& r , pid_t , int64_
}
// access
-template static inline void _entry_stat( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
+template void _entry_stat( void* & /*ctx*/ , Record& r , pid_t pid , uint64_t args[6] , const char* comment ) {
try {
Record::Stat s{ r , _path(pid,args+0) , _flag(args,AT_SYMLINK_NOFOLLOW) , comment } ;
_update(args+0,s) ;
diff --git a/src/client.hh b/src/client.hh
index ebc3d131..9deaaaf6 100644
--- a/src/client.hh
+++ b/src/client.hh
@@ -24,7 +24,7 @@ struct AutoCloseFdPair {
extern AutoCloseFdPair g_server_fds ;
-static inline Rc mk_rc(Bool3 ok) {
+inline Rc mk_rc(Bool3 ok) {
switch (ok) {
case Yes : return Rc::Ok ;
case Maybe : return Rc::Format ;
diff --git a/src/disk.cc b/src/disk.cc
index 60d3e09b..0de8e8fb 100644
--- a/src/disk.cc
+++ b/src/disk.cc
@@ -179,7 +179,7 @@ namespace Disk {
return res ;
}
- static inline int/*n_dirs*/ _mkdir( Fd at , ::string const& dir , NfsGuard* nfs_guard , bool multi , bool unlnk_ok ) {
+ static int/*n_dirs*/ _mkdir( Fd at , ::string const& dir , NfsGuard* nfs_guard , bool multi , bool unlnk_ok ) {
::vector_s to_mk { dir } ;
const char* msg = nullptr ;
int res = 0 ;
@@ -385,7 +385,7 @@ namespace Disk {
// - avoid ::string copying as much as possible
// - do not support links outside repo & tmp, except from /proc (which is meaningful)
// - note that besides syscalls, this algo is very fast and caching intermediate results could degrade performances (checking the cache could take as long as doing the job)
- static inline int _get_symloop_max() { // max number of links to follow before decreting it is a loop
+ static int _get_symloop_max() { // max number of links to follow before decreting it is a loop
int res = ::sysconf(_SC_SYMLOOP_MAX) ;
if (res>=0) return res ;
else return _POSIX_SYMLOOP_MAX ;
@@ -533,10 +533,10 @@ namespace Disk {
::string interpreter ; interpreter.reserve(256) ;
::string root_dir_s = _env->root_dir+'/' ;
// from tmp, we can go back to repo
- for( int i=0 ; i<=4 ; i++ ) { // interpret #! recursively (4 levels as per man execve)
+ for( int i=0 ; i<=4 ; i++ ) { // interpret #! recursively (4 levels as per man execve)
for( ::string& l : sr.lnks ) res.emplace_back(::move(l),Accesses(Access::Lnk)) ;
//
- if (sr.file_loc>FileLoc::Dep && sr.file_loc!=FileLoc::Tmp) break ; // if we escaped from the repo, there is no more deps to gather
+ if (sr.file_loc>FileLoc::Dep && sr.file_loc!=FileLoc::Tmp) break ; // if we escaped from the repo, there is no more deps to gather
//
if (sr.mapped)
throw to_string("executing ",mk_file(sr.real)," with mapped files along its interpreter path from ",_tmp_view," to ",_env->tmp_dir," would require to modify file contents") ;
@@ -549,11 +549,11 @@ namespace Disk {
if (!real_stream.read(hdr,sizeof(hdr))) break ;
if (strncmp(hdr,"#!",2)!=0 ) break ;
interpreter.resize(256) ;
- real_stream.getline(interpreter.data(),interpreter.size()) ; // man execve specifies that data beyond 255 chars are ignored
+ real_stream.getline(interpreter.data(),interpreter.size()) ; // man execve specifies that data beyond 255 chars are ignored
if (!real_stream.gcount()) break ;
interpreter.resize(real_stream.gcount()) ;
- if ( size_t pos = interpreter.find(' ' ) ; pos!=Npos ) interpreter.resize(pos) ; // interpreter is the first word
- else if ( size_t pos = interpreter.find('\0') ; pos!=Npos ) interpreter.resize(pos) ; // interpreter is the entire line (or the first \0 delimited word)
+ if ( size_t pos = interpreter.find(' ' ) ; pos!=Npos ) interpreter.resize(pos) ; // interpreter is the first word
+ else if ( size_t pos = interpreter.find('\0') ; pos!=Npos ) interpreter.resize(pos) ; // interpreter is the entire line (or the first \0 delimited word)
// recurse
sr = solve(interpreter,false/*no_follow*/) ;
}
diff --git a/src/disk.hh b/src/disk.hh
index f0c07df5..c0ba8658 100644
--- a/src/disk.hh
+++ b/src/disk.hh
@@ -150,55 +150,55 @@ namespace Disk {
bool/*done*/ uniquify ( Fd at , ::string const& file ) ;
void rmdir ( Fd at , ::string const& dir ) ;
//
- static inline void lnk( Fd at , ::string const& file , ::string const& target ) {
+ inline void lnk( Fd at , ::string const& file , ::string const& target ) {
if (::symlinkat(target.c_str(),at,file.c_str())!=0) {
::string at_str = at==Fd::Cwd ? ""s : to_string('<',int(at),">/") ;
throw to_string("cannot create symlink from ",at_str,file," to ",target) ;
}
}
- static inline Fd open_read( Fd at , ::string const& filename ) {
+ inline Fd open_read( Fd at , ::string const& filename ) {
return ::openat( at , filename.c_str() , O_RDONLY|O_CLOEXEC , 0666 ) ;
}
- static inline Fd open_write( Fd at , ::string const& filename , bool append=false , bool exe=false , bool read_only=false ) {
+ inline Fd open_write( Fd at , ::string const& filename , bool append=false , bool exe=false , bool read_only=false ) {
dir_guard(at,filename) ;
return ::openat( at , filename.c_str() , O_WRONLY|O_CREAT|O_NOFOLLOW|O_CLOEXEC|(append?O_APPEND:O_TRUNC) , 0777 & ~(exe?0000:0111) & ~(read_only?0222:0000) ) ;
}
- static inline ::string read_lnk( Fd at , ::string const& file ) {
+ inline ::string read_lnk( Fd at , ::string const& file ) {
char buf[PATH_MAX] ;
ssize_t cnt = ::readlinkat(at,file.c_str(),buf,PATH_MAX) ;
if ( cnt<0 || cnt>=PATH_MAX ) return {} ;
return {buf,size_t(cnt)} ;
}
- static inline bool is_reg ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).is_reg() ; }
- static inline bool is_dir ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).tag()==FileTag::Dir ; }
- static inline bool is_target( Fd at , ::string const& file={} , bool no_follow=true ) { return +FileInfo(at,file,no_follow) ; }
- static inline bool is_exe ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).tag()==FileTag::Exe ; }
- static inline Ddate file_date( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).date ; }
+ inline bool is_reg ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).is_reg() ; }
+ inline bool is_dir ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).tag()==FileTag::Dir ; }
+ inline bool is_target( Fd at , ::string const& file={} , bool no_follow=true ) { return +FileInfo(at,file,no_follow) ; }
+ inline bool is_exe ( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).tag()==FileTag::Exe ; }
+ inline Ddate file_date( Fd at , ::string const& file={} , bool no_follow=true ) { return FileInfo(at,file,no_follow).date ; }
- static inline ::vector_s lst_dir ( ::string const& dir , ::string const& prefix={} ) { return lst_dir (Fd::Cwd,dir ,prefix ) ; }
- static inline ::vector_s walk ( ::string const& file , ::string const& prefix={} ) { return walk (Fd::Cwd,file,prefix ) ; }
- static inline int/*n_dirs*/ mkdir ( ::string const& dir , bool multi=true , bool unlnk_ok=false ) { return mkdir (Fd::Cwd,dir , multi,unlnk_ok ) ; }
- static inline int/*n_dirs*/ mkdir ( ::string const& dir , NfsGuard& ng , bool multi=true , bool unlnk_ok=false ) { return mkdir (Fd::Cwd,dir ,ng,multi,unlnk_ok ) ; }
- static inline ::string const& dir_guard ( ::string const& file ) { dir_guard (Fd::Cwd,file) ; return file ; }
- static inline void unlnk_inside( ::string const& dir ) { unlnk_inside(Fd::Cwd,dir ) ; }
- static inline bool/*done*/ unlnk ( ::string const& file , bool dir_ok=false ) { return unlnk (Fd::Cwd,file,dir_ok ) ; }
- static inline bool/*done*/ uniquify ( ::string const& file ) { return uniquify (Fd::Cwd,file ) ; }
- static inline void rmdir ( ::string const& file ) { rmdir (Fd::Cwd,file ) ; }
- static inline void lnk ( ::string const& file , ::string const& target ) { lnk (Fd::Cwd,file,target ) ; }
- static inline Fd open_read ( ::string const& file ) { return open_read (Fd::Cwd,file ) ; }
- static inline Fd open_write ( ::string const& file , bool append=false , bool exe=false , bool read_only=false ) { return open_write (Fd::Cwd,file,append,exe,read_only) ; }
- static inline ::string read_lnk ( ::string const& file ) { return read_lnk (Fd::Cwd,file ) ; }
- static inline bool is_reg ( ::string const& file , bool no_follow=true ) { return is_reg (Fd::Cwd,file,no_follow ) ; }
- static inline bool is_dir ( ::string const& file , bool no_follow=true ) { return is_dir (Fd::Cwd,file,no_follow ) ; }
- static inline bool is_target ( ::string const& file , bool no_follow=true ) { return is_target (Fd::Cwd,file,no_follow ) ; }
- static inline bool is_exe ( ::string const& file , bool no_follow=true ) { return is_exe (Fd::Cwd,file,no_follow ) ; }
- static inline Ddate file_date ( ::string const& file , bool no_follow=true ) { return file_date (Fd::Cwd,file,no_follow ) ; }
+ inline ::vector_s lst_dir ( ::string const& dir , ::string const& prefix={} ) { return lst_dir (Fd::Cwd,dir ,prefix ) ; }
+ inline ::vector_s walk ( ::string const& file , ::string const& prefix={} ) { return walk (Fd::Cwd,file,prefix ) ; }
+ inline int/*n_dirs*/ mkdir ( ::string const& dir , bool multi=true , bool unlnk_ok=false ) { return mkdir (Fd::Cwd,dir , multi,unlnk_ok ) ; }
+ inline int/*n_dirs*/ mkdir ( ::string const& dir , NfsGuard& ng , bool multi=true , bool unlnk_ok=false ) { return mkdir (Fd::Cwd,dir ,ng,multi,unlnk_ok ) ; }
+ inline ::string const& dir_guard ( ::string const& file ) { dir_guard (Fd::Cwd,file) ; return file ; }
+ inline void unlnk_inside( ::string const& dir ) { unlnk_inside(Fd::Cwd,dir ) ; }
+ inline bool/*done*/ unlnk ( ::string const& file , bool dir_ok=false ) { return unlnk (Fd::Cwd,file,dir_ok ) ; }
+ inline bool/*done*/ uniquify ( ::string const& file ) { return uniquify (Fd::Cwd,file ) ; }
+ inline void rmdir ( ::string const& file ) { rmdir (Fd::Cwd,file ) ; }
+ inline void lnk ( ::string const& file , ::string const& target ) { lnk (Fd::Cwd,file,target ) ; }
+ inline Fd open_read ( ::string const& file ) { return open_read (Fd::Cwd,file ) ; }
+ inline Fd open_write ( ::string const& file , bool append=false , bool exe=false , bool read_only=false ) { return open_write (Fd::Cwd,file,append,exe,read_only) ; }
+ inline ::string read_lnk ( ::string const& file ) { return read_lnk (Fd::Cwd,file ) ; }
+ inline bool is_reg ( ::string const& file , bool no_follow=true ) { return is_reg (Fd::Cwd,file,no_follow ) ; }
+ inline bool is_dir ( ::string const& file , bool no_follow=true ) { return is_dir (Fd::Cwd,file,no_follow ) ; }
+ inline bool is_target ( ::string const& file , bool no_follow=true ) { return is_target (Fd::Cwd,file,no_follow ) ; }
+ inline bool is_exe ( ::string const& file , bool no_follow=true ) { return is_exe (Fd::Cwd,file,no_follow ) ; }
+ inline Ddate file_date ( ::string const& file , bool no_follow=true ) { return file_date (Fd::Cwd,file,no_follow ) ; }
- static inline ::string cwd() {
+ inline ::string cwd() {
char buf[PATH_MAX] ; // use posix, not linux extension that allows to pass nullptr as argument and malloc's the returned string
char* cwd = ::getcwd(buf,PATH_MAX) ;
if (!cwd) throw "cannot get cwd"s ;
@@ -208,19 +208,19 @@ namespace Disk {
else return res ;
}
- static inline bool is_abs (::string const& name ) { return !name || name [0]=='/' ; } // name is (/)* or (/)* with =[^/]+, empty name is necessarily absolute
- static inline bool is_abs_s(::string const& name_s) { return name_s[0]=='/' ; } // name_s is (/)* or /(/)* with =[^/]+, empty name_s is necessarily relative
+ inline bool is_abs (::string const& name ) { return !name || name [0]=='/' ; } // name is (/)* or (/)* with =[^/]+, empty name is necessarily absolute
+ inline bool is_abs_s(::string const& name_s) { return name_s[0]=='/' ; } // name_s is (/)* or /(/)* with =[^/]+, empty name_s is necessarily relative
//
- static inline bool is_lcl (::string const& name ) { return !( is_abs (name ) || name .starts_with("../") || name==".." ) ; }
- static inline bool is_lcl_s(::string const& name_s) { return !( is_abs_s(name_s) || name_s.starts_with("../") ) ; }
+ inline bool is_lcl (::string const& name ) { return !( is_abs (name ) || name .starts_with("../") || name==".." ) ; }
+ inline bool is_lcl_s(::string const& name_s) { return !( is_abs_s(name_s) || name_s.starts_with("../") ) ; }
//
- /**/ ::string mk_lcl( ::string const& file , ::string const& dir_s ) ; // return file (passed as from dir_s origin) as seen from dir_s
- /**/ ::string mk_glb( ::string const& file , ::string const& dir_s ) ; // return file (passed as from dir_s ) as seen from dir_s origin
- static inline ::string mk_abs( ::string const& file , ::string const& dir_s ) { // return file (passed as from dir_s ) as absolute
+ /**/ ::string mk_lcl( ::string const& file , ::string const& dir_s ) ; // return file (passed as from dir_s origin) as seen from dir_s
+ /**/ ::string mk_glb( ::string const& file , ::string const& dir_s ) ; // return file (passed as from dir_s ) as seen from dir_s origin
+ inline ::string mk_abs( ::string const& file , ::string const& dir_s ) { // return file (passed as from dir_s ) as absolute
SWEAR( is_abs_s(dir_s) , dir_s ) ;
return mk_glb(file,dir_s) ;
}
- static inline ::string mk_rel( ::string const& file , ::string const& dir_s ) {
+ inline ::string mk_rel( ::string const& file , ::string const& dir_s ) {
if (is_abs(file)==is_abs_s(dir_s)) return mk_lcl(file,dir_s) ;
else return file ;
}
@@ -229,15 +229,15 @@ namespace Disk {
// file format is : FileMrkr + file length + file
static constexpr char FileMrkr = 0 ;
::string _localize( ::string const& txt , ::string const& dir_s , size_t first_file ) ; // not meant to be used directly
- static inline ::string localize( ::string const& txt , ::string const& dir_s={} ) {
+ inline ::string localize( ::string const& txt , ::string const& dir_s={} ) {
if ( size_t pos = txt.find(FileMrkr) ; pos==Npos ) return txt ; // fast path : avoid calling localize
else return _localize(txt,dir_s,pos) ;
}
- static inline ::string localize( ::string&& txt , ::string const& dir_s={} ) {
+ inline ::string localize( ::string&& txt , ::string const& dir_s={} ) {
if ( size_t pos = txt.find(FileMrkr) ; pos==Npos ) return ::move (txt ) ; // fast path : avoid copy
else return _localize(txt,dir_s,pos) ;
}
- static inline ::string mk_file( ::string const& f , Bool3 exists=Maybe ) {
+ inline ::string mk_file( ::string const& f , Bool3 exists=Maybe ) {
::string pfx(1+sizeof(FileNameIdx),FileMrkr) ;
encode_int(&pfx[1],f.size()) ;
switch (exists) {
diff --git a/src/hash.cc b/src/hash.cc
index 38ab431b..2b3a50c0 100644
--- a/src/hash.cc
+++ b/src/hash.cc
@@ -143,10 +143,10 @@ namespace Hash {
return { *reinterpret_cast(_hash) , is_lnk } ;
}
- static inline void _round1( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( ((b&c)|((~b)&d)) + a + m , s ) ; }
- static inline void _round2( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( ((d&b)|((~d)&c)) + a + m , s ) ; }
- static inline void _round3( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( (b^c^d ) + a + m , s ) ; }
- static inline void _round4( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( (c^(b|(~d)) ) + a + m , s ) ; }
+ static void _round1( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( ((b&c)|((~b)&d)) + a + m , s ) ; }
+ static void _round2( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( ((d&b)|((~d)&c)) + a + m , s ) ; }
+ static void _round3( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( (b^c^d ) + a + m , s ) ; }
+ static void _round4( uint32_t& a , uint32_t b , uint32_t c , uint32_t d , uint32_t m , int s ) { a = b + ::rotl( (c^(b|(~d)) ) + a + m , s ) ; }
//
void _Md5::_update64(const uint32_t _data[BlkSz]) {
uint32_t a = _hash[0] ;
diff --git a/src/job_exec.cc b/src/job_exec.cc
index c013c0d0..5ccad4bc 100644
--- a/src/job_exec.cc
+++ b/src/job_exec.cc
@@ -25,21 +25,21 @@ using namespace Time ;
static constexpr int NConnectionTrials = 3 ; // number of times to try connect when connecting to server
-template struct PatternDict {
- static constexpr T NotFound = {} ;
+struct PatternDict {
+ static constexpr MatchFlags NotFound = {} ;
// services
- T const& at(::string const& x) const {
+ MatchFlags const& at(::string const& x) const {
if ( auto it=knowns.find(x) ; it!=knowns.end() ) return it->second ;
for( auto const& [p,r] : patterns ) if (+p.match(x)) return r ;
/**/ return NotFound ;
}
- void add( bool star , ::string const& key , T const& val ) {
+ void add( bool star , ::string const& key , MatchFlags const& val ) {
if (star) patterns.emplace_back( RegExpr(key,true/*fast*/,true/*no_group*/) , val ) ;
else knowns .emplace ( key , val ) ;
}
// data
- ::umap_s knowns = {} ;
- ::vmap patterns = {} ;
+ ::umap_s knowns = {} ;
+ ::vmap patterns = {} ;
} ;
ServerSockFd g_server_fd ;
@@ -51,9 +51,10 @@ ::string g_service_end ;
SeqId g_seq_id = 0/*garbage*/ ;
JobIdx g_job = 0/*garbage*/ ;
::atomic g_killed = false ; // written by thread S and read by main thread
-PatternDict g_match_dct ;
+PatternDict g_match_dct ;
NfsGuard g_nfs_guard ;
::umap_s g_missing_static_targets ;
+::vector_s g_washed ;
void kill_thread_func(::stop_token stop) {
t_thread_key = 'K' ;
@@ -96,16 +97,11 @@ bool/*keep_fd*/ handle_server_req( JobServerRpcReq&& jsrr , SlaveSockFd const& )
return false ;
}
-::pair_s wash(Pdate start) {
- Trace trace("wash",start,g_start_info.pre_actions) ;
- ::pair/*msg*/> actions = do_file_actions( ::move(g_start_info.pre_actions) , g_nfs_guard , g_start_info.hash_algo ) ;
+::pair_s wash() {
+ Trace trace("wash",g_start_info.pre_actions) ;
+ ::pair_s actions = do_file_actions( ::move(g_start_info.pre_actions) , g_nfs_guard , g_start_info.hash_algo ) ;
trace("unlnks",actions) ;
- if (actions.second.second/*ok*/)
- for( ::string const& f : actions.first ) {
- MatchFlags flags = g_match_dct.at(f) ;
- if ( flags.is_target==Yes && static_phony(flags.tflags()) ) g_gather.new_unlnk(start,f) ; // other washed files belong to history, dont record them being erased
- }
- return actions.second ;
+ return actions ;
}
::map_ss prepare_env(JobRpcReq& end_report) {
@@ -231,24 +227,31 @@ Digest analyze( bool at_end , bool killed=false ) {
/**/ append_to_string( res.msg , mk_file(file,No|!unlnk) , '\n') ;
break ;
}
- if (ad.write!=No) {
+ switch (ad.write) {
+ case No : break ;
// /!\ if a write is interrupted, it may continue past the end of the process when accessing a network disk
- if ( ad.write==Maybe ) relax.sleep_until() ; // no need to optimize (could compute other crcs while waiting) as this is exceptional
- if ( unlnk ) td.crc = Crc::None ;
- else if ( killed || !td.tflags[Tflag::Target] ) { FileInfo fi{file} ; td.crc = Crc(fi.tag()) ; td.date = fi.date ; } // no crc if meaningless
- else res.crcs.emplace_back(res.targets.size()) ; // record index in res.targets for deferred (parallel) crc computation
- }
+ case Maybe : relax.sleep_until() ; [[fallthrough]] ; // no need to optimize (could compute other crcs while waiting) as this is exceptional
+ case Yes :
+ if ( unlnk ) td.crc = Crc::None ;
+ else if ( killed || !td.tflags[Tflag::Target] ) { FileInfo fi{file} ; td.crc = Crc(fi.tag()) ; td.date = fi.date ; } // no crc if meaningless
+ else res.crcs.emplace_back(res.targets.size()) ; // record index in res.targets for deferred (parallel) crc computation
+ break ;
+ DF}
if ( td.tflags[Tflag::Target] && !static_phony(td.tflags) ) { // unless static or phony, a target loses its official status if not actually produced
if (ad.write==Yes) { if (unlnk ) td.tflags &= ~Tflag::Target ; }
else { if (!is_target(file)) td.tflags &= ~Tflag::Target ; }
}
- if ( td.tflags[Tflag::Target] && td.tflags[Tflag::Static] ) g_missing_static_targets.erase(file) ;
+ if ( td.tflags[Tflag::Target] && td.tflags[Tflag::Static] && (td.tflags[Tflag::Phony]||td.crc!=Crc::None) ) g_missing_static_targets.erase(file) ;
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
res.targets.emplace_back(file,td) ;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
trace("target",ad,td,STR(unlnk),file) ;
}
}
+ for( ::string const& t : g_washed ) if (!g_gather.access_map.contains(t)) {
+ trace("wash",t) ;
+ res.targets.emplace_back( t , TargetDigest{.extra_tflags=ExtraTflag::Wash,.crc=Crc::None} ) ;
+ }
trace("done",res.deps.size(),res.targets.size(),res.crcs.size(),res.msg) ;
return res ;
}
@@ -406,10 +409,12 @@ int main( int argc , char* argv[] ) {
/**/ g_gather.timeout = g_start_info.timeout ;
/**/ g_gather.kill_job_cb = kill_job ;
//
- ::pair_s wash_report = wash(start_overhead) ;
+ trace("wash",g_start_info.pre_actions) ;
+ ::pair_s wash_report = do_file_actions( g_washed , ::move(g_start_info.pre_actions) , g_nfs_guard , g_start_info.hash_algo ) ;
end_report.msg += wash_report.first ;
if (!wash_report.second) { end_report.digest.status = Status::LateLostErr ; goto End ; }
g_gather.new_deps( start_overhead , ::move(g_start_info.deps) , g_start_info.stdin ) ;
+ for( auto const& [t,f] : g_match_dct.knowns ) if (f.is_target==Yes) g_gather.new_unlnk(start_overhead,t) ;
//
Fd child_stdin ;
if (+g_start_info.stdin) child_stdin = open_read(g_start_info.stdin) ;
@@ -431,7 +436,6 @@ int main( int argc , char* argv[] ) {
struct rusage rsrcs ; getrusage(RUSAGE_CHILDREN,&rsrcs) ;
trace("start_job",start_job,"end_job",end_job) ;
//
- //
Digest digest = analyze(true/*at_end*/,killed) ;
for( auto const& [f,p] : g_missing_static_targets ) {
FileInfo fi{f} ;
diff --git a/src/lmakeserver/backend.cc b/src/lmakeserver/backend.cc
index eb919e83..b36e71b4 100644
--- a/src/lmakeserver/backend.cc
+++ b/src/lmakeserver/backend.cc
@@ -65,7 +65,7 @@ namespace Backends {
return res ;
}
- static inline bool _localize( Tag t , ReqIdx ri ) {
+ static bool _localize( Tag t , ReqIdx ri ) {
::unique_lock lock{Req::s_reqs_mutex} ; // taking Req::s_reqs_mutex is compulsery to derefence req
return Req(ri)->options.flags[ReqFlag::Local] || !Backend::s_ready(t) ; // if asked backend is not usable, force local execution
}
@@ -441,8 +441,8 @@ namespace Backends {
//
auto it = _s_start_tab.find(+job) ; if (it==_s_start_tab.end() ) { trace("not_in_tab" ) ; return false ; }
StartEntry& entry = it->second ; if (entry.conn.seq_id!=jrr.seq_id) { trace("bad_seq_id",entry.conn.seq_id,jrr.seq_id) ; return false ; }
- je = JobExec( job , entry.conn.host , entry.start_date ) ;
- rsrcs = ::move(entry.rsrcs) ;
+ je = JobExec( job , entry.conn.host , entry.start_date ) ;
+ rsrcs = ::move(entry.rsrcs) ;
_s_small_ids.release(entry.conn.small_id) ;
trace("release_start_tab",job,entry) ;
// if we have no fd, job end was invented by heartbeat, no acknowledge
@@ -462,8 +462,9 @@ namespace Backends {
dep.acquire_crc() ;
dd.crc_date(dep) ;
}
+ for( auto& [tn,td] : jrr.digest.targets ) if (td.extra_tflags[ExtraTflag::Wash]) td.date = je.start_date.d ; // adjust wash date as start_date was not available in job
::string jaf = job->ancillary_file() ;
- serialize( OFStream(jaf,::ios::app) , JobInfoEnd{jrr} ) ; // /!\ _s_starting_job ensures ancillary file is written by _s_handle_job_start before we append to it
+ serialize( OFStream(jaf,::ios::app) , JobInfoEnd{jrr} ) ; // /!\ _s_starting_job ensures ancillary file is written by _s_handle_job_start before we append to it
job->end_exec() ;
je.end_date = file_date(jaf) ;
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
diff --git a/src/lmakeserver/backends/generic.hh b/src/lmakeserver/backends/generic.hh
index 829627eb..9e9a0cd6 100644
--- a/src/lmakeserver/backends/generic.hh
+++ b/src/lmakeserver/backends/generic.hh
@@ -79,12 +79,12 @@ namespace std {
namespace Backends {
- template static inline I from_string_rsrc( ::string const& k , ::string const& v ) {
+ template I from_string_rsrc( ::string const& k , ::string const& v ) {
if ( k=="mem" || k=="tmp" ) return from_string_with_units<'M',I>(v) ;
else return from_string_with_units< I>(v) ;
}
- template static inline ::string to_string_rsrc( ::string const& k , I v ) {
+ template ::string to_string_rsrc( ::string const& k , I v ) {
if ( k=="mem" || k=="tmp" ) return to_string_with_units<'M'>(v) ;
else return to_string_with_units (v) ;
}
diff --git a/src/lmakeserver/backends/slurm.cc b/src/lmakeserver/backends/slurm.cc
index f3b3b868..fe6b639e 100644
--- a/src/lmakeserver/backends/slurm.cc
+++ b/src/lmakeserver/backends/slurm.cc
@@ -299,7 +299,7 @@ namespace Backends::Slurm {
return os <<')' ;
}
- static inline void _sort_entry(::string& s) {
+ static void _sort_entry(::string& s) {
if (s.find(',')==Npos) return ;
::vector_s v = split(s,',') ;
SWEAR(v.size()>1) ;
@@ -393,7 +393,7 @@ namespace Backends::Slurm {
}
static constexpr char LibSlurm[] = "libslurm.so" ;
- template static inline void _load_func( void* handler , T*& dst , const char* name ) {
+ template void _load_func( void* handler , T*& dst , const char* name ) {
dst = reinterpret_cast(::dlsym(handler,name)) ;
if (!dst) throw to_string("cannot find ",name," in ",LibSlurm) ;
}
@@ -418,7 +418,7 @@ namespace Backends::Slurm {
trace("done") ;
}
- static inline ::string slurm_err() {
+ static ::string slurm_err() {
return SlurmApi::strerror(errno) ;
}
@@ -549,9 +549,9 @@ namespace Backends::Slurm {
return { {} , Maybe|completed } ;
}
- static inline ::string _get_log_dir (JobIdx job) { return Job(job)->ancillary_file(AncillaryTag::Backend) ; }
- static inline ::string _get_stderr_path(JobIdx job) { return _get_log_dir(job) + "/stderr" ; }
- static inline ::string _get_stdout_path(JobIdx job) { return _get_log_dir(job) + "/stdout" ; }
+ static ::string _get_log_dir (JobIdx job) { return Job(job)->ancillary_file(AncillaryTag::Backend) ; }
+ static ::string _get_stderr_path(JobIdx job) { return _get_log_dir(job) + "/stderr" ; }
+ static ::string _get_stdout_path(JobIdx job) { return _get_log_dir(job) + "/stdout" ; }
::string read_stderr(JobIdx job) {
Trace trace(Channel::Backend,"Slurm::read_stderr",job) ;
@@ -565,7 +565,7 @@ namespace Backends::Slurm {
}
}
- static inline ::string _cmd_to_string(::vector_s const& cmd_line) {
+ static ::string _cmd_to_string(::vector_s const& cmd_line) {
::string res = "#!/bin/sh" ;
char sep = '\n' ;
for ( ::string const& s : cmd_line ) { append_to_string(res,sep,s) ; sep = ' ' ; }
diff --git a/src/lmakeserver/caches/dir_cache.cc b/src/lmakeserver/caches/dir_cache.cc
index 7e0ddd30..b6f35f92 100644
--- a/src/lmakeserver/caches/dir_cache.cc
+++ b/src/lmakeserver/caches/dir_cache.cc
@@ -93,7 +93,7 @@ namespace Caches {
append_to_string(res,"rule-",::string(rule->cmd_crc)) ;
return res ;
}
- static inline ::string _unique_name( Job job , ::string const& repo ) { return to_string(_unique_name(job),'/',repo) ; }
+ static ::string _unique_name( Job job , ::string const& repo ) { return to_string(_unique_name(job),'/',repo) ; }
// END_OF_VERSIONING
void DirCache::_mk_room( Sz old_sz , Sz new_sz ) {
@@ -159,9 +159,8 @@ namespace Caches {
break ;
DF}
}
- static inline void _copy( ::string const& src_file , Fd dst_at , ::string const& dst_file , bool ud , bool ro ) { _copy( Fd::Cwd , src_file , dst_at , dst_file , ud , ro ) ; }
- static inline void _copy( Fd src_at , ::string const& src_file , ::string const& dst_file , bool ud , bool ro ) { _copy( src_at , src_file , Fd::Cwd , dst_file , ud , ro ) ; }
- static inline void _copy( ::string const& src_file , ::string const& dst_file , bool ud , bool ro ) { _copy( Fd::Cwd , src_file , Fd::Cwd , dst_file , ud , ro ) ; }
+ static void _copy( ::string const& src_file , Fd dst_at , ::string const& dst_file , bool ud , bool ro ) { _copy( Fd::Cwd , src_file , dst_at , dst_file , ud , ro ) ; }
+ static void _copy( Fd src_at , ::string const& src_file , ::string const& dst_file , bool ud , bool ro ) { _copy( src_at , src_file , Fd::Cwd , dst_file , ud , ro ) ; }
DirCache::Sz DirCache::_lru_remove(::string const& entry) {
SWEAR(entry!=Head) ;
diff --git a/src/lmakeserver/global.cc b/src/lmakeserver/global.cc
index 331dbc5e..1a082530 100644
--- a/src/lmakeserver/global.cc
+++ b/src/lmakeserver/global.cc
@@ -14,7 +14,7 @@ namespace Engine {
ThreadQueue g_engine_queue ;
- static inline ::string _audit_indent( ::string&& t , DepDepth l , char sep=0 ) {
+ static ::string _audit_indent( ::string&& t , DepDepth l , char sep=0 ) {
if (!l) {
SWEAR(!sep) ; // cannot have a sep if we have no room to put it
return ::move(t) ;
diff --git a/src/lmakeserver/global.x.hh b/src/lmakeserver/global.x.hh
index 3db3ed61..96ddffa5 100644
--- a/src/lmakeserver/global.x.hh
+++ b/src/lmakeserver/global.x.hh
@@ -223,16 +223,16 @@ namespace Engine {
// sep is put before the last indent level, useful for porcelaine output
#define ROC ReqOptions const
#define SC ::string const
- /**/ void audit( Fd out , ::ostream& log , ROC& , Color , SC& , bool as_is=false , DepDepth =0 , char sep=0 ) ;
- static inline void audit( Fd out , ROC& ro , Color c , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { static OFakeStream fs ; audit(out,fs ,ro,c ,t,a,l,sep) ; }
- static inline void audit( Fd out , ::ostream& log , ROC& ro , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { audit(out,log,ro,Color::None,t,a,l,sep) ; }
- static inline void audit( Fd out , ROC& ro , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { static OFakeStream fs ; audit(out,fs ,ro,Color::None,t,a,l,sep) ; }
+ /**/ void audit( Fd out , ::ostream& log , ROC& , Color , SC& , bool as_is=false , DepDepth =0 , char sep=0 ) ;
+ inline void audit( Fd out , ROC& ro , Color c , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { static OFakeStream fs ; audit(out,fs ,ro,c ,t,a,l,sep) ; }
+ inline void audit( Fd out , ::ostream& log , ROC& ro , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { audit(out,log,ro,Color::None,t,a,l,sep) ; }
+ inline void audit( Fd out , ROC& ro , SC& t , bool a =false , DepDepth l=0 , char sep=0 ) { static OFakeStream fs ; audit(out,fs ,ro,Color::None,t,a,l,sep) ; }
#undef SC
#undef ROC
- template static inline ::string title ( ReqOptions const& , A&&... ) ;
- /**/ static inline ::string color_pfx( ReqOptions const& , Color ) ;
- /**/ static inline ::string color_sfx( ReqOptions const& , Color ) ;
+ template ::string title ( ReqOptions const& , A&&... ) ;
+ inline ::string color_pfx( ReqOptions const& , Color ) ;
+ inline ::string color_sfx( ReqOptions const& , Color ) ;
}
@@ -352,24 +352,24 @@ namespace Engine {
namespace Engine {
- static inline ::string reason_str(JobReason const& reason) {
+ inline ::string reason_str(JobReason const& reason) {
::string res = reason.msg() ;
if (reason.node) append_to_string( res ," : ", Disk::mk_file(Node(reason.node)->name()) ) ;
return res ;
}
- template static inline ::string title( ReqOptions const& ro , A&&... args ) {
+ template ::string title( ReqOptions const& ro , A&&... args ) {
if (ro.reverse_video==Maybe) return {} ;
return to_string( "\x1b]0;" , ::forward(args)... , '\a' ) ;
}
- static inline ::string color_pfx( ReqOptions const& ro , Color color ) {
+ inline ::string color_pfx( ReqOptions const& ro , Color color ) {
if ( color==Color::None || ro.reverse_video==Maybe || ro.flags[ReqFlag::Porcelaine] ) return {} ;
::array const& colors = g_config.colors[+color][ro.reverse_video==Yes] ;
return to_string( "\x1b[38;2;" , int(colors[0/*R*/]) ,';', int(colors[1/*G*/]) ,';', int(colors[2/*B*/]) , 'm' ) ;
}
- static inline ::string color_sfx(ReqOptions const& ro , Color color ) {
+ inline ::string color_sfx(ReqOptions const& ro , Color color ) {
if ( color==Color::None || ro.reverse_video==Maybe || ro.flags[ReqFlag::Porcelaine] ) return {} ;
return "\x1b[0m" ;
}
diff --git a/src/lmakeserver/job.cc b/src/lmakeserver/job.cc
index 53001676..1394d876 100644
--- a/src/lmakeserver/job.cc
+++ b/src/lmakeserver/job.cc
@@ -30,7 +30,7 @@ namespace Engine {
for( Node hd=Node(d.first)->dir() ; +hd ; hd = hd->dir() )
if (!locked_dirs.insert(hd).second) break ; // if dir contains a dep, it cannot be rmdir'ed
//
- // remove old_targets
+ // remove old targets
for( Target t : targets ) {
FileActionTag fat = {}/*garbage*/ ;
//
@@ -352,10 +352,10 @@ namespace Engine {
//
if ( !lost && status>Status::Early ) { // if early, we have not touched the targets, not even washed them, if lost, old targets are better than new ones
//
- ::uset from_here ;
+ ::uset old_targets ;
for( Node t : (*this)->targets ) if (t->has_actual_job(*this)) {
t->actual_job().clear() ; // ensure targets we no more generate do not keep pointing to us
- from_here.insert(t) ;
+ old_targets.insert(t) ;
}
//
::vector targets ; targets.reserve(digest.targets.size()) ;
@@ -372,7 +372,7 @@ namespace Engine {
//
if (+crc) {
// file dates are very fuzzy and unreliable, at least, filter out targets we generated ourselves
- if ( +start_date.d && target->date>start_date.d && !from_here.contains(target) ) { // if no start_date.d, job did not execute, it cannot generate a clash
+ if ( +start_date.d && target->date>start_date.d && !old_targets.contains(target) ) { // if no start_date.d, job did not execute, it cannot generate a clash
// /!\ This may be very annoying !
// A job was running in parallel with us and there was a clash on this target.
// There are 2 problems : for us and for them.
@@ -1032,7 +1032,7 @@ namespace Engine {
//
vmap fas = pre_actions(match).first ;
::vmap_s actions ; for( auto [t,a] : fas ) actions.emplace_back( t->name() , a ) ;
- ::pair_s dfa_msg = do_file_actions( ::move(actions) , nfs_guard , g_config.hash_algo ).second/*msg*/ ;
+ ::pair_s dfa_msg = do_file_actions( ::move(actions) , nfs_guard , g_config.hash_algo ) ;
//
if ( +dfa_msg.first || !dfa_msg.second ) {
run_status = RunStatus::Err ;
diff --git a/src/lmakeserver/job.x.hh b/src/lmakeserver/job.x.hh
index c3bb47ee..44612ab3 100644
--- a/src/lmakeserver/job.x.hh
+++ b/src/lmakeserver/job.x.hh
@@ -120,9 +120,6 @@ namespace Engine {
bool is_static_phony( ) const { return Job::side<1>() ; }
void is_static_phony(bool isp) { { if (isp) SWEAR(+*this) ; } Job::side<1>(isp) ; }
bool sure ( ) const ;
- //
- template requires( W>0 && W+LSB<=NGuardBits ) Idx side( ) const = delete ; // { return Job::side( ) ; }
- template requires( W>0 && W+LSB<=NGuardBits ) void side(Idx s) = delete ; // { Job::side(s) ; }
// services
bool produces(Node) const ;
} ;
@@ -403,7 +400,7 @@ namespace Engine {
inline bool JobTgt::produces(Node t) const {
if ((*this)->missing() ) return false ; // missing jobs produce nothing
if ((*this)->err() ) return true ; // jobs in error are deemed to produce all their potential targets
- if (sure() ) return true ; // fast path
+ if (sure() ) return true ;
if (t->has_actual_job(*this)) return t->actual_tflags()[Tflag::Target] ; // .
//
auto it = ::lower_bound( (*this)->targets , {t,{}} ) ;
@@ -444,7 +441,7 @@ namespace Engine {
_set_pressure_raw(ri,pressure) ;
}
- template inline void JobData::audit_end(A&&... args) const {
+ template void JobData::audit_end(A&&... args) const {
JobExec(idx(),New,New).audit_end(::forward(args)...) ;
}
@@ -476,7 +473,7 @@ namespace Engine {
if (&cri==&Req::s_store[+cri.req].jobs.dflt) return req_info(cri.req) ; // allocate
else return const_cast(cri) ; // already allocated, no look up
}
- inline ::vector JobData::reqs() const { return Req::reqs(*this) ; }
+ inline ::vector JobData::reqs() const { return Req::s_reqs(*this) ; }
inline bool JobData::has_req(Req r) const {
return Req::s_store[+r].jobs.contains(idx()) ;
diff --git a/src/lmakeserver/makefiles.cc b/src/lmakeserver/makefiles.cc
index 93ed0a6d..a1ad90ba 100644
--- a/src/lmakeserver/makefiles.cc
+++ b/src/lmakeserver/makefiles.cc
@@ -105,7 +105,7 @@ namespace Engine::Makefiles {
return {} ;
}
- static inline ::string _deps_file( ::string const& action , bool new_ ) {
+ static ::string _deps_file( ::string const& action , bool new_ ) {
if (new_) return to_string(PrivateAdminDir,'/',action,"_new_deps") ;
else return to_string(AdminDir ,'/',action,"_deps" ) ;
}
diff --git a/src/lmakeserver/node.cc b/src/lmakeserver/node.cc
index 86b78460..8bb2a82f 100644
--- a/src/lmakeserver/node.cc
+++ b/src/lmakeserver/node.cc
@@ -424,7 +424,7 @@ namespace Engine {
return ri.done() ;
}
- static inline bool _must_regenerate( NodeData const& nd , NodeReqInfo& ri ) {
+ static bool _must_regenerate( NodeData const& nd , NodeReqInfo& ri ) {
SWEAR(ri.done_>=ri.goal) ; // must be done to ask for regeneration
Job cj = nd.conform_job() ;
if (!cj ) return false ; // no hope to regenerate, proceed as a done target
@@ -652,7 +652,7 @@ namespace Engine {
}
}
- static inline ::pair _manual_refresh( NodeData& nd , FileInfo const& fi ) {
+ static ::pair _manual_refresh( NodeData& nd , FileInfo const& fi ) {
Manual m = nd.manual(fi) ;
if (m(cri) ; // already allocated, no look up
}
- inline ::vector NodeData::reqs() const { return Req::reqs(*this) ; }
+ inline ::vector NodeData::reqs() const { return Req::s_reqs(*this) ; }
inline bool NodeData::waiting() const {
for( Req r : reqs() ) if (c_req_info(r).waiting()) return true ;
@@ -495,7 +495,7 @@ namespace Engine {
return prio_job_tgts(prio_idx) ;
}
- template inline void NodeData::add_watcher( ReqInfo& ri , Watcher watcher , RI& wri , CoarseDelay pressure ) {
+ template void NodeData::add_watcher( ReqInfo& ri , Watcher watcher , RI& wri , CoarseDelay pressure ) {
ri.add_watcher(watcher,wri) ;
set_pressure(ri,pressure) ;
}
diff --git a/src/lmakeserver/req.x.hh b/src/lmakeserver/req.x.hh
index 0342b084..ceccf448 100644
--- a/src/lmakeserver/req.x.hh
+++ b/src/lmakeserver/req.x.hh
@@ -44,7 +44,7 @@ namespace Engine {
// init
static void s_init() {}
// statics
- template requires(IsOneOf) static ::vector reqs(T const& jn) { // sorted by start
+ template requires(IsOneOf) static ::vector s_reqs(T const& jn) { // sorted by start
::vector res ; res.reserve(s_reqs_by_start.size()) ; // pessimistic
for( Req r : s_reqs_by_start ) if (jn.has_req(r)) res.push_back(r) ;
return res ;
diff --git a/src/lmakeserver/rule.cc b/src/lmakeserver/rule.cc
index c1ae8604..994070e3 100644
--- a/src/lmakeserver/rule.cc
+++ b/src/lmakeserver/rule.cc
@@ -144,12 +144,9 @@ namespace Engine {
case Re : throw to_string("spurious { in ",str) ;
DF}
}
- static inline void _parse_py( ::string const& str , size_t* unnamed_star_idx , ParsePyFuncStem const& cb_stem ) {
+ static void _parse_py( ::string const& str , size_t* unnamed_star_idx , ParsePyFuncStem const& cb_stem ) {
_parse_py( str , unnamed_star_idx , [](::string const&)->void{} , cb_stem ) ;
}
- static inline void _parse_py( ::string const& str , size_t* unnamed_star_idx , ParsePyFuncFixed const& cb_fixed ) {
- _parse_py( str , unnamed_star_idx , cb_fixed , [](::string const&,bool,bool,::string const*)->void{} ) ;
- }
// star stems are represented by a StemMrkr followed by the stem idx
// cb is called on each stem found
@@ -174,7 +171,7 @@ namespace Engine {
return res ;
}
// provide shortcut when pos is unused
- static inline ::string _subst_target( ::string const& str , ::function const& cb , Escape escape=Escape::None , VarIdx stop_above=-1 ) {
+ static ::string _subst_target( ::string const& str , ::function const& cb , Escape escape=Escape::None , VarIdx stop_above=-1 ) {
return _subst_target( str , [&](FileNameIdx,VarIdx s)->::string { return cb(s) ; } , escape , stop_above ) ;
}
@@ -188,10 +185,6 @@ namespace Engine {
}
}
}
- // provide shortcut when pos is unused
- static inline void _parse_target( ::string const& str , ::function const& cb ) {
- _parse_target( str , [&](FileNameIdx,VarIdx s)->void { cb(s) ; } ) ;
- }
template static void _mk_flags( ::string const& key , Sequence const& py_seq , uint8_t n_skip , BitMap& flags , BitMap& extra_flags ) {
for( Object const& item : py_seq ) {
diff --git a/src/lmakeserver/rule.x.hh b/src/lmakeserver/rule.x.hh
index 09f050c8..b3f4a83e 100644
--- a/src/lmakeserver/rule.x.hh
+++ b/src/lmakeserver/rule.x.hh
@@ -121,7 +121,7 @@ namespace Engine {
if (py_dct.contains(key)) return acquire( dst , &py_dct[key] , min , max ) ;
else return false ;
}
- static inline void acquire_env( ::vmap_ss& dst , Py::Dict const& py_dct , ::string const& key ) { acquire_from_dct<::vmap_ss,true/*Env*/>(dst,py_dct,key) ; }
+ inline void acquire_env( ::vmap_ss& dst , Py::Dict const& py_dct , ::string const& key ) { acquire_from_dct<::vmap_ss,true/*Env*/>(dst,py_dct,key) ; }
//
::string subst_fstr( ::string const& fstr , ::umap_s const& var_idxs , VarIdx& n_unnamed ) ;
} ;
diff --git a/src/lmakeserver/store.x.hh b/src/lmakeserver/store.x.hh
index 4eb7b8dd..cd93693c 100644
--- a/src/lmakeserver/store.x.hh
+++ b/src/lmakeserver/store.x.hh
@@ -369,13 +369,13 @@ namespace Engine::Persistent {
for( RuleTgt rt : view() ) if (rt.old()) { pop() ; break ; }
}
- template static inline void _s_update( Disk& disk , ::uset- & mem , bool add , ::vector
- const& items ) {
+ template void _s_update( Disk& disk , ::uset
- & mem , bool add , ::vector
- const& items ) {
bool modified = false ;
if (add ) for( Item i : items ) modified |= mem.insert(i).second ;
else if (+mem) for( Item i : items ) modified |= mem.erase (i) ; // fast path : no need to update mem if it is already empty
if (modified) disk.assign(mk_vector(mem)) ;
}
- template inline void _s_update( Disk& disk , bool add , ::vector
- const& items ) {
+ template void _s_update( Disk& disk , bool add , ::vector
- const& items ) {
::uset
- mem = mk_uset
- (disk) ;
_s_update(disk,mem,add,items) ;
}
@@ -391,10 +391,10 @@ namespace Engine::Persistent {
//
inline Job JobBase::s_idx(JobData const& jd) { return _job_file.idx(jd) ; }
// cxtors & casts
- template inline JobBase::JobBase( NewType , A&&... args ) { // 1st arg is only used to disambiguate
+ template JobBase::JobBase( NewType , A&&... args ) { // 1st arg is only used to disambiguate
*this = _job_file.emplace( Name() , ::forward(args)... ) ;
}
- template inline JobBase::JobBase( ::pair_ss const& name_sfx , bool new_ , A&&... args ) { // jobs are only created in main thread, so no locking is necessary
+ template JobBase::JobBase( ::pair_ss const& name_sfx , bool new_ , A&&... args ) { // jobs are only created in main thread, so no locking is necessary
Name name_ = _name_file.insert(name_sfx.first,name_sfx.second) ;
*this = _name_file.c_at(+name_).job() ;
if (+*this) {
diff --git a/src/process.hh b/src/process.hh
index 7025f583..e4abec81 100644
--- a/src/process.hh
+++ b/src/process.hh
@@ -37,7 +37,7 @@ struct Pipe {
Fd write ; // write side of the pipe
} ;
-static inline bool/*all_done*/ set_sig( ::vector const& sigs , bool block ) {
+inline bool/*all_done*/ set_sig( ::vector const& sigs , bool block ) {
sigset_t new_mask ;
sigset_t old_mask ;
::sigemptyset(&new_mask) ;
@@ -48,7 +48,7 @@ static inline bool/*all_done*/ set_sig( ::vector const& sigs , bool block )
for( int s : sigs ) if (::sigismember(&old_mask,s)==block) return false ;
return true ;
}
-static inline Fd open_sig_fd(::vector const& sigs) {
+inline Fd open_sig_fd(::vector const& sigs) {
swear_prod(set_sig(sigs,true/*block*/),"some of signals",sigs,"are already blocked") ;
//
sigset_t mask ;
@@ -57,12 +57,12 @@ static inline Fd open_sig_fd(::vector const& sigs) {
//
return ::signalfd( -1 , &mask , SFD_CLOEXEC ) ;
}
-static inline void close_sig_fd( Fd fd , ::vector const& sigs ) {
+inline void close_sig_fd( Fd fd , ::vector const& sigs ) {
fd.close() ;
set_sig(sigs,false/*block*/) ;
}
-static inline bool is_sig_sync(int sig) {
+inline bool is_sig_sync(int sig) {
switch (sig) {
case SIGILL :
case SIGTRAP :
@@ -74,7 +74,7 @@ static inline bool is_sig_sync(int sig) {
}
}
-static inline ::string wstatus_str(int wstatus) {
+inline ::string wstatus_str(int wstatus) {
if (WIFEXITED (wstatus)) return WEXITSTATUS(wstatus) ? to_string("exit ",WEXITSTATUS(wstatus)) : "ok"s ;
if (WIFSIGNALED(wstatus)) return to_string("signal ",WTERMSIG(wstatus),'-',::strsignal(WTERMSIG(wstatus))) ;
else return "??" ;
diff --git a/src/py.hh b/src/py.hh
index 980719d2..8a5d56bf 100644
--- a/src/py.hh
+++ b/src/py.hh
@@ -50,14 +50,14 @@ namespace Py {
// functions
//
- template static inline T const* _chk (T const * o) { if ( o && !o->qualify() ) throw to_string("not a ",o->type_name()) ; return o ; }
- template static inline T * _chk (T * o) { if ( o && !o->qualify() ) throw to_string("not a ",o->type_name()) ; return o ; }
- template static inline T * from_py(PyObject* o) { T* res = static_cast(o) ; _chk(res) ; return res ; }
+ template T const* _chk (T const * o) { if ( o && !o->qualify() ) throw to_string("not a ",o->type_name()) ; return o ; }
+ template T * _chk (T * o) { if ( o && !o->qualify() ) throw to_string("not a ",o->type_name()) ; return o ; }
+ template T * from_py(PyObject* o) { T* res = static_cast(o) ; _chk(res) ; return res ; }
- static inline void py_err_clear () { PyErr_Clear () ; }
- static inline bool py_err_occurred() { return PyErr_Occurred() ; }
+ inline void py_err_clear () { PyErr_Clear () ; }
+ inline bool py_err_occurred() { return PyErr_Occurred() ; }
//
- template static inline T& py_get_sys(::string const& name) {
+ template T& py_get_sys(::string const& name) {
PyObject* v = PySys_GetObject(const_cast(name.c_str())) ;
if (!v) throw to_string("cannot find sys.",name) ;
return *from_py(v) ;
@@ -67,7 +67,7 @@ namespace Py {
::string py_err_str_clear() ; // like PyErr_Print, but return text instead of printing it (Python API provides no means to do this !)
//
- static inline nullptr_t py_err_set( Exception e , ::string const& txt ) {
+ inline nullptr_t py_err_set( Exception e , ::string const& txt ) {
static PyObject* s_exc_tab[] = {
PyExc_RuntimeError // RuntimeErr
, PyExc_TypeError // TypeErr
@@ -574,7 +574,7 @@ namespace Py {
// Object
//
- template inline Ptr Object::get_attr(::string const& attr) const {
+ template Ptr Object::get_attr(::string const& attr) const {
PyObject* val = PyObject_GetAttrString(to_py(),attr.c_str()) ;
if (!val) throw py_err_str_clear() ;
return val ;
diff --git a/src/rpc_client.hh b/src/rpc_client.hh
index fcad3336..b2c793cd 100644
--- a/src/rpc_client.hh
+++ b/src/rpc_client.hh
@@ -41,7 +41,7 @@ ENUM( ReqKey // PER_CMD : add key as necessary (you may share with other comma
, Stdout // if proc==Show
, Targets // if proc==Show
)
-static inline bool is_mark_glb(ReqKey key) {
+inline bool is_mark_glb(ReqKey key) {
switch (key) {
case ReqKey::Clear :
case ReqKey::List : return true ;
diff --git a/src/rpc_job.cc b/src/rpc_job.cc
index 9b01d4ea..6e20b379 100644
--- a/src/rpc_job.cc
+++ b/src/rpc_job.cc
@@ -21,11 +21,10 @@ ::ostream& operator<<( ::ostream& os , FileAction const& fa ) {
return os <<')' ;
}
-::pair/*msg*/> do_file_actions( ::vmap_s&& pre_actions , NfsGuard& nfs_guard , Algo ha ) {
- ::uset_s keep_dirs ;
- ::vector_s unlnks ;
- ::string msg ;
- bool ok = true ;
+::pair_s do_file_actions( ::vector_s* unlnks , ::vmap_s&& pre_actions , NfsGuard& nfs_guard , Algo ha ) {
+ ::uset_s keep_dirs ;
+ ::string msg ;
+ bool ok = true ;
//
for( auto const& [f,a] : pre_actions ) { // pre_actions are adequately sorted
SWEAR(+f) ; // acting on root dir is non-sense
@@ -43,10 +42,10 @@ ::pair/*msg*/> do_file_actions( ::vmap_spush_back(f) ;
+ ok &= done ;
} break ;
case FileActionTag::Rmdir :
if (!keep_dirs.contains(f))
@@ -55,7 +54,7 @@ ::pair/*msg*/> do_file_actions( ::vmap_s/*msg*/> do_file_actions( ::vmap_s&& pre_actions , Disk::NfsGuard& nfs_guard , Algo ) ;
+/**/ ::pair_s do_file_actions( ::vector_s* unlnks/*out*/ , ::vmap_s&& , Disk::NfsGuard& , Algo ) ;
+inline ::pair_s do_file_actions( ::vector_s& unlnks/*out*/ , ::vmap_s&& pa , Disk::NfsGuard& ng , Algo a ) { return do_file_actions(&unlnks,::move(pa),ng,a) ; }
+inline ::pair_s do_file_actions( ::vmap_s&& pa , Disk::NfsGuard& ng , Algo a ) { return do_file_actions(nullptr,::move(pa),ng,a) ; }
ENUM_2( Dflag // flags for deps
, NRule = Required // number of Dflag's allowed in rule definition
@@ -99,7 +101,7 @@ static constexpr char TflagChars[] = {
} ;
static_assert(::size(TflagChars)==N) ;
using Tflags = BitMap ;
-static inline bool static_phony(Tflags tf) {
+inline bool static_phony(Tflags tf) {
return tf[Tflag::Target] && (tf[Tflag::Static]||tf[Tflag::Phony]) ;
}
@@ -109,12 +111,14 @@ ENUM_1( ExtraTflag
, Ignore
, SourceOk // ok to overwrite source files
, Allow // writing to this target is allowed (for use in clmake.target and ltarget)
+, Wash // target was unlinked when washing before job execution
)
static constexpr char ExtraTflagChars[] = {
0 // Top
, 'I' // Ignore
, 's' // SourceOk
, 'a' // Allow
+, 0 // Wash
} ;
static_assert(::size(ExtraTflagChars)==N) ;
using ExtraTflags = BitMap ;
@@ -250,8 +254,8 @@ ENUM_3( Status // result of job execution
, Ok // job execution ended successfully
, Err // job execution ended in error
)
-static inline bool is_lost(Status s) { return s<=Status::LateLostErr && s>=Status::EarlyLost ; }
-static inline Bool3 is_ok (Status s) {
+inline bool is_lost(Status s) { return s<=Status::LateLostErr && s>=Status::EarlyLost ; }
+inline Bool3 is_ok (Status s) {
static constexpr Bool3 IsOkTab[] = {
Maybe // New
, Maybe // EarlyChkDeps
@@ -269,7 +273,7 @@ static inline Bool3 is_ok (Status s) {
static_assert(sizeof(IsOkTab)==N) ;
return IsOkTab[+s] ;
}
-static inline Status mk_err(Status s) {
+inline Status mk_err(Status s) {
switch (s) {
case Status::New : return Status::EarlyErr ;
case Status::EarlyLost : return Status::EarlyLostErr ;
@@ -277,7 +281,7 @@ static inline Status mk_err(Status s) {
case Status::Ok : return Status::Err ;
DF}
}
-static inline JobReasonTag mk_reason(Status s) {
+inline JobReasonTag mk_reason(Status s) {
static constexpr JobReasonTag ReasonTab[] = {
JobReasonTag::New // New
, JobReasonTag::ChkDeps // EarlyChkDeps
diff --git a/src/serialize.hh b/src/serialize.hh
index 4b089e69..03e30f34 100644
--- a/src/serialize.hh
+++ b/src/serialize.hh
@@ -17,24 +17,24 @@ template concept HasSerdeser = !HasSerdes && requires( T x , ::istre
template concept Serializable = HasSerdes || HasSerdeser ;
// serdes method should be const when serializing but is not because C++ does not let constness be template arg dependent
-/**/ static inline void serdes( ::ostream& ) { }
-/**/ static inline void serdes( ::istream& ) { }
-template static inline void serdes( ::ostream& os , T const& x ) { const_cast(x).serdes(os) ; }
-template static inline void serdes( ::istream& is , T & x ) { x .serdes(is) ; }
-template static inline void serdes( ::ostream& os , T const& x ) { Serdeser::s_serdes(os,x) ; }
-template static inline void serdes( ::istream& is , T & x ) { Serdeser::s_serdes(is,x) ; }
-template< Serializable T1 , Serializable T2 , Serializable... Ts > static inline void serdes( ::ostream& os , T1 const& x1 , T2 const& x2 , Ts const&... xs ) { serdes(os,x1) ; serdes(os,x2,xs...) ; }
-template< Serializable T1 , Serializable T2 , Serializable... Ts > static inline void serdes( ::istream& is , T1 & x1 , T2 & x2 , Ts &... xs ) { serdes(is,x1) ; serdes(is,x2,xs...) ; }
+inline void serdes( ::ostream& ) { }
+inline void serdes( ::istream& ) { }
+template void serdes( ::ostream& os , T const& x ) { const_cast(x).serdes(os) ; }
+template void serdes( ::istream& is , T & x ) { x .serdes(is) ; }
+template void serdes( ::ostream& os , T const& x ) { Serdeser::s_serdes(os,x) ; }
+template void serdes( ::istream& is , T & x ) { Serdeser::s_serdes(is,x) ; }
+template< Serializable T1 , Serializable T2 , Serializable... Ts > void serdes( ::ostream& os , T1 const& x1 , T2 const& x2 , Ts const&... xs ) { serdes(os,x1) ; serdes(os,x2,xs...) ; }
+template< Serializable T1 , Serializable T2 , Serializable... Ts > void serdes( ::istream& is , T1 & x1 , T2 & x2 , Ts &... xs ) { serdes(is,x1) ; serdes(is,x2,xs...) ; }
//
-template static inline void serialize ( ::ostream& os , T const& x ) { serdes(os ,x ) ; os.flush() ; }
-template static inline ::string serialize ( T const& x ) { OStringStream res ; serdes(res,x ) ; return res.str() ; }
-template static inline void deserialize( ::istream& is , T & x ) { serdes(is ,x ) ; }
-template static inline T deserialize( ::istream& is ) { T res ; serdes(is ,res) ; return res ; }
+template void serialize ( ::ostream& os , T const& x ) { serdes(os ,x ) ; os.flush() ; }
+template ::string serialize ( T const& x ) { OStringStream res ; serdes(res,x ) ; return res.str() ; }
+template void deserialize( ::istream& is , T & x ) { serdes(is ,x ) ; }
+template T deserialize( ::istream& is ) { T res ; serdes(is ,res) ; return res ; }
//
-template static inline void serialize ( ::ostream&& os , T const& x ) { serialize (os ,x) ; }
-template static inline void deserialize( ::istream&& is , T & x ) { deserialize(is ,x) ; }
-template static inline T deserialize( ::istream&& is ) { return deserialize(is ) ; }
-template static inline T deserialize( ::string const& s ) { return deserialize(IStringStream(s) ) ; }
+template void serialize ( ::ostream&& os , T const& x ) { serialize (os ,x) ; }
+template void deserialize( ::istream&& is , T & x ) { deserialize(is ,x) ; }
+template T deserialize( ::istream&& is ) { return deserialize(is ) ; }
+template T deserialize( ::string const& s ) { return deserialize(IStringStream(s) ) ; }
// make objects hashable as soon as they define serdes(::ostream) && serdes(::istream)
// as soon as a class T is serializable, you can simply use ::set, ::uset, ::map or ::umap
diff --git a/src/store/prefix.hh b/src/store/prefix.hh
index e47f7f41..5dc3a6a5 100644
--- a/src/store/prefix.hh
+++ b/src/store/prefix.hh
@@ -33,16 +33,16 @@ namespace Store {
template using VecStr = ::conditional_t
,Vec> ;
template using ItemChar = ::conditional_t