Split CP up into components that can be called individually

First tests are working.  Changing a source file and header works
as before.  Adding library dependencies in either of these files
causes the makefile pieces to be redone.  Only tested in the ball
sim so far.

refs #86
This commit is contained in:
Alex Lin 2015-07-20 16:22:34 -05:00
parent e1c1bbaccf
commit dfa961808b
5 changed files with 100 additions and 213 deletions

View File

@ -10,7 +10,6 @@ use lib "$RealBin/pm" ;
use File::Basename ;
use Cwd 'abs_path' ;
use gte ;
use get_headers ;
use trick_version ;
use Digest::MD5 qw(md5_hex) ;
@ -37,31 +36,25 @@ Options:
display this help and exit
-s, --stl
Allow convert_swig to process STLs
-o, --outfile <OUT_FILE>
provide a name for the generated SWIG interface file which
is usually denoted with a special .i or .swg suffix
Usage:
convert_swig [-o <OUT_FILE>] <IN_FILE>
convert_swig <IN_FILES>
Examples:
% convert_swig -o swig/Ball.i include/Ball.hh
% convert_swig -o swig_src/S_source.i S_source.hh
% convert_swig include/Ball.hh
% convert_swig S_source.hh
" ;
my ($in_file , $out_file ) ;
my $help = ''; # option variable with default value (false)
my $stls = 0; # option variable with default value (false)
my ( @include_paths, @include_dirs , @defines) ;
my ( @include_dirs , @defines) ;
my ( @swig_exclude_dirs) ;
my ( @exclude_dirs) ;
my %sim ;
my %out_of_date ;
my ($version, $thread, $year) ;
my %icg_no ;
my %skipped_files ;
my %processed_templates ;
my $typedef_def = qr/typedef\s+ # the word typedef
@ -112,8 +105,7 @@ my %stl_names = qw(deque 1 set 1 multiset 1 multimap 1 hash_set 1
std::bitset 1 std::auto_ptr 1 pair 1 std::pair 1 std::tr1::shared_ptr 1) ;
Getopt::Long::Configure ("bundling");
GetOptions ( "outfile|o=s" => \$out_file ,
"stl|s" => sub { $stls = 1 } ,
GetOptions ( "stl|s" => sub { $stls = 1 } ,
'help|h' => \$help ) or usage() ;
if ( $help ) {
@ -123,188 +115,65 @@ if ( $help ) {
($version, $thread) = get_trick_version() ;
($year) = $version =~ /^(\d+)/ ;
@include_paths = $ENV{"TRICK_CFLAGS"} =~ /(-I\s*\S+)/g ; # get include paths from TRICK_CFLAGS
@include_dirs = $ENV{"TRICK_CFLAGS"} =~ /-I\s*(\S+)/g ; # get include paths from TRICK_CFLAGS
@swig_exclude_dirs = split /:/ , $ENV{"TRICK_SWIG_EXCLUDE"} ;
if ( scalar @swig_exclude_dirs == 0 ) {
@swig_exclude_dirs = split /:/ , $ENV{"TRICK_ICG_EXCLUDE"} ;
}
@exclude_dirs = split /:/ , $ENV{"TRICK_EXCLUDE"} ;
push @include_paths , ("-I".$ENV{"TRICK_HOME"}."/trick_source" , "-I../include") ;
@defines = $ENV{"TRICK_CFLAGS"} =~ /(-D\S+)/g ; # get defines from TRICK_CFLAGS
if ( $ENV{"TRICK_CFLAGS"} !~ /DTRICK_VER=/ ) {
push @defines , "-DTRICK_VER=$year" ;
}
#(my $cc = gte("TRICK_CC")) =~ s/\n// ;
# Use the c preporcessor directly
my $cc ;
my $system_type = `uname -s` ;
chomp $system_type ;
if ( $system_type eq "Darwin" ) {
$cc = "/usr/bin/llvm-gcc -E" ;
} else {
$cc = "/usr/bin/cpp" ;
}
($in_file) = (grep !/^-/ , @ARGV) ;
## The list of header files to be processed is usually produced by the script
## make_swig_makefile.pm, as it's creating Makefile_swig. This list is stored in
## the file ".S_library_swig". So, if .S_library_swig exists, we can just open and read it.
##
my ($s_library_swig) = "build/S_library_swig" ;
if ( -e $s_library_swig ) {
open FILE_LIST, $s_library_swig ;
if ( scalar @ARGV == 0 ) {
my ($s_library_swig) = "build/S_library_swig" ;
open FILE_LIST, $s_library_swig or die "Could not open $s_library_swig" ;
while ( <FILE_LIST> ) {
chomp ;
$sim{final_all_includes}{$_} = 1 ;
my ($f) = $_ ;
my ($swig_dir , $base_file , $swig_file ) ;
$base_file = basename($f) ;
$base_file =~ s/\.[^\.]+$// ;
$swig_dir = dirname($f) ;
$swig_dir = "build/$swig_dir" ;
$swig_file = "$swig_dir/${base_file}.i" ;
#print "$swig_file\n" ;
if ( -e $swig_file ) {
if ( !exists $sim{mod_date}{$f} ) {
$sim{mod_date}{$f} = (stat $f)[9] ;
}
$sim{swig_mod_date}{$f} = (stat $swig_file)[9] ;
if ( $sim{mod_date}{$f} > $sim{swig_mod_date}{$f} ) {
$out_of_date{$f} = 1 ;
}
} else {
$out_of_date{$f} = 1 ;
$sim{swig_mod_date}{$f} = 0 ;
}
}
} else {
## Otherwise we need to process S_source.hh to produce the list of header files.
##
## Specifically, we want to generate SWIG interfaces for those header files that are:
## 1) actual dependencies of S_source.hh, GIVEN THE CURRENT environment and
## 2) not excluded from ICG processing ( by ICG_NO or ICG_EXCLUDE).
##
## The header files that are actually included are the dependencies we care
## about. Keep in mind that the pre-processor and the current ENVIRONMENT
## may cause some headers to be conditionally included or excluded. We only
## want to generate SWIG interfaces for headers that are ACTUALLY included.
##
## Whereas the pre-processor can (using the gcc -MM option) generate a list
## of dependencies that satisfy 1) (above), it can't handle that ICG exclusions.
## And, whereas the function get_headers() can generate a list of dependences
## which are flagged if they contain ICG_NO, it doesn't handle conditional includes.
##
## So, the strategy that we employ is to generate and then find the
## intersection of both lists. Then we eliminate those that are in 1)
## $TRICK_HOME/trick_source, or 2) flagged as containing ICG_NO or 3) are
## in ICG_EXCLUDE'd directories.
##
## First, create a list headers using the GCC with the -MM option. GCC will
## handle conditional inclusion.
##
# list of files to process does not exist. Process S_source.hh to create one.
my ($s_source_full_path) = abs_path("S_source.hh") ;
open FILE_LIST, "$cc -MM -DSWIG @include_paths @defines $in_file |" ;
my $dir ;
$dir = dirname($s_source_full_path) ;
while ( <FILE_LIST> ) {
next if ( /^#/ or /^\s+\\/ ) ;
my $word ;
foreach $word ( split ) {
next if ( $word eq "\\" or $word =~ /o:/ ) ;
if ( $word !~ /^\// and $dir ne "\/" ) {
$word = "$dir/$word" ;
}
$word = abs_path(dirname($word)) . "/" . basename($word) ;
# filter out system headers that are missed by the compiler -MM flag
next if ( $word =~ /^\/usr\/include/) ;
next if ( $word =~ /$ENV{TRICK_HOME}\/trick_source\//) ;
#print "gcc found $word\n" ;
$sim{gcc_all_includes}{$word} = 1 ;
#$sim{mod_date}{$word} = (stat $word)[9] ;
}
}
## Second, create a list where the files are flagged if they contain ICG_NO.
##
get_headers(\%sim, $s_source_full_path) ;
if ( open ICGNOFOUND , ("build/icg_no_found") ) {
while ( <ICGNOFOUND> ) {
chomp ;
$icg_no{$_} = 1 ;
}
}
## Then we generate the intersection of the two lists and then eliminate the dependencies that:
## 1) are in $TRICK_HOME/trick_source.
## 2) contain ICG_NO.
## 3) are in ICG_EXCLUDE'd directories.
## to create the final list of header dependencies that we need to convert into SWIG interfaces.
##
foreach my $k ( keys %{$sim{gcc_all_includes}} ) {
$sim{final_all_includes}{$k} = 1 if exists $sim{all_includes}{$s_source_full_path} ;
}
foreach my $f ( keys %{$sim{final_all_includes}} ) {
if ( $f =~ /$ENV{TRICK_HOME}\/trick_source/ ) {
delete $sim{final_all_includes}{$f} ;
} elsif ( exists $icg_no{$f} ) {
$skipped_files{$f} = "ICG No found" ;
delete $sim{final_all_includes}{$f} ;
} else {
foreach my $ie ( @swig_exclude_dirs ) {
# if file location begins with $ie (an IGC exclude dir)
if ( $f =~ /^\Q$ie/ ) {
$skipped_files{$f} = "ICG exclude dir $ie" ;
delete $sim{final_all_includes}{$f} ;
last ; # break out of loop
}
}
foreach my $ie ( @exclude_dirs ) {
# if file location begins with $ie (an IGC exclude dir)
if ( $f =~ /^\Q$ie/ ) {
$skipped_files{$f} = "Exclude dir $ie" ;
delete $sim{final_all_includes}{$f} ;
last ; # break out of loop
}
}
}
}
#print "HERE I AM @ARGV\n" ;
map { $out_of_date{$_} = 1 } @ARGV ;
}
## Next we need to determine which of the files do not have up-to-date SWIG files.
## For each header file in final dependency list, if the corresponding SWIG (.i) file
## doesn't exist or the header file is newer than the existing SWIG file, then record
## that a new SWIG file needs needs to be created. The global hash %out_of_date
## represents a list of header files whose corresponding .i files need to be regenerated.
## The global hash %out_of_date represents a list of header files whose
## corresponding .i files need to be regenerated.
##
foreach my $f ( keys %{$sim{final_all_includes}} ) {
my ($swig_dir , $base_file , $swig_file ) ;
$base_file = basename($f) ;
$base_file =~ s/\.[^\.]+$// ;
$swig_dir = dirname($f) ;
$swig_dir = "build/$swig_dir" ;
$swig_file = "$swig_dir/${base_file}.i" ;
#print "$swig_file\n" ;
if ( -e $swig_file ) {
if ( !exists $sim{mod_date}{$f} ) {
$sim{mod_date}{$f} = (stat $f)[9] ;
}
$sim{swig_mod_date}{$f} = (stat $swig_file)[9] ;
if ( $sim{mod_date}{$f} > $sim{swig_mod_date}{$f} ) {
$out_of_date{$f} = 1 ;
}
} else {
$out_of_date{$f} = 1 ;
$sim{swig_mod_date}{$f} = 0 ;
}
}
if ( scalar keys %out_of_date == 0 ) {
exit ;
}
foreach ( sort keys %skipped_files ) {
print "convert_swig skipping $_ ($skipped_files{$_})\n" ;
}
## Finally, call process_file() to create SWIG interface files for each of the out_of_date headers.
##
process_file(\%sim , abs_path($in_file)) ;
process_file() ;
##
## ================================================================================
@ -319,16 +188,10 @@ process_file(\%sim , abs_path($in_file)) ;
##
## sim_ref
##
## Is this parameter ever used?
##
## in_file
##
## The name of input file, invariably "S_source.hh".
##
sub process_file($$) {
my ($sim_ref , $in_file) = @_ ;
sub process_file() {
## Foreach out_of_date header file, generate a SWIG interface file.
@ -425,6 +288,7 @@ sub process_file($$) {
my ($out_dir) = dirname($f) ;
$out_dir = "build$out_dir" ;
my $out_file ;
$out_file = basename($f) ;
$out_file =~ s/\.h.*$/\.i/ ;
@ -447,7 +311,6 @@ sub process_file($$) {
open OUT, ">$out_file" ;
print OUT "\%module m$md5_sum\n\n" ;
print OUT "/* $in_file */\n" ;
print OUT "#include \"trick/swig/trick_swig.i\"\n\n" ;

View File

@ -43,8 +43,10 @@ sub read_lib_deps(@) {
}
for my $f ( @ARGV ) {
print "Updating Dependencies for $f\n" ;
write_lib_deps($f) ;
if ( $f !~ /Makefile_io_src/ ) {
print "Updating Dependencies for $f\n" ;
write_lib_deps($f) ;
}
}
open FILE, "build/header_lib_deps_files" or die 'cannot open build/header_lib_deps_files' ;
@ -258,7 +260,8 @@ foreach $k ( sort keys %files_by_dir ) {
print MAKEFILE "\$(CURDIR)/build$k/$files_by_dir{$k}{src_dir}$f :\n" ;
print MAKEFILE "\t@ mkdir -p \$\@\n\n" ;
print MAKEFILE "\$(CURDIR)/build/lib/o${num_inc_objs}.o : \$(MODEL_${print_ext}_OBJ_$files_by_dir{$k}{dir_num})\n" ;
#print MAKEFILE "\$(CURDIR)/build/lib/o${num_inc_objs}.o : \$(MODEL_${print_ext}_OBJ_$files_by_dir{$k}{dir_num})\n" ;
print MAKEFILE "\$(CURDIR)/build/lib/o_${print_ext}_$files_by_dir{$k}{dir_num}.o : \$(MODEL_${print_ext}_OBJ_$files_by_dir{$k}{dir_num})\n" ;
print MAKEFILE "\t\$(PRINT_INC_LINK)\n" ;
print MAKEFILE "\t\$(ECHO_CMD)cd \${<D} ; ld \$(LD_PARTIAL) -o \$\@ \$(notdir \$^)\n\n" ;
$num_inc_objs++ ;
@ -338,8 +341,18 @@ print MAKEFILE "-include \$(MODEL_cxx_OBJ:.o=.d)\n" ;
print MAKEFILE "-include \$(MODEL_CPLUSPLUS_OBJ:.o=.d)\n\n" ;
printf MAKEFILE "\n\nOBJECTS =" ;
for( $i = 0 ; $i < $num_inc_objs ; $i++ ) {
print MAKEFILE " \\\n\t\$(LIB_DIR)/o$i.o" ;
foreach $k ( sort keys %files_by_dir ) {
foreach my $ext ( qw{ c C cc cxx cpp c++ l y} ) {
my $print_ext ;
if ( $ext eq "c++" ) {
$print_ext = "CPLUSPLUS" ;
} else {
$print_ext = $ext ;
}
if ( scalar @{$files_by_dir{$k}{$ext}} ne 0 ) {
print MAKEFILE "\\\n\t\$(CURDIR)/build/lib/o_${print_ext}_$files_by_dir{$k}{dir_num}.o" ;
}
}
}
# print out the libraries we link
@ -412,8 +425,9 @@ close MAKEFILE ;
# write out all of files as dependencies to Makefile_src
open MAKEFILEDEPS, ">build/Makefile_src_deps" or die "Could not open build/Makefile_src_deps" ;
print MAKEFILEDEPS "build/Makefile_src :" ;
print MAKEFILEDEPS "\$(CURDIR)/build/Makefile_src :" ;
print MAKEFILEDEPS map {"\\\n $_"} (sort keys %non_lib_processed_files) ;
print MAKEFILEDEPS "\n" ;
close MAKEFILEDEPS ;
# write out all of the files we used to S_library_list

View File

@ -294,7 +294,6 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS)
}
close SWIGLIB ;
open S_INSTANCE , "build/S_instances" or return ;
my @instances = <S_INSTANCE> ;
close S_INSTANCE ;
@ -336,6 +335,9 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS)
print INITSWIGFILE " return ;\n}\n\n}\n" ;
close INITSWIGFILE ;
if ( ! -e "trick") {
mkdir "trick" ;
}
open INITFILE , ">trick/__init__.py" or return ;
print INITFILE "import sys\n" ;

View File

@ -12,8 +12,8 @@ else
PRINT_CP = @echo "Running configuration_processor"
PRINT_ICG = @echo "Running ICG"
PRINT_CONVERT_SWIG = @echo "Running convert_swig"
PRINT_MAKEFILE_SRC = @echo "Creating source Makefile"
PRINT_MAKEFILE_SWIG = @echo "Creating swig Makefile"
PRINT_MAKEFILE_SRC = @echo "Creating/updating source Makefile"
PRINT_MAKEFILE_SWIG = @echo "Creating/updating swig Makefile"
ECHO_CMD = @
endif
@ -24,7 +24,11 @@ export TRICK_ICG_EXCLUDE
# Use /bin/bash as the shell so we can use PIPESTATUS
SHELL = /bin/bash
all : ${TRICK_LIB_DIR}/libtrick.a S_source.hh build/Makefile_io_src build/Makefile_src build/Makefile_swig
all : ${TRICK_LIB_DIR}/libtrick.a S_source.hh \
$(CURDIR)/build/Makefile_io_src \
$(CURDIR)/build/Makefile_src \
$(CURDIR)/build/Makefile_swig \
$(CURDIR)/build/convert_swig_last_run
@/bin/cp ${TRICK_HOME}/share/trick/MAKE_out_header.txt build/MAKE_out
@$(MAKE) --no-print-directory -f build/Makefile_src all 2>&1 | tee -a build/MAKE_out ; exit $${PIPESTATUS[0]}
@ -42,17 +46,13 @@ ${TRICK_LIB_DIR}/libtrick.a:
@echo "Cannot find $@. Please build Trick for this platfrom"
@exit -1
# CP creates S_source.hh required for ICG and SWIG processing
S_source.hh : S_define | build
$(PRINT_CP)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/configuration_processor $(TRICK_CPFLAGS)
# Create makefile for source code
build/Makefile_src: | build/Makefile_io_src
$(PRINT_MAKEFILE_SRC)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/make_makefile_src $?
# ICG rules
build/Makefile_io_src : | S_source.hh
# Automatic and manual ICG rules
$(CURDIR)/build/Makefile_io_src : | S_source.hh
$(PRINT_ICG)
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_CXXFLAGS} S_source.hh
@ -64,24 +64,33 @@ force_ICG:
$(PRINT_ICG)
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -f -m ${TRICK_CXXFLAGS} S_source.hh
# SWIG rules
build/Makefile_swig : | build/Makefile_io_src
# Create makefile for source code
$(CURDIR)/build/Makefile_src: $(CURDIR)/build/Makefile_io_src
$(PRINT_MAKEFILE_SRC)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/make_makefile_src $?
# Create makefile for SWIG code
$(CURDIR)/build/Makefile_swig : | $(CURDIR)/build/Makefile_io_src
$(PRINT_MAKEFILE_SWIG)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/make_makefile_swig $?
# convert_swig rules
#$(CURDIR)/build/convert_swig_last_run : | build/Makefile_sim
# $(PRINT_CONVERT_SWIG)
# $(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} S_source.hh
# @ touch $@
# Automatic and manual convert_swig rules
$(CURDIR)/build/convert_swig_last_run : | $(CURDIR)/build/Makefile_swig
$(PRINT_CONVERT_SWIG)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS}
@ touch $@
convert_swig:
$(PRINT_CONVERT_SWIG)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} S_source.hh
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS}
@ touch $(CURDIR)/build/convert_swig_last_run
sie S_define_exp:
@if [ -f build/Makefile_sim ] ; then $(MAKE) --no-print-directory -f build/Makefile_sim $@ ; else echo "No build/Makefile_sim found" ; fi
S_define_exp:
$(TRICK_CC) -E -C -xc++ ${TRICK_SFLAGS} S_define > $@
# Pass these options
sie:
@if [ -f build/Makefile_src ] ; then $(MAKE) --no-print-directory -f build/Makefile_src $@ ; else echo "No build/Makefile_src found" ; fi
help:
@ echo -e "\
@ -111,7 +120,8 @@ apocalypse: clean
@echo "I love the smell of napalm in the morning"
# Dependencies to other files that may cause a re-CP
# Dependencies for the above rules generated by configuration_process, ICG, make_makefile and make_makefile_swig
-include S_overrides.mk
-include build/S_define.deps
-include build/Makefile_ICG
-include build/Makefile_convert_swig

View File

@ -428,7 +428,7 @@ void PrintAttributes::printIOMakefile() {
makefile_io_src.close() ;
/*
Makefile_ICG lists all headers as dependencies of class_map.cpp
Makefile_ICG lists all headers as dependencies of Makefile_io_src
causing ICG to run if any header file changes.
link_io_objs lists all io_src object files to be partially
@ -439,7 +439,7 @@ void PrintAttributes::printIOMakefile() {
makefile_ICG.open("build/Makefile_ICG") ;
link_io_objs.open("build/link_io_objs") ;
ICG_processed.open("build/ICG_processed") ;
makefile_ICG << "$(CURDIR)/build/class_map.cpp :" ;
makefile_ICG << "$(CURDIR)/build/Makefile_io_src :" ;
for ( mit = all_io_files.begin() ; mit != all_io_files.end() ; mit++ ) {
makefile_ICG << "\\\n " << (*mit).first ;
size_t found ;
@ -461,13 +461,11 @@ void PrintAttributes::printHeaderLibraryDependencies() {
header_lib_deps.open("build/header_lib_deps_files") ;
std::map< std::string , std::string >::iterator mit ;
for ( mit = all_io_files.begin() ; mit != all_io_files.end() ; mit++ ) {
size_t found ;
found = (*mit).first.find_last_of(".") ;
std::string lib_dep_file = std::string("build") + (*mit).first.substr(0,found) + ".lib_deps" ;
header_lib_deps << lib_dep_file << std::endl ;
if ( out_of_date_io_files.find((*mit).first) != out_of_date_io_files.end()) {
size_t found ;
found = (*mit).first.find_last_of(".") ;
std::string lib_dep_file = std::string("build") + (*mit).first.substr(0,found) + ".lib_deps" ;
header_lib_deps << lib_dep_file << std::endl ;
std::ofstream file_list ;
file_list.open(lib_dep_file) ;
std::vector< std::string > lib_deps = cs.getLibraryDependencies((*mit).first) ;