2010-02-28 09:34:43 +03:00
# waf build tool for building IDL files with pidl
2015-10-27 22:46:46 +03:00
import os
2018-01-31 12:48:43 +03:00
from waflib import Build , Utils
from waflib . TaskGen import feature , before
2015-10-27 22:46:46 +03:00
from samba_utils import SET_TARGET_TYPE , TO_LIST , LOCAL_CACHE
2010-02-28 09:34:43 +03:00
2010-03-17 14:15:46 +03:00
def SAMBA_PIDL ( bld , pname , source ,
options = ' ' ,
output_dir = ' . ' ,
2010-05-05 06:40:20 +04:00
generate_tables = True ) :
2010-02-28 09:34:43 +03:00
''' Build a IDL file using pidl.
2023-11-09 03:17:24 +03:00
This will produce up to 17 output files depending on the options used '''
2010-02-28 09:34:43 +03:00
2023-08-29 11:47:58 +03:00
bname = source [ 0 : - 4 ] # strip off the .idl suffix
2010-05-05 06:40:20 +04:00
bname = os . path . basename ( bname )
2010-03-17 13:48:26 +03:00
name = " %s _ %s " % ( pname , bname . upper ( ) )
2010-02-28 09:34:43 +03:00
if not SET_TARGET_TYPE ( bld , name , ' PIDL ' ) :
return
bld . SET_BUILD_GROUP ( ' build_source ' )
2010-03-17 13:46:38 +03:00
2010-03-17 13:48:26 +03:00
# the output files depend on the options used. Use this dictionary
# to map between the options and the resulting file names
options_map = { ' --header ' : ' %s .h ' ,
' --ndr-parser ' : ' ndr_ %s .c ndr_ %s .h ' ,
' --samba3-ndr-server ' : ' srv_ %s .c srv_ %s .h ' ,
' --samba3-ndr-client ' : ' cli_ %s .c cli_ %s .h ' ,
' --server ' : ' ndr_ %s _s.c ' ,
2019-01-15 19:55:07 +03:00
' --server-compat ' : ' ndr_ %s _scompat.c ndr_ %s _scompat.h ' ,
2010-03-17 13:48:26 +03:00
' --client ' : ' ndr_ %s _c.c ndr_ %s _c.h ' ,
' --python ' : ' py_ %s .c ' ,
' --tdr-parser ' : ' tdr_ %s .c tdr_ %s .h ' ,
2012-02-09 16:08:31 +04:00
' --dcom-proxy ' : ' %s _p.c ' ,
' --com-header ' : ' com_ %s .h '
2010-03-17 13:48:26 +03:00
}
table_header_idx = None
2010-03-17 13:46:38 +03:00
out_files = [ ]
2010-03-20 08:27:48 +03:00
options_list = TO_LIST ( options )
2010-03-17 13:46:38 +03:00
2010-03-17 13:48:26 +03:00
for o in options_list :
if o in options_map :
2010-03-20 08:27:48 +03:00
ofiles = TO_LIST ( options_map [ o ] )
2010-03-17 13:48:26 +03:00
for f in ofiles :
out_files . append ( os . path . join ( output_dir , f % bname ) )
if f == ' ndr_ %s .h ' :
# remember this one for the tables generation
table_header_idx = len ( out_files ) - 1
2010-03-17 13:46:38 +03:00
2010-03-17 12:12:16 +03:00
# depend on the full pidl sources
source = TO_LIST ( source )
2010-03-17 01:55:41 +03:00
try :
pidl_src_nodes = bld . pidl_files_cache
except AttributeError :
2010-04-02 12:57:32 +04:00
bld . pidl_files_cache = bld . srcnode . ant_glob ( ' pidl/lib/Parse/**/*.pm ' , flat = False )
2010-03-27 08:46:33 +03:00
bld . pidl_files_cache . extend ( bld . srcnode . ant_glob ( ' pidl ' , flat = False ) )
pidl_src_nodes = bld . pidl_files_cache
2010-03-17 13:53:29 +03:00
2010-03-17 13:48:26 +03:00
# the cd .. is needed because pidl currently is sensitive to the directory it is run in
2010-12-10 02:36:24 +03:00
cpp = " "
cc = " "
2013-03-22 06:47:46 +04:00
if bld . CONFIG_SET ( " CPP " ) and bld . CONFIG_GET ( " CPP " ) != " " :
2010-12-10 10:06:44 +03:00
if isinstance ( bld . CONFIG_GET ( " CPP " ) , list ) :
2013-03-22 06:06:43 +04:00
cpp = ' CPP= " %s " ' % " " . join ( bld . CONFIG_GET ( " CPP " ) )
2010-12-10 10:06:44 +03:00
else :
2011-01-19 18:53:39 +03:00
cpp = ' CPP= " %s " ' % bld . CONFIG_GET ( " CPP " )
2010-12-10 10:06:44 +03:00
2010-12-10 23:47:54 +03:00
if cpp == " CPP=xlc_r " :
2010-12-10 14:37:00 +03:00
cpp = " "
pidl: optionally annotate output for debug purposes
It can sometimes be hard to tell which bit of pidl generated which bit
of C. This commit wants to help.
If the PIDL_DEVELOPER environment variable is set (via waf
--pidl-developer or some other means), pidl will annotate *most* C
indicating which lines were generated by which bits of pidl. It looks
something like this:
_PUBLIC_ enum ndr_err_code ndr_push_auth_session_info(struct ndr_push *ndr, int ndr_flags, const struct auth_session_info *r)
{ //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseTypePushFunction lib/Parse/Pidl/Samba4/NDR/Parser.pm:3079
NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseStructPush lib/Parse/Pidl/Samba4/NDR/Parser.pm:604
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 5)); //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseStructPushPrimitives lib/Parse/Pidl/Samba4/NDR/Parser.pm:1448
NDR_CHECK(ndr_push_unique_ptr(ndr, r->security_token)); //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParsePtrPush lib/Parse/Pidl/Samba4/NDR/Parser.pm:604
NDR_CHECK(ndr_push_unique_ptr(ndr, r->unix_token));
NDR_CHECK(ndr_push_unique_ptr(ndr, r->info));
NDR_CHECK(ndr_push_unique_ptr(ndr, r->unix_info));
NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, 0));
/* [ignore] 'torture' */ //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseElementPushLevel lib/Parse/Pidl/Samba4/NDR/Parser.pm:729
NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->session_key)); //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseDataPush lib/Parse/Pidl/Samba4/NDR/Parser.pm:604
NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, 0)); //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParsePtrPush lib/Parse/Pidl/Samba4/NDR/Parser.pm:604
/* [ignore] 'credentials' */ //:PIDL: Parse::Pidl::Samba4::NDR::Parser::ParseElementPushLevel lib/Parse/Pidl/Samba4/NDR/Parser.pm:729
The comments starting with '//:PIDL:' have the function name, the filename,
and line number. The comment follows the ordinary output, and uses the '//'
style so as not to interfere with multiline /* */ comments if they happen
to exist.
A '//:PIDL:' comment is added whenever the pidl function or indentation
level changes, and very occasionally at other places if pidl runs for a
while without either of these things happening.
This does not affect pidl parsers that do not inherit from Parse::Pidl::Base,
and is careful to have no performance impact on non-debug generation.
This may help with semi-automated flow analysis.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2019-11-30 06:22:22 +03:00
if bld . env [ ' PIDL_DEVELOPER_MODE ' ] :
pidl_dev = ' PIDL_DEVELOPER=1 '
else :
pidl_dev = ' '
2010-12-10 14:37:00 +03:00
2010-12-10 02:36:24 +03:00
if bld . CONFIG_SET ( " CC " ) :
if isinstance ( bld . CONFIG_GET ( " CC " ) , list ) :
2013-03-22 06:06:43 +04:00
cc = ' CC= " %s " ' % " " . join ( bld . CONFIG_GET ( " CC " ) )
2010-12-10 02:36:24 +03:00
else :
2011-01-19 18:53:39 +03:00
cc = ' CC= " %s " ' % bld . CONFIG_GET ( " CC " )
2010-12-10 10:06:44 +03:00
2024-05-28 03:17:06 +03:00
t = bld ( rule = ( ' cd $ {PIDL_LAUNCH_DIR} && PERL_HASH_SEED=0 %s %s %s $ {PERL} '
' $ {PIDL} --quiet $ {OPTIONS} --outputdir $ {OUTPUTDIR} -- " $ {IDLSRC} " ' %
( pidl_dev , cpp , cc ) ) ,
2010-03-17 14:17:15 +03:00
ext_out = ' .c ' ,
2016-03-26 15:18:07 +03:00
before = ' c ' ,
2015-03-07 17:31:18 +03:00
update_outputs = True ,
2010-03-17 14:17:15 +03:00
shell = True ,
source = source ,
target = out_files ,
name = name ,
samba_type = ' PIDL ' )
2010-03-17 13:53:29 +03:00
2010-03-17 01:55:41 +03:00
2018-11-13 19:04:39 +03:00
t . env . PIDL_LAUNCH_DIR = bld . srcnode . path_from ( bld . bldnode )
2018-11-15 14:51:37 +03:00
pnode = bld . srcnode . find_resource ( ' pidl/pidl ' )
t . env . PIDL = pnode . path_from ( bld . srcnode )
2010-03-20 08:27:48 +03:00
t . env . OPTIONS = TO_LIST ( options )
2018-11-15 14:51:37 +03:00
snode = t . path . find_resource ( source [ 0 ] )
t . env . IDLSRC = snode . path_from ( bld . srcnode )
t . env . OUTPUTDIR = bld . bldnode . path_from ( bld . srcnode ) + ' / ' + bld . path . find_dir ( output_dir ) . path_from ( bld . srcnode )
2010-03-17 13:53:29 +03:00
2018-11-23 16:06:52 +03:00
bld . add_manual_dependency ( snode , pidl_src_nodes )
2010-05-05 06:40:20 +04:00
if generate_tables and table_header_idx is not None :
2010-03-17 13:48:26 +03:00
pidl_headers = LOCAL_CACHE ( bld , ' PIDL_HEADERS ' )
pidl_headers [ name ] = [ bld . path . find_or_declare ( out_files [ table_header_idx ] ) ]
2010-03-17 13:53:29 +03:00
2018-01-31 12:48:43 +03:00
t . more_includes = ' # ' + bld . path . path_from ( bld . srcnode )
2010-03-17 13:48:26 +03:00
Build . BuildContext . SAMBA_PIDL = SAMBA_PIDL
2010-02-28 09:34:43 +03:00
2010-03-17 14:15:46 +03:00
def SAMBA_PIDL_LIST ( bld , name , source ,
options = ' ' ,
output_dir = ' . ' ,
2019-10-31 06:28:28 +03:00
generate_tables = True ,
generate_fuzzers = True ) :
2010-03-17 13:48:26 +03:00
''' A wrapper for building a set of IDL files '''
2010-03-20 08:27:48 +03:00
for p in TO_LIST ( source ) :
2012-10-28 12:38:10 +04:00
bld . SAMBA_PIDL ( name , p , options = options , output_dir = output_dir , generate_tables = generate_tables )
2019-10-31 06:28:28 +03:00
# Some IDL files don't exactly match between name and
# "interface" so we need a way to skip those, while other IDL
# files have the table generation skipped entirely, on which
# the fuzzers rely
if generate_tables and generate_fuzzers :
interface = p [ 0 : - 4 ] # strip off the .idl suffix
2019-12-11 03:03:43 +03:00
bld . SAMBA_NDR_FUZZ ( interface ,
auto_deps = True ,
fuzz_type = " TYPE_STRUCT " )
# Only generate the TYPE_STRUCT fuzzer if this isn't
# really DCE/RPC
if ' --client ' in options :
bld . SAMBA_NDR_FUZZ ( interface ,
auto_deps = True ,
fuzz_type = " TYPE_IN " )
bld . SAMBA_NDR_FUZZ ( interface ,
auto_deps = True ,
fuzz_type = " TYPE_OUT " )
2010-03-17 13:46:38 +03:00
Build . BuildContext . SAMBA_PIDL_LIST = SAMBA_PIDL_LIST
#################################################################
# the rule for generating the NDR tables
@feature ( ' collect ' )
@before ( ' exec_rule ' )
def collect ( self ) :
2010-03-17 13:48:26 +03:00
pidl_headers = LOCAL_CACHE ( self . bld , ' PIDL_HEADERS ' )
2018-11-15 15:37:58 +03:00
# The first source is tables.pl itself
2016-03-26 15:18:07 +03:00
self . source = Utils . to_list ( self . source )
2010-03-17 13:48:26 +03:00
for ( name , hd ) in pidl_headers . items ( ) :
2015-06-26 23:32:43 +03:00
y = self . bld . get_tgen_by_name ( name )
2010-03-17 13:48:26 +03:00
self . bld . ASSERT ( y is not None , ' Failed to find PIDL header %s ' % name )
2010-03-17 13:46:38 +03:00
y . post ( )
for node in hd :
2010-05-05 06:40:20 +04:00
self . bld . ASSERT ( node is not None , ' Got None as build node generating PIDL table for %s ' % name )
2016-03-26 15:18:07 +03:00
self . source . append ( node )
2010-03-17 13:46:38 +03:00
2010-03-17 13:48:26 +03:00
2010-03-17 13:46:38 +03:00
def SAMBA_PIDL_TABLES ( bld , name , target ) :
2010-03-28 15:01:04 +04:00
''' generate the pidl NDR tables file '''
2010-03-28 03:00:53 +04:00
bld . SET_BUILD_GROUP ( ' main ' )
2010-03-17 13:46:38 +03:00
t = bld (
features = ' collect ' ,
2018-11-15 15:37:58 +03:00
rule = ' $ {PERL} $ {SRC} > $ {TGT} ' ,
2010-03-17 13:48:26 +03:00
ext_out = ' .c ' ,
2016-03-26 15:18:07 +03:00
before = ' c ' ,
2015-03-07 17:31:18 +03:00
update_outputs = True ,
2010-03-17 13:48:26 +03:00
shell = True ,
source = ' ../../librpc/tables.pl ' ,
target = target ,
name = name )
2010-04-08 15:46:20 +04:00
t . env . LIBRPC = os . path . join ( bld . srcnode . abspath ( ) , ' librpc ' )
2010-03-17 13:46:38 +03:00
Build . BuildContext . SAMBA_PIDL_TABLES = SAMBA_PIDL_TABLES