From d744eba5576fd52d68525f42daf97f3ac5dbd475 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Wed, 22 Jul 2015 10:54:00 -0500 Subject: [PATCH] Split CP up into components that can be called individually Added a new TRICK_EXT_LIB_DIRS variable that allows users to tell Trick about external libraries, rather than trying to use TRICK_EXCLUDE. Added back getting multiple library dependency sections from source files. refs #86 --- libexec/trick/make_makefile_src | 2 + libexec/trick/make_makefile_swig | 64 +++++++-------- libexec/trick/pm/get_lib_deps.pm | 22 +++--- share/trick/makefiles/Makefile.common | 2 + .../Interface_Code_Gen/HeaderSearchDirs.cpp | 47 +++++++++++ .../Interface_Code_Gen/HeaderSearchDirs.hh | 19 +++++ .../Interface_Code_Gen/PrintAttributes.cpp | 77 ++++++++++++------- .../Interface_Code_Gen/PrintAttributes.hh | 5 +- 8 files changed, 167 insertions(+), 71 deletions(-) diff --git a/libexec/trick/make_makefile_src b/libexec/trick/make_makefile_src index 05099d4d..972c2754 100755 --- a/libexec/trick/make_makefile_src +++ b/libexec/trick/make_makefile_src @@ -43,6 +43,8 @@ sub read_lib_deps(@) { } for my $f ( @ARGV ) { + # Makefile_io_src is listed as a dependency of make_makefile_src and comes in as + # an argument from make. Ignore it. if ( $f !~ /Makefile_io_src/ ) { print "Updating Dependencies for $f\n" ; write_lib_deps($f) ; diff --git a/libexec/trick/make_makefile_swig b/libexec/trick/make_makefile_swig index fcff948c..c8c23803 100755 --- a/libexec/trick/make_makefile_swig +++ b/libexec/trick/make_makefile_swig @@ -14,6 +14,7 @@ use strict ; my @exclude_dirs ; my @swig_exclude_dirs ; my @files_to_process ; +my @ext_lib_files ; sub get_exclude_dirs() { @exclude_dirs = split /:/ , $ENV{"TRICK_EXCLUDE"}; @@ -67,13 +68,18 @@ sub read_files_to_process() { @files_to_process = ; close FILE ; chomp @files_to_process ; + + open FILE, "build/external_lib_header_files" or die 'could not open build/external_lib_header_files' ; + @ext_lib_files = ; + close FILE ; + chomp @ext_lib_files ; } sub make_swig_makefile() { my ($n , $f , $k , $m); my %temp_hash ; - my (@temp_array , @temp_array2) ; + my (@temp_array) ; my ($ii) ; my ($swig_sim_dir, $swig_src_dir) ; my (%py_module_map) ; @@ -97,9 +103,7 @@ sub make_swig_makefile() { $swig_sim_dir = "\$(CURDIR)/trick" ; $swig_src_dir = "\$(CURDIR)/build" ; - undef @temp_array2 ; foreach $n (@files_to_process) { - undef @temp_array ; # check to see if the parent directory of each file is writable. # If it isn't, then don't add it to the list of files to requiring ICG @@ -114,8 +118,9 @@ sub make_swig_makefile() { } } next if ( $continue == 0 ) ; - push @temp_array2 , $f ; + push @temp_array , $f ; } + @files_to_process = @temp_array ; open MAKEFILE , ">build/Makefile_swig" or return ; open LINK_PY_OBJS , ">build/link_py_objs" or return ; @@ -146,18 +151,7 @@ SWIG_MODULE_OBJECTS = \$(LIB_DIR)/swig_python.o SWIG_PY_OBJECTS =" ; - foreach my $f ( @temp_array2 ) { - my ($continue) = 1 ; - foreach my $ie ( @exclude_dirs ) { - # if file location begins with $ie (an IGC exclude dir) - if ( $f =~ /^\Q$ie/ ) { - $continue = 0 ; - $ii++ ; - last ; # break out of loop - } - } - next if ( $continue == 0 ) ; - + foreach my $f ( @files_to_process ) { my ($swig_dir, $swig_object_dir , $swig_module_dir , $swig_file_only) ; my ($swig_f) = $f ; $swig_object_dir = dirname($f) ; @@ -174,7 +168,7 @@ SWIG_PY_OBJECTS =" ; my %swig_dirs ; my %python_modules ; $ii = 0 ; - foreach my $f ( @temp_array2 ) { + foreach my $f ( @files_to_process ) { my ($swig_dir, $swig_object_dir , $swig_module_dir , $swig_file_only) ; my ($swig_f) = $f ; @@ -194,16 +188,6 @@ SWIG_PY_OBJECTS =" ; # } my ($continue) = 1 ; - foreach my $ie ( @exclude_dirs ) { - # if file location begins with $ie (an IGC exclude dir) - if ( $f =~ /^\Q$ie/ ) { - $continue = 0 ; - $ii++ ; - last ; # break out of loop - } - } - next if ( $continue == 0 ) ; - my $md5_sum = md5_hex($f) ; # check if .sm file was accidentally ##included instead of #included if ( rindex($swig_f,".sm") != -1 ) { @@ -284,7 +268,7 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS) close LINK_PY_OBJS ; open SWIGLIB , ">build/S_library_swig" or return ; - foreach my $f ( @temp_array2 ) { + foreach my $f ( @files_to_process ) { print SWIGLIB "$f\n" ; } close SWIGLIB ; @@ -303,7 +287,11 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS) open INITSWIGFILE , ">build/init_swig_modules.cpp" or return ; print INITSWIGFILE "extern \"C\" {\n\n" ; - foreach $f ( @temp_array2 ) { + foreach $f ( @files_to_process ) { + my $md5_sum = md5_hex($f) ; + print INITSWIGFILE "void init_m${md5_sum}(void) ; /* $f */\n" ; + } + foreach $f ( @ext_lib_files ) { my $md5_sum = md5_hex($f) ; print INITSWIGFILE "void init_m${md5_sum}(void) ; /* $f */\n" ; } @@ -314,12 +302,15 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS) print INITSWIGFILE "void init_swig_ref(void) ;\n" ; print INITSWIGFILE "\nvoid init_swig_modules(void) {\n\n" ; - foreach $f ( @temp_array2 ) { + foreach $f ( @files_to_process ) { next if ( $f =~ /S_source.hh/ ) ; my $md5_sum = md5_hex($f) ; print INITSWIGFILE " init_m${md5_sum}() ;\n" ; } - + foreach $f ( @ext_lib_files ) { + my $md5_sum = md5_hex($f) ; + print INITSWIGFILE " init_m${md5_sum}() ;\n" ; + } print INITSWIGFILE " init_m${s_source_md5}() ;\n" ; print INITSWIGFILE " init_sim_services() ;\n" ; @@ -372,6 +363,15 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS) print INITFILE "cvar = None\n\n" ; } + foreach $f ( @ext_lib_files ) { + my $md5_sum = md5_hex($f) ; + print INITFILE "# $f\n" ; + print INITFILE "import _m${md5_sum}\n" ; + print INITFILE "from m${md5_sum} import *\n" ; + print INITFILE "combine_cvars(all_cvars, cvar)\n" ; + print INITFILE "cvar = None\n\n" ; + } + print INITFILE "# S_source.hh\n" ; print INITFILE "import _m${s_source_md5}\n" ; print INITFILE "from m${s_source_md5} import *\n\n" ; @@ -413,7 +413,7 @@ OBJECTS += \$(SWIG_MODULE_OBJECTS) open MAKEFILECONV , ">build/Makefile_convert_swig" or return ; print MAKEFILECONV "\$(CURDIR)/build/convert_swig_last_run :" ; - foreach $f ( @temp_array2 ) { + foreach $f ( @files_to_process ) { print MAKEFILECONV " \\\n $f" ; } close MAKEFILECONV ; diff --git a/libexec/trick/pm/get_lib_deps.pm b/libexec/trick/pm/get_lib_deps.pm index 627c6a5c..082286dd 100644 --- a/libexec/trick/pm/get_lib_deps.pm +++ b/libexec/trick/pm/get_lib_deps.pm @@ -14,11 +14,15 @@ sub get_lib_deps ($$) { my ($lib_deps) ; my (@lib_list) ; my (@inc_paths) ; + my (@raw_lib_deps) ; # library dependency regular expression will match all the way through last parenthesis followed by # another field in the trick header, a doxygen style keyword, or the end of comment *. - ($lib_deps) = $contents =~ /LIBRARY[ _]DEPENDENC(?:Y|IES):[^(]*(.*?)\)([A-Z _\t\n\r]+:|\s*[\*@])/si ; - @lib_list = split /\)[ \t\n\r\*]*\(/ , $lib_deps ; + # we capture all library dependencies at once into raw_lib_deps + @raw_lib_deps = ($contents =~ /LIBRARY[ _]DEPENDENC(?:Y|IES)\s*:[^(]*(.*?)\)(?:[A-Z _\t\n\r]+:|\s*[\*@])/gsi) ; + foreach ( @raw_lib_deps ) { + push @lib_list , (split /\)[ \t\n\r\*]*\(/ , $_) ; + } @inc_paths = $ENV{"TRICK_CFLAGS"} =~ /-I\s*(\S+)/g ; # get include paths from TRICK_CFLAGS # Get only the include paths that exist @@ -32,7 +36,7 @@ sub get_lib_deps ($$) { $file_path_dir =~ s/\/+$// ; # remove trailing slash $file_path_dir =~ s/\/include$// ; - my @resolved_files ; + my %resolved_files ; foreach my $l (@lib_list) { my $found = 0 ; $l =~ s/\(|\)|\s+//g ; @@ -44,7 +48,7 @@ sub get_lib_deps ($$) { foreach my $inc ( dirname($source_file_name) , @inc_paths) { if ( -e "$inc/$rel_dir" ) { my $f = abs_path("$inc/$rel_dir") . "/" . basename($l) ; - push @resolved_files, $f ; + $resolved_files{$f} = 1 ; $found = 1 ; last ; } @@ -54,7 +58,7 @@ sub get_lib_deps ($$) { if ( -e "$inc/$l" ) { #print "found $inc/$l$ext\n" ; my $f = abs_path(dirname("$inc/$l")) . "/" . basename("$inc/$l") ; - push @resolved_files, $f ; + $resolved_files{$f} = 1 ; $found = 1 ; last ; } @@ -68,14 +72,14 @@ sub get_lib_deps ($$) { if ( -e "$inc/$rel_dir/$base$ext" ) { #print "found $inc/$l$ext\n" ; my $f = abs_path("$inc/$rel_dir") . "/$base$ext" ; - push @resolved_files, $f ; + $resolved_files{$f} = 1 ; $found = 1 ; last ; } elsif ( -e "$inc/$rel_dir/src/$base$ext" ) { #print "found $inc/src/$l$ext\n" ; my $f = abs_path("$inc/$rel_dir/src") . "/$base$ext" ; - push @resolved_files, $f ; + $resolved_files{$f} = 1 ; $found = 1 ; last ; } @@ -88,7 +92,7 @@ sub get_lib_deps ($$) { print STDERR "$source_file_name: Warning: Could not find dependency $l\n" ; } } - return @resolved_files ; + return (sort keys %resolved_files) ; } sub write_lib_deps($) { @@ -105,7 +109,7 @@ sub write_lib_deps($) { make_path("build$dir") ; } open LIBDEP, ">$lib_dep_file_name" ; - print LIBDEP map {"$_\n"} (sort @resolved_files) ; + print LIBDEP map {"$_\n"} @resolved_files ; close LIBDEP ; return @resolved_files ; diff --git a/share/trick/makefiles/Makefile.common b/share/trick/makefiles/Makefile.common index bae49766..fea05fab 100644 --- a/share/trick/makefiles/Makefile.common +++ b/share/trick/makefiles/Makefile.common @@ -32,9 +32,11 @@ export TRICK_CFLAGS export TRICK_CXXFLAGS export TRICK_LDFLAGS export TRICK_SFLAGS +export TRICK_EXCLUDE export TRICK_ICG_EXCLUDE export TRICK_ICG_NOCOMMENT export TRICK_SWIG_EXCLUDE +export TRICK_EXT_LIB_DIRS export TRICK_GTE_EXT export TRICK_HOST_CPU := $(shell export TRICK_CC=$(TRICK_CC) && $(TRICK_HOME)/bin/trick-gte TRICK_HOST_CPU) export TRICK_EXEC_LINK_LIBS = ${PTHREAD_LIBS} $(PYTHON_LIB) $(PLATFORM_LIBS) -lm -ldl -lz diff --git a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp index c2cf2c87..3adf6207 100644 --- a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp +++ b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.cpp @@ -169,6 +169,28 @@ void HeaderSearchDirs::AddExcludeDirs () { } } +void HeaderSearchDirs::AddExtLibDirs () { + + char * trick_ext_lib_dirs = getenv("TRICK_EXT_LIB_DIRS") ; + + if( trick_ext_lib_dirs != NULL ) { + std::string s = std::string(trick_ext_lib_dirs) ; + std::stringstream ss(s); + std::string item; + while(std::getline(ss, item, ':')) { + item = trim(item) ; + if ( ! item.empty() ) { + char * resolved_path = realpath(item.c_str(), NULL) ; + if ( resolved_path ) { + ext_lib_dirs.push_back(std::string(resolved_path) + std::string("/")); + } else { + std::cout << "Cannot find TRICK_EXT_LIB_DIRS directory " << item << std::endl ; + } + } + } + } +} + void HeaderSearchDirs::AddICGNoCommentDirs () { char * trick_icg_nocomment = getenv("TRICK_ICG_NOCOMMENT") ; @@ -214,6 +236,7 @@ void HeaderSearchDirs::addSearchDirs ( std::vector & include_dirs ) AddCompilerBuiltInSearchDirs() ; AddExcludeDirs() ; AddICGExcludeDirs() ; + AddExtLibDirs() ; AddICGNoCommentDirs() ; ApplyHeaderSearchOptions() ; } @@ -272,6 +295,18 @@ bool HeaderSearchDirs::isPathInICGExclude (std::string in_dir ) { return false ; } +bool HeaderSearchDirs::isPathInExtLib (std::string in_dir ) { + + std::vector::iterator vit ; + for ( vit = ext_lib_dirs.begin() ; vit != ext_lib_dirs.end() ; vit++ ) { + if ( ! in_dir.compare(0, (*vit).size(), (*vit))) { + return true ; + } + } + + return false ; +} + bool HeaderSearchDirs::isPathInICGNoComment (std::string in_file ) { char * resolved_path = almostRealPath(in_file.c_str() ) ; @@ -320,6 +355,18 @@ std::string HeaderSearchDirs::getPathInICGExclude (std::string in_dir ) { return std::string() ; } +std::string HeaderSearchDirs::getPathInExtLib (std::string in_dir ) { + + std::vector::iterator vit ; + for ( vit = ext_lib_dirs.begin() ; vit != ext_lib_dirs.end() ; vit++ ) { + if ( ! in_dir.compare(0, (*vit).size(), (*vit))) { + return (*vit) ; + } + } + + return std::string() ; +} + void HeaderSearchDirs::addDefines ( std::vector & defines ) { // Add -D command line arguments as well as "#define TRICK_ICG" to the preprocessor diff --git a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh index 0fafcc25..2472dea2 100644 --- a/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh +++ b/trick_source/codegen/Interface_Code_Gen/HeaderSearchDirs.hh @@ -61,6 +61,13 @@ class HeaderSearchDirs { */ bool isPathInICGExclude (std::string path) ; + /** Returns true if directory is a subdirectory of an external library directory listed + in the TRICK_EXT_LIB_DIRS environment variable. + @param path = directory path to be checked + @return true = path is in a system directory, false = not in system directory. + */ + bool isPathInExtLib (std::string path) ; + /** Returns true if directory is a subdirectory of a no comment directory in the TRICK_ICG_NOCOMMENT environment variable. @param path = directory path to be checked @@ -80,6 +87,12 @@ class HeaderSearchDirs { */ std::string getPathInICGExclude (std::string path) ; + /** Returns the TRICK_EXT_LIB_DIRS directory that contains the path argument. + @param path = path to be checked + @return string from TRICK_ICG_EXCLUDE that contains the path. + */ + std::string getPathInExtLib (std::string path) ; + /** Add all #defines from the command line and built in default predefines @param defines = a list of all -D arguments on the command line. */ @@ -119,6 +132,9 @@ class HeaderSearchDirs { /** Create list of ICG_EXCLUDE directories */ void AddICGExcludeDirs () ; + /** Create list of EXT_LIB_DIRS directories */ + void AddExtLibDirs () ; + /** Create list of ICG_NOCOMMENT directories */ void AddICGNoCommentDirs () ; @@ -131,6 +147,9 @@ class HeaderSearchDirs { /** List of directoris to exclude from the TRICK_ICG_EXCLUDE environment variable */ std::vector icg_exclude_dirs ; + /** List of directoris to mark as belonging in TRICK_EXT_LIB_DIRS environment variable */ + std::vector ext_lib_dirs ; + /** List of directoris to exclude comments from the TRICK_ICG_NOCOMMENT environment variable */ std::vector icg_nocomment_dirs ; diff --git a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp index f185848a..643b3adf 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp @@ -116,7 +116,7 @@ bool PrintAttributes::isFileIncluded(std::string header_file_name) { // Only include user directories (not system dirs like /usr/include) if ( hsd.isPathInUserDir(rp) ) { // Don't process files in excluded directories - if ( hsd.isPathInICGExclude(rp) == false ) { + if ( (hsd.isPathInExclude(rp) == false) and (hsd.isPathInICGExclude(rp) == false) ) { // Only include files that do not have ICG: (No) // hasICGNo uses original header name, not the real path if ( ! cs.hasICGNo(header_file_name) ) { @@ -147,26 +147,33 @@ bool PrintAttributes::openIOFile(std::string header_file_name) { // Only include files that do not have ICG: (No) // hasICGNo uses original header name, not the real path if ( ! cs.hasICGNo(header_file_name) ) { - std::string io_file_name = createIOFileName(std::string(rp)) ; - all_io_files[header_file_name] = io_file_name ; - // Does the io_src directory exist or can we successfully mkdir it? - if ( doesIODirectoryExist(io_file_name) ) { - // Is the io_src file out of date or does not exist yet - if ( isIOFileOutOfDate(rp, io_file_name) ) { - // All conditions have been met. Store the io_src file name in out_of_date_io_files. - out_of_date_io_files[header_file_name] = io_file_name ; - free(rp) ; - /* This is the first time we are visiting the file, - open the file and write header information */ - outfile.open(out_of_date_io_files[header_file_name].c_str()) ; - printer->printIOHeader(outfile, header_file_name) ; - std::cout << "Writing " << out_of_date_io_files[header_file_name] << "" << std::endl ; - // Get all of the ignored types from this file. - ignored_types[header_file_name] = cs.getIgnoreTypes(header_file_name) ; - return true ; + // Don't process files in external library directories + if ( hsd.isPathInExtLib(rp) == false ) { + std::string io_file_name = createIOFileName(std::string(rp)) ; + all_io_files[header_file_name] = io_file_name ; + // Does the io_src directory exist or can we successfully mkdir it? + if ( doesIODirectoryExist(io_file_name) ) { + // Is the io_src file out of date or does not exist yet + if ( isIOFileOutOfDate(rp, io_file_name) ) { + // All conditions have been met. Store the io_src file name in out_of_date_io_files. + out_of_date_io_files[header_file_name] = io_file_name ; + free(rp) ; + /* This is the first time we are visiting the file, + open the file and write header information */ + outfile.open(out_of_date_io_files[header_file_name].c_str()) ; + printer->printIOHeader(outfile, header_file_name) ; + std::cout << "Writing " << out_of_date_io_files[header_file_name] << "" << std::endl ; + // Get all of the ignored types from this file. + ignored_types[header_file_name] = cs.getIgnoreTypes(header_file_name) ; + return true ; + } + } else { + std::cout << "ICG skipping " << rp << " (cannot create io_src dir)" << std::endl ; } } else { - std::cout << "ICG skipping " << rp << " (cannot create io_src dir)" << std::endl ; + std::cout << "ICG skipping " << rp << " (ext lib dir " << + hsd.getPathInExtLib(rp) << ")" << std::endl ; + ext_lib_io_files.insert(header_file_name) ; } } else { std::cout << "ICG skipping " << rp << " (ICG No found)" << std::endl ; @@ -371,13 +378,19 @@ void PrintAttributes::addEmptyFiles() { if ( rp != NULL ) { // Only include user directories (not system dirs like /usr/include) if ( hsd.isPathInUserDir(rp) ) { - // Don't process files in excluded directories - if ( hsd.isPathInICGExclude(rp) == false ) { - // Only include files that do not have ICG: (No) - // hasICGNo uses original header name, not the real path - if ( ! cs.hasICGNo(header_file_name) ) { - std::string io_file_name = createIOFileName(std::string(rp)) ; - empty_header_files.insert(rp) ; + if ( hsd.isPathInExclude(rp) == false ) { + if ( hsd.isPathInICGExclude(rp) == false ) { + // Only include files that do not have ICG: (No) + // hasICGNo uses original header name, not the real path + if ( ! cs.hasICGNo(header_file_name) ) { + // Don't process files in excluded directories + if ( hsd.isPathInExtLib(rp) == false ) { + std::string io_file_name = createIOFileName(std::string(rp)) ; + empty_header_files.insert(rp) ; + } else { + ext_lib_io_files.insert(rp) ; + } + } } } } @@ -393,6 +406,7 @@ void PrintAttributes::printIOMakefile() { std::ofstream makefile_ICG ; std::ofstream link_io_objs ; std::ofstream ICG_processed ; + std::ofstream ext_lib ; unsigned int ii ; // Don't create a makefile if we didn't process any files. @@ -490,6 +504,11 @@ void PrintAttributes::printIOMakefile() { link_io_objs.close() ; ICG_processed.close() ; + ext_lib.open("build/external_lib_header_files") ; + for ( sit = ext_lib_io_files.begin() ; sit != ext_lib_io_files.end() ; sit++ ) { + ext_lib << (*sit) << std::endl ; + } + ext_lib.close() ; } void PrintAttributes::printHeaderLibraryDependencies() { @@ -521,10 +540,10 @@ void PrintAttributes::printHeaderLibraryDependencies() { found = (*sit).find_last_of(".") ; std::string lib_dep_file = std::string("build") + (*sit).substr(0,found) + ".lib_deps" ; - char * dir_name ; - dir_name = dirname(strdup((char *)lib_dep_file.c_str())) ; + char * tmp_str = strdup(lib_dep_file.c_str()) ; + char * dir_name = dirname(tmp_str) ; _mkdir(dir_name) ; - free(dir_name) ; + free(tmp_str) ; std::vector< std::string > lib_deps = cs.getLibraryDependencies((*sit)) ; std::vector< std::string >::iterator vit ; diff --git a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh index 9a00fbb7..c5061326 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh +++ b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh @@ -113,7 +113,10 @@ class PrintAttributes { /** map of all io_files we processed */ std::map< std::string , std::string > all_io_files ; - /** map of all io_files we processed */ + /** set of external library header files */ + std::set< std::string > ext_lib_io_files ; + + /** set of headers that have no class/enums */ std::set< std::string > empty_header_files ; /** map of open files to the out of date io_src file */