#!/usr/bin/perl -w # NAME: amsrcs04.pl # AIM: To scan a GNU configure.ac, or configure.in input file, for output Makefiles, then # successifly scan the Makefile.am (or .in) files, and create a DSP file foreach LIBRARY, # or PROGRAMS found in this make file san, then finally a DSW file. # ======================================================================================= # NOTE: This is NOT really a follow on from amsrcs03.pl ;=(( # This is a COMPLETE rewrite using lib_acscan.pl, and lib_amscan.pl # ======================================================================================= # History: Growing upwards... # 14/10/2011 - Found a case where only 2 Makefile.am found in configure.ac scan, BUT there is a line # [01] 39: [AC_CONFIG_SUBDIRS(autoconf-lib-link gettext-runtime gettext-tools)], and these SUBDIRS do # contain Makefile.am files... so add them to the list of AM to scan # 03/08/2011 - FIX20110803 - Found macro in Makefile.am like E00 = # src1.c - This should yield NO source # 21/04/2011 - FIX20110421 in lib_amscan.pl, to eliminate duplicate libs and paths. # 27/03/2011 - FIX20110327 - -L Allow the 'set' to include MULTIPLE libraries, for multiple project # 2011-03-14 The -L of library:path:[D|R|B][:project] could be EXTENDED to include # multiple name, of both the library and project parts, like # -L lib1;lib2:common_path:[D|R|B][:proj1;proj2;proj3 # Likewise -x project could be EXTENDED to be -x project1;project2;project3 # 23/03/2011 - FIX20110323 - Some minor improvement, and allow -I MACRO:project per project, and fix # 2011-03-14:FIXED:20110322: The -D macro[:value] got real messed up with say # '-D DEF_DIR=C:\some\path' Now FIXED 20110322 with got_colon_split(), and colon_split() subs # 06/03/2011 - FIX20110306 - Set project RUNTIME - either 'T'=static /MT, or 'D'=DLL (default) /MD # 30/12/2010 - Release 4.24, with some minor things in libraries... # 18/11/2010 - Fix librayr input -L lib:path:D[;proj] to accept 'c:\' as not a colon split # 03/11/2010 - Try moving JOINED to FIRST # 31/10/2010 - Several important additional options, and when a user option -L a-lib.lib:lib:[D|R|B], # where the a-lib.lib can be a semicolon separated list of libraries, but if no [;proj] # also try to add this to the DSW, if a local library dependency, to set the build order. # 21/10/2010 - Added new functions to handle # defines on a project, by project basis, like # -D TESTNUM=1:signal1, -D TESTNUM=2:signal2, -D TESTNUM=3:signal3 # AND set project type like SL to DLL, or CA to WA, but DLL NOT tested # 28/09/2010 Conditionals in the Makefile.am are stored, BUT when it comes to choosing the # correct sustitution, was just the FIRST TRUE always CHOSEN. # Added the option like - # --cond item[:1|0] (-c) = Define a conditional to be applied during parsing. # Revert to previous, if no conditional defined by user, but write a temp/missed_cond_list.txt # for items NOT defined. # 23/09/2010:19/09/2010 - Lots of updates, changes, additions # 08/09/2010 geoff mclane http://geoffair.net/mperl use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use File::Spec; # File::Spec->rel2abs($rel); # we are IN the SLN directory, get ABSOLUTE from RELATIVE use Cwd; my $perl_sdir = 'C:\GTools\perl'; unshift(@INC, $perl_sdir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl'! Check location and \@INC content.\n"; require 'lib_acscan.pl' or die "Unable to load 'lib_acscan.pl'! Check location and \@INC content.\n"; require 'lib_amscan.pl' or die "Unable to load 'lib_amscan.pl'! Check location and \@INC content.\n"; require 'lib_dsphdrs.pl' or die "Unable to load 'lib_dsphdrs.pl'! Check location and \@INC content.\n"; require 'lib_vcscan.pl' or die "Unable to load 'lib_vcscan.pl'! Check location and \@INC content.\n"; require 'lib_params.pl' or die "Unable to load 'lib_params.pl'! Check location and \@INC content.\n"; require 'lib_srcscan.pl' or die "Unable to load 'lib_srcscan.pl'! Check location and \@INC content.\n"; my $my_version = "version 0.4.30 2011-08-03"; # log file stuff my ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $perl_sdir."\\temp.$pgmname.txt"; open_log($outfile); my $perl_temp_dir = $perl_sdir."\\temp"; # user variables my $load_log = 0; my $no_conf_write = 0; my $write_am_list = 1; my $verbosity = 0; my $show_per_file = 1; my $dsp_out_dir = $perl_temp_dir; my $do_joined_first = 0; # NO, this is a BAD idea, since the 'original' DSP would overwrite any joined my $conf_file = $perl_temp_dir."\\temp.$pgmname.conf"; my $amlistfile = $perl_temp_dir."\\amlist.txt"; my $temp_copy_bat = $perl_temp_dir."\\tempcopy.bat"; my $miss_mac_file = $perl_temp_dir."\\missed_mscro_list.txt"; my $missing_list_file = $perl_temp_dir."\\missed_defined_list.txt"; my $missed_source_list = $perl_temp_dir."\\missed_source_list.txt"; my $missed_source_dsp = $perl_temp_dir."\\missed_source_dsp.txt"; my $missed_cond_list = $perl_temp_dir."\\missed_cond_list.txt"; # ========================================================== # test projects my $debug_on = 0; # run with DEFAULT, if no other input... my $def_file = 'C:\Projects\libxml2\configure.in'; my $def_targ = ''; #my $def_file = 'C:\Projects\giflib\configure.ac'; #my $def_file = 'C:\Projects\pcre\configure.ac'; #my $def_targ = 'C:\Projects\giflib\msvc'; #my $def_targ = ''; #my $def_file = 'C:\Projects\libsigc\libsigc++-2.2.8\configure.ac'; #my $def_targ = 'C:\Projects\libsigc\libsigc++-2.2.8\msvc'; #my $def_name = 'pcre'; my $def_name = ''; # ============================================================ my %g_default_condits = ( # default conditionals "USE_GLUT" => "TRUE", "ENABLE_JPEG_SERVER" => "FALSE", "ENABLE_SP_FDM" => "TRUE" ); ######################################## ### SHARED RESOURCES, VALUES ### ======================== our $fix_relative_sources = 1; our %g_user_subs = (); # supplied by USER INPUT our %g_user_condits = (); # conditionals supplied by the user # Auto output does the following - # For libaries # Debug: '/out:"lib\barD.lib"' # Release:'/out:"lib\barD.lib"' # for programs # Debug: '/out:"bin\fooD.exe"' # Release:'/out:"bin\foo.exe"' # This also 'adds' missing 'include' files #Bit: 1: Use 'Debug\$proj_name', and 'Release\$proj_name' for intermediate and out directories #Bit: 2: Set output to lib, or bin, and names to fooD.lib/foo.lib or barD.exe/bar.exe #Bit: 4: Set program dependence per library output directories #Bit: 8: Add 'msvc' to input file directory, if no target directory given #Bit: 16: Add program library dependencies, if any, to DSW file output. #Bit: 32: Add all necessary headers to the DSP file. That is scan the sources for #include "foo.h", etc. #Bit: 64: Write a blank header group even there are no header files for that component. #Bit: 128: Add defined item of HAVE_CONFIG_H to all DSP files. #Bit: 256: Exclude projects in SUBDIRS protected by a DEFINITION macro, else include ALL. #Bit: 512: Unconditionally add ANY libraries build, and NOT excluded to the last application #Bit:1024: If NO users conditional, do sustitution, if at all possible, regardless of TRUE or FALSE #Bit:2048: Add User -L dependent libraries to each application #Bit: These can be given as an integer, or the form 2+8, etc. Note using -1 sets ALL bits on. #Bit: Bit 32 really slows down the DSP creation, since it involves scanning every line of the sources. my $auto_max_bit = 512; our $auto_on_flag = -1; #Bit: ALL ON by default = ${$rparams}{'CURR_AUTO_ON_FLAG'} #my ($g_in_name, $g_in_dir); #my ($root_file, $root_folder); #sub get_root_dir() { return $root_folder; } our $exit_value = 0; # But SOME Makefile.am will use specific 'paths' so the above can FAIL to find # a file, so the following two 'try harder' options, will do a full 'root' # directory SCAN, and search for the file of that name in the scanned files our $try_harder = 1; our $try_much_harder = 1; # ============================================================================== our $process_subdir = 0; our $warn_on_plus = 0; # ============================================================================== # NOTE: Usually a Makefile.am contains SOURCE file names 'relative' to itself, # which is usually without any path. This options ADDS the path to the # Makefile.am, and then substracts the 'root' path, to get a SOURCE file # relative to the 'root' configure.ac, which is what is needed if the DSP # is to be placed in a $target_dir, and we want the file relative to that our $add_rel_sources = 1; our $target_dir = ''; # ============================================================================== our $ignore_EXTRA_DIST = 0; our $added_in_init = ''; our $supp_make_in = 0; # Support Makefile.in scanning our $project_name = ''; # a name to override any ac scanned name of the project ### ============================= # offsets into REF_LIB_LIST array my $RLO_MSG = 0; my $RLO_PRJ = 1; my $RLO_VAL = 2; my $RLO_NAM = 3; my $RLO_EXC = 4; ### ============================= # Add to this (IN LOWER CASE FORM) as new libraries are found... my @win_libs = qw( msimg32.lib imm32.lib winmm.lib ws2_32.lib shlwapi.lib ); sub is_win_library($) { my ($lib) = @_; my $lclib = lc($lib); my ($key); foreach $key (@win_libs) { return 1 if ($key eq $lclib); } return 0; } my %excluded_projects = (); my %joined_projects = (); # my $excluded_msg = '')) { return 1; } return 0; } my $dbg_lib_path = 0; my $in_input_file = 0; my %by_proj_includes = (); my $proj_incs = '/I "."'; my $proj_rt = 'D'; # ie use /MD and /MDd sub warn_unused_keys($$$) { my ($ruser,$rused,$msg) = @_; my ($key,$cnt); $cnt = 0; foreach $key (keys %{$ruser}) { if (!defined ${$rused}{$key}) { prtw("WARNING: UNUSED $msg key [$key]\n"); $cnt++; } } return $cnt; } my %by_proj_types = (); my %by_proj_typused = (); # GET -T project:type[:source_list] sub get_user_proj_type($$$) { my ($proj,$def,$rsrcs) = @_; ${$rsrcs} = ''; # ensure $addsrcs is cleared if (defined $by_proj_types{$proj}) { my (@arr,$cnt,$srcs,$msg); @arr = split(/:/,$by_proj_types{$proj}); $cnt = scalar @arr; $def = $arr[0]; $srcs = ''; $srcs = $arr[1] if ($cnt == 2); ${$rsrcs} = $srcs; $msg = "[v9] get_user_proj_type [$proj] [$def] ($cnt)"; $msg .= ", with srcs [$srcs]" if (length($srcs)); prt("$msg\n") if (VERB9()); $by_proj_typused{$proj} = 1; } return $def; } my $proj_defs = '/D "_CRT_SECURE_NO_WARNINGS"'; my %by_proj_defines = (); my %by_proj_defused = (); sub warn_missed_user_types() { my $msg = "Types"; my $cnt = scalar keys(%by_proj_types); my $res = 0; if ($cnt) { prt("[v9] Checking for unused $msg ($cnt)\n") if (VERB9()); $res = warn_unused_keys(\%by_proj_types,\%by_proj_typused,$msg); } return $res; } sub warn_missed_user_defined() { my $msg = "Defines"; my $cnt = scalar keys(%by_proj_defines); my $res = 0; if ($cnt) { prt("[v9] Checking for unused $msg ($cnt)\n") if (VERB9()); $res = warn_unused_keys(\%by_proj_defines,\%by_proj_defused,$msg); } return $res; } my %by_proj_libraries = (); my %by_proj_libraryD = (); my %by_proj_libraryR = (); my %by_proj_libsused = (); sub warn_missed_user_libs() { my $msg = "Libraries"; my $cnt = scalar keys(%by_proj_libraries); my $res = 0; if ($cnt) { prt("[v9] Checking for unused $msg ($cnt)\n") if (VERB9()); $res += warn_unused_keys(\%by_proj_libraries,\%by_proj_libsused,$msg); } $msg = "LibraryD"; $cnt = scalar keys(%by_proj_libraryD); if ($cnt) { prt("[v9] Checking for unused $msg ($cnt)\n") if (VERB9()); $res += warn_unused_keys(\%by_proj_libraryD,\%by_proj_libsused,$msg); } $msg = "LibraryR"; $cnt = scalar keys(%by_proj_libraryR); if ($cnt) { prt("[v9] Checking for unused $msg ($cnt)\n") if (VERB9()); $res += warn_unused_keys(\%by_proj_libraryR,\%by_proj_libsused,$msg); } return $res; } # NOTE: For user includes, usually also NEED 'libpath' # like $proj_libD .= " /libpath:\"Debug\" foo.lib"; # like $proj_libR .= " /libpath:\"Release\" foo.lib"; # OR # like $proj_lib .= " /libpath:\"lib\"; # like $proj_libD .= " fooD.lib"; # like $proj_libR .= " foo.lib"; # sub in line ADD LINK32 kernel32.lib ... -NEW_LIBS- /nologo ... my $proj_libs = 'Winmm.lib ws2_32.lib'; my $proj_libD = ''; my $proj_libR = ''; # NOTE: This is for say '/out:"bin\foo.exe"' or '/out:"lib\bar.lib"' my $proj_outputR = ''; my $proj_outputD = ''; # object output, and the default for other things if NOT specifically stated my $proj_interR = '"Release"'; my $proj_interD = '"Debug"'; ### program variables my @warnings = (); my $cwd = cwd(); my $os = $^O; my $conf_string = ''; my $only_dry_run = 0; my $in_file = ''; my $curr_command = ''; ######################################### ### DEBUG STUFF ### # Debug items SHARED with LIBRARY - note use of 'our' - to adjust this list # must also adjust the lib_acscan.pl library!!! our $dbg_lac01 = 0; # prt( "[01] scan_..._file: Reading $file\n" ) if $dbg_lac01; and more our $dbg_lac02 = 0; # show EACH line prt( "[02] $lnn: $cline... for each read line. our $dbg_lac03 = 0; # prt( "[03] Variable [$key] = [$nval]\n" ) our $dbg_lac04 = 0; # prt( "[04] Split to $vlen components ...\n" ) our $dbg_lac05 = 0; # prt( "[05] Substitute [$key] = [$nval]\n" ) if ($v1 ne $v2)) our $dbg_lac06 = 0; # prt( "[06] $.: Should JOIN lines? - [$cline]\n" ) and more... our $dbg_lac07 = 0; # prt( "[07] $.: Got AC_INIT = [$1]\n" ) and AC_DEFIN... etc our $dbg_lac08 = 0; # prt( "[08] Got ac_output_line = $. [$rawline]\n" ) plus accumulation our $dbg_lac09 = 0; # prt( "[01|09] Adding $input [$ff] to mk_inp_list ...\n" ) our $dbg_lac10 = 0; # prt( "[01|10] Adding $input [$ff] to other_input_files ...\n" ) our $dbg_lac11 = 0; # prt( "[11] Storing configure_cond key $1 ... value=2\n" ), and more our $dbg_lac12 = 0; # prt( "[12] $.: 1=[$1] = 2=[$2] NOT USED [$cline]\n" ) our $dbg_lac13 = 0; # prt("[13] $lnn: Failed on MACRO [$blk], in file [$file]\n") our $dbg_lac14 = 0; # show each MACRO split in FULL our $dbg_lac15 = 0; # Show each AC MACRO accumulation... our $dbg_lac16 = 0; # Show back slash accumulation... our $dbg_lac17 = 0; # show all substitutions our $dbg_lac18 = 0; # show setting or replacing each macro with value our $dbg_lac19 = 0; # unused at present our $dbg_lac20 = 0; # prt("[20] Directory SEARCH for [$test], found $fcnt... my $dbg_lac_check = 20; ######################################### # DEBUG for lib_amscan.pl our $dbg_s01 = 0; # show each file line, in form "[01] $i2: [$line]" our $dbg_s02 = 0; # show extraction from hash, like "Listing $acnt keys in hash ..." our $dbg_s03 = 0; # show "Find sources for $val LIBRARY keys ...\n" and MORE our $dbg_s04 = 0; # show prt( "LIBRARY [$ky] has SOURCES [$val] our $dbg_s05 = 0; # show prt( "$am ". ((-f $am) ? "ok" : "no find!") our $dbg_s06 = 0; # show prt( "Opened cond_stack with [".$cond_stack[$#cond_stack]."] $fil our $dbg_s07 = 0; # add new line before 'Processing $cnt lines..., as does 08 also... our $dbg_s08 = 0; # show prt( "Processing $cnt lines from $fil ... our $dbg_s09 = 0; # show prt( "Got $cnt subdirectories [$slist] ... our $dbg_s10 = 0; # show prtw("WARNING:1: No substitution for [$ms] found in hash ... our $dbg_s11 = 0; # show target: gathering of lines... our $dbg_s12 = 0; # show setting key=value in hash, during am file scan our $dbg_s13 = 0; # show initial substitution, during am file scan our $dbg_s14 = 0; # similar to about, but only show NO sub FOUND our $dbg_s15 = 0; # List each source, for each project... our $dbg_s16 = 0; # Like [02] list ALL keys showing dispostion our $dbg_s17 = 0; # Out CHECK ME - SHOULD THIS ITEMS BE INCLUDED for a prog,lib,src key, now skipped! our $dbg_s18 = 0; # show change due to adding relative directory our $dbg_s19 = 0; # show finds found by directory searching... our $dbg_s20 = 0; # output list of sources and header from dir scan, NOT included in a project our $dbg_s21 = 0; # prt("\n[21] Seeking 'all' or 'default' in $cnt keys...\n"), and MORE... our $dbg_s22 = 0; # show '[22]CHANGED:1: key [gatomic_c] cond [FALSE] Was [gatomic-gcc.c], now [gatomic.c] FALSE, plus our $dbg_s23 = 0; # debug the search for sub-directories to avoid our $dbg_s24 = 0; # output a list of ALL projects in $rlibs and $rprogs my $am_check_tot = 24; sub VERB1() { return ($verbosity > 0); } sub VERB2() { return ($verbosity > 1); } sub VERB5() { return ($verbosity > 4); } sub VERB9() { return ($verbosity > 8); } my $project_dbg_write = 0; sub set_all_dbg_on() { ac_set_all_dbg_on(); am_set_all_dbg_on(); } sub set_all_dbg_off() { ac_set_all_dbg_off(); am_set_all_dbg_off(); } sub set_max_debug_on() { $verbosity = 10; $project_dbg_write = -1; set_all_dbg_on(); #ac_set_dbg_extra(); prt("[debug_on] Have set MAXIMUM debug output...\n"); } sub wait_key() { prt("Any key to continue...\n"); my $char = <>; } # ***TBD*** this is NOW not called - see show_missing_subs2() instead # but perhaps this is better, in that it als adds those added automatically # but this is a 'conflict' between g_user_sub, and common_sub to be resolved sub show_missing_subs($) { my ($rsnf) = @_; if ($dbg_s13 || $dbg_s14) { my @arr = keys %{$rsnf}; my ($cnt,$txt,$key,$fil,$val,%hash,$msg); $txt = ''; if (@arr) { $cnt = scalar @arr; prt("[13|14] There are at least $cnt missing substitutions.\n"); $txt = "# [13|14] There are at least $cnt missing substitutions.\n"; if ($show_per_file) { %hash = (); foreach $key (@arr) { $fil = ${$rsnf}{$key}; push(@{$hash{$fil}},$key); } foreach $fil (keys %hash) { $val = $hash{$fil}; $cnt = scalar @{$val}; $txt .= "\n# Missing $cnt from file [$fil]\n"; prt("Missing $cnt ["); $msg = ''; foreach $key (sort @{$val}) { $txt .= "-m $key \"\"\n"; $msg .= ', ' if (length($msg)); $msg .= $key; } prt("$msg] from file [$fil]\n"); } } else { foreach $key (sort @arr) { $fil = ${$rsnf}{$key}; prt("Missing [$key], in [$fil]\n"); $txt .= "-m $key \"\"\n"; } } } else { prt("[13|14] There are NO missing substitutions.\n"); } @arr = split(/\s/,$added_in_init); $cnt = scalar @arr; if ($cnt) { prt("But note ADDED $cnt items, during init..."); if (length($miss_mac_file) && (length($txt))) { $txt .= "\n# Note the following set of $cnt items were added during init...\n"; %hash = (); init_common_subs2(\%hash,0); $cnt = 0; foreach $key (@arr) { if (defined $hash{$key}) { $val = $hash{$key}; if ( (length($val) == 0) || ($val =~ /^\s+$/) ) { $val = '""'; } $txt .= "-m $key $val\n"; $cnt++; } } prt(" also now added to response file..."); } prt("\n"); } if (length($miss_mac_file) && (length($txt))) { write2file($txt,$miss_mac_file); prt("Written list for use as '-r $miss_mac_file' response file, after correction.\n"); } } } # ============================================= sub show_warnings($) { my $val = shift; my $cnt = warn_missed_user_types(); $cnt += warn_missed_user_defined(); $cnt += warn_missed_user_libs(); if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } elsif ($cnt == 0) { prt("No warnings issued.\n"); } } sub show_missing_conds() { my $rparams = get_ref_params(); my $rmc = ${$rparams}{'REF_MISSED_CONDITIONS'}; my $cnt = scalar keys(%{$rmc}); if ($cnt) { if (VERB1()) { prt("[v1] List of $cnt missing conditionals...\n"); } else { prt("Would list $cnt missing conditionals... if verbose >= 1\n"); } my ($key,$val,$msg,@arr,$num,%dupes); $msg = "# List of $cnt missing conditionals...\n"; $msg .= "# If used ONLY in TRUE or FALSE, then parameter should be correct.\n"; $msg .= "# but if used TRUE and FALSE, then must select 0 or 1 only.\n"; $cnt = 0; foreach $key (sort keys %{$rmc}) { $cnt++; $val = ${$rmc}{$key}; @arr = split(/\|/,$val); %dupes = (); foreach $num (@arr) { $dupes{$num} = 1; } @arr = sort keys(%dupes); $val = ''; foreach $num (@arr) { $val .= '|' if (length($val)); $val .= $num; } $num = '0|1'; if (scalar @arr == 1) { if ($val eq 'FALSE') { $num = 0; } elsif ($val eq 'TRUE') { $num = 1; } else { $num .= '?'; } } else { $msg .= "# TO BE SELECTED\n"; } $msg .= "-c $key:$num\n"; prt(" $cnt: -c $key:$num ($val)\n") if (VERB1()); } if (length($missed_cond_list)) { write2file($msg,$missed_cond_list); prt("Written list of $cnt missing conditionals to [$missed_cond_list]\n"); } } else { prt("No missing conditionals listed.\n"); } } sub show_missing_subs2($) { my ($val) = shift; my $rparams = get_ref_params(); my $rsnf = ${$rparams}{'CURR_SUBS_NOT_FOUND'}; my @arr = keys %{$rsnf}; my $cnt = scalar @arr; my $msg = ''; #if ($dbg_lac13) { my ($key,$fil); if ($cnt) { $cnt = scalar @arr; prt("There are at least $cnt missing substitutions. "); if ($dbg_lac13) { prt("\n"); } else { prt("Use '-d 113' to view list...\n"); } foreach $key (sort @arr) { $fil = ${$rsnf}{$key}; prt("Missing [$key], in [$fil]\n") if ($dbg_lac13); $msg .= "-m $key \"\"\n"; } if (length($missing_list_file)) { write2file($msg,$missing_list_file); prt("List written to file [$missing_list_file] for review...\n"); } } else { prt("[13] There are NO missing substitutions.\n") if ($val == 0); } #@arr = split $added_in_init; #$cnt = scalar @arr; #prt("But note added $cnt, [$added_in_init] in init...\n") if (length($added_in_init)); #} elsif ($cnt && ($val == 0)) { # prt("There are at least $cnt missing substitutions. Use '-d 13' to view.\n"); #} } sub show_scanned_lines_and_time() { my $rparams = get_ref_params(); my ($cnt,$tim,$fil); if (defined ${$rparams}{'TOTAL_LINE_COUNT'} && defined ${$rparams}{'CURR_BEGIN_TIME'}) { $cnt = ${$rparams}{'TOTAL_LINE_COUNT'}; $tim = time(); $fil = $tim - ${$rparams}{'CURR_BEGIN_TIME'}; prt("Scanned a total of ".get_nn($cnt)." lines of source, in ".secs_HHMMSS($fil)." ...\n"); } } sub pgm_exit($$) { my ($val,$msg) = @_; show_missing_conds() if ($val == 0); show_missing_subs2($val) if ($val != 2); if (length($conf_string) && ($val == 0) && !$no_conf_write) { write2file($conf_string,$conf_file); prt("Written configuration to [$conf_file]\n"); } show_warnings($val) if ($val != 2); show_scanned_lines_and_time(); if (length($msg)) { prt("Current CMD: [$curr_command]\n") if (length($curr_command)); prt("\a\n") if ($msg =~ /^ERROR/); $msg =~ s/\n$//; $msg .= " time:".localtime(time())." ($val)\n"; prt("$msg\n"); } else { prt("Current CMD: [$curr_command] time [".localtime(time())."] ($val)\n"); } close_log($outfile,$load_log); exit($val); } my %warnings_done = (); my $last_warning = ''; sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; # avoid REPETATIVE warnings prt("$tx\n") if ($tx ne $last_warning); $last_warning = $tx; if (!defined $warnings_done{$tx}) { $warnings_done{$tx} = 1; push(@warnings,$tx); } } sub write_to_am_list($$) { my ($ff,$ok) = @_; if (length($amlistfile) && $write_am_list) { my $dff = path_u2d($ff); my ($nm,$dir) = fileparse($ff); my $typ = 3; if ($ok) { my $lcid = lc(path_u2d(get_root_dir())); # g_in_dir my $lcfd = lc($dir); if ($lcid eq $lcfd) { $typ = 1; } else { $typ = 2; } } if (-f $amlistfile) { if (open INF, "<$amlistfile") { my @lines = ; close INF; my ($line,@arr,$cnt,$fff); my $lcinf = lc($dff); foreach $line (@lines) { chomp $line; @arr = split(/\s/,$line); $cnt = scalar @arr; if ($cnt == 2) { $fff = lc($arr[1]); if ($fff eq $lcinf) { return; } } } } append2file("$typ $dff\n",$amlistfile); } else { write2file("$typ $dff\n",$amlistfile); } } } sub got_colon_split($) { my ($txt) = @_; my $len = length($txt); my ($i,$ch,$pc,$i2,$nc); $ch = ''; for ($i = 0; $i < $len; $i++) { $pc = $ch; $ch = substr($txt,$i,1); if ($ch eq ':') { # skip over LETTER : SLASH $i2 = $i + 1; $nc = ($i2 < $len) ? substr($txt,$i2,1) : ""; if (($nc =~ /(\\|\/)/) && ($pc =~ /\w+/)) { # next is slash - previous was letter - no split here } else { return 1; } } } return 0; } # take care with things like lib:C:\projs\lib - skip 'DRIVE_LETTER:\' sub colon_split($) { my ($txt) = @_; my $len = length($txt); my @arr = (); my ($i,$ch,$tag,$pc,$i2,$nc); $ch = ''; $tag = ''; for ($i = 0; $i < $len; $i++) { $pc = $ch; $ch = substr($txt,$i,1); $i2 = $i + 1; $nc = ($i2 < $len) ? substr($txt,$i2,1) : ""; if ($ch eq ':') { # skip over LETTER : SLASH if (($nc =~ /(\\|\/)/) && ($pc =~ /\w+/)) { # next is slash - previous was letter - no split here } else { #push(@arr,$tag) if (length($tag)); push(@arr,$tag); # even BLANK tags get pushed $tag = ''; # kill current tag next; # and go for NEXT } } $tag .= $ch; } push(@arr,$tag) if (length($tag)); return @arr; } sub process_ac_file($) { my ($rparams) = @_; my $inf = ${$rparams}{'CURR_FILE'}; return if (! -f $inf); #($g_in_name, $g_in_dir) = fileparse($inf); prt("Scanning [$inf] file... using lib_acscsn.pl:scan_configure_ac_file()\n"); scan_configure_ac_file($rparams,0); # ====================================================== show_ac_hash($rparams); return $rparams; } #==================================================== # do NOT know WHY I have 2 subs that do the SAME thing # sub sub_root_folder AND sub_root_dir($) sub sub_common_folder { my ($fil,$root) = @_; my $lfil = lc(path_u2d($fil)); my $lrot = lc(path_u2d($root)); my $len1 = length($lfil); my $len2 = length($lrot); my ($i); for ($i = 0; (($i < $len1)&&($i < $len2)); $i++) { if (substr($lfil,$i,1) ne substr($lrot,$i,1)) { last; } } return substr($fil,$i); } sub sub_root_folder { my ($fil) = shift; my $rd = get_root_dir(); return sub_common_folder($fil,$rd); } sub begins_with { my ($rt, $pt) = @_; my $ln = length($rt); my ($i); if (length($pt) >= $ln) { for ($i = 0; $i < $ln; $i++) { return 0 if (substr($rt,$i,1) ne substr($pt,$i,1)); } return 1; # does indeed begin with... } return 0; } sub sub_first_from_second_if($$) { my ($d1,$d2) = @_; if (being_with($d1,$d2)) { $d2 = substr($d2, length($d1)); } return $d2; } # VARIOUS FIXES FOR THE FILE NAME # 1. ensure ALL DOS format # 2. remove any simple dot relative, like '.\' from beginning # 3. if given a FULL PATH name, remove C:\FG\20\FlightGear # 4. if a relative name, remove FligthGear # 5. if any removal, ensure any beginning '\' is removed sub sub_root_dir($) { my ($ff) = shift; # = $a_dir.$src $ff = path_u2d($ff); my $rd = get_root_dir(); if (begins_with($rd, $ff)) { $ff = substr($ff, length($rd)); } return $ff; } sub set_anon_ref_hashes($) { my ($rparams) = @_; my %hash = (); my %targ = (); ${$rparams}{'CURR_REF_HASH'} = \%hash; ${$rparams}{'AM_FILE_TARGETS'} = \%targ; } sub process_one_am_file($); # Process a Makefile.am file sub process_one_am_file($) { my ($rparams) = @_; my $ramsdone = ${$rparams}{'REF_AMS_DONE'}; my $fil = ${$rparams}{'AM_FILE'}; $fil = fix_rel_path3($fil,'process_one_am_file'); my $sfil = sub_root_folder($fil); return if (defined ${$ramsdone}{$fil}); ${$ramsdone}{$fil} = 1; set_anon_ref_hashes($rparams); my $ramh = am_process_AM_file($rparams,0); my ($p_tit,$p_dir,$p_ext) = fileparse( $fil, qr/\.[^.]*/ ); my $do_subs = ${$rparams}{'PROCESS_SUBDIR'}; if ($do_subs && (defined ${$ramh}{'SUBDIRS'})) { my $slist = ${$ramh}{'SUBDIRS'}; my @ar = split(/\s+/,$slist); my $cnt = scalar @ar; prt( "[09] Got $cnt subdirectories [$slist] ...from [$sfil]\n" ) if ($dbg_s09); foreach my $dir (@ar) { my $am = $p_dir.$dir.'\Makefile.am'; $am = path_u2d($am); $am =~ s/\\\\/\\/g while ($am =~ /\\\\/); my $sam = sub_root_folder($am); if (-f $am) { prt( "[05] Processing AM file [$am], from [$fil] ...\n" ) if ($dbg_s05); ${$rparams}{'AM_FILE'} = $am; # DOS form ensured process_one_am_file($rparams); ${$rparams}{'AM_FILE'} = $fil; } else { prtw( "[05] WARNING: AM [$am] NOT FOUND! in [$dir], from [$fil]!\n" ) if ($dbg_s05); } } } return $ramh; } sub process_an_am_file($) { my ($rparams) = @_; my $rh = process_one_am_file($rparams); # iteratively process the Makefile.am files #list_to_arrays($fil,\%g_programs,\%g_libraries,\%g_ams_done); #list_to_arrays($rparams); ##write_temp_dsp($dsp_outfile); } # [dbg_v40] STORE:1: In rcfgs (ra)[Release], [-NEW_OUTD-], [Release|Win32], & $dsp_sub_sub ] ) # [dbg_v40] STORE:2: In rcfgs (ra)[Debug], [-NEW_OUTD-], [Debug|Win32], & $dsp_sub_sub ] ) sub set_default_configs_2($) { my ($rh) = @_; #my $var1 = "-NEW_OUTD-"; my $var1 = ""; my $rcfgs = get_project_configs($rh); # 'PROJECT_CFGS' my ($dsp_sub_sub,$confname,$conf); $dsp_sub_sub = get_default_sub3(0); $confname = 'Release'; $conf = 'Release|WIN32'; push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS' ${$rh}{'PROJECT_CCNT'}++; # count of stored 'PROJECT_CFGS $dsp_sub_sub = get_default_sub3(1); $confname = 'Debug'; $conf = 'Debug|WIN32'; push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS' ${$rh}{'PROJECT_CCNT'}++; # count of stored 'PROJECT_CFGS } # ########################################################### # get DSP replacement values # ========================== sub get_user_rt($$) { my ($flag,$proj) = @_; my $urt = ''; if ($proj_rt eq 'D') { if ($flag == 1) { $urt = '/MD'; } else { $urt = '/MDd'; } } else { if ($flag == 1) { $urt = '/MT'; } else { $urt = '/MTd'; } } prt("[v9] get_user_rt: flag=$flag, proj=$proj, return=[$urt]\n") if (VERB9()); return $urt; } # GET -L dependent libraries option ## NOTE: Bit 1 == Release, else Debug #my %by_proj_libraries = (); #my %by_proj_libraryD = (); #my %by_proj_libraryR = (); #my %by_proj_libsused = (); sub get_user_libs($$) { my ($flag,$proj) = @_; my $var1 = $proj_libs; my ($refh); if ((!defined $proj)||(length($proj) == 0)||($proj =~ /^\s+$/)) { pgm_exit(1,"ERROR: INTERNAL: get_user_libs call WITHOUT a PROJECT NAME!\n"); } if ($flag & 1) { $refh = \%by_proj_libraryR; if (length($proj_libR)) { $var1 .= " " if (length($var1)); $var1 .= $proj_libR; } } else { $refh = \%by_proj_libraryD; if (length($proj_libD)) { $var1 .= " " if (length($var1)); $var1 .= $proj_libD; } } if (defined $by_proj_libraries{$proj}) { $var1 .= ' '.$by_proj_libraries{$proj}; } if (defined ${$refh}{$proj}) { $var1 .= ' '.${$refh}{$proj}; } $by_proj_libsused{$proj} = 1; prt("[v9] get_user_libs: flag=$flag, proj=$proj, return=[$var1]\n") if (VERB9()); return $var1; } sub rationalise_lib_paths() { # need to CHECK the library paths, and # eliminate DUPLICATES my $rlist = get_user_libs(1,""); my $dlist = get_user_libs(2,""); my $rhr = space_split_to_rh($rlist); my $rhd = space_split_to_rh($dlist); my $plibs = ''; my $plibr = ''; my $plibd = ''; my ($key); foreach $key (keys %{$rhr}) { next if ($key =~ /^\/libpath:/); # do path second if (defined ${$rhd}{$key}) { # this is COMMON $plibs .= ' ' if (length($plibs)); $plibs .= $key; } else { # only for RELEASE $plibr .= ' ' if (length($plibr)); $plibr .= $key; } } foreach $key (keys %{$rhr}) { next if ( !($key =~ /^\/libpath:/) ); # do paths now if (defined ${$rhd}{$key}) { # this is COMMON $plibs .= ' ' if (length($plibs)); $plibs .= $key; } else { # only for RELEASE $plibr .= ' ' if (length($plibr)); $plibr .= $key; } } foreach $key (keys %{$rhd}) { next if ($key =~ /^\/libpath:/); # do path second if (defined ${$rhr}{$key}) { # this is COMMON - already done } else { # only for DEBUG $plibd .= ' ' if (length($plibd)); $plibd .= $key; } } foreach $key (keys %{$rhd}) { next if ( !($key =~ /^\/libpath:/) ); # do paths now if (defined ${$rhr}{$key}) { # this is COMMON - already done } else { # only for DEBUG $plibd .= ' ' if (length($plibd)); $plibd .= $key; } } if (($plibs ne $proj_libs)|| ($plibr ne $proj_libR)|| ($plibd ne $proj_libD)) { prt("LIB CHANGE: [$plibs] ne [$proj_libs] and/or\n". " [$plibr] ne [$proj_libR] and/or\n". " [$plibd] ne [$proj_libD] and/or\n") if ($dbg_lib_path); $proj_libs = $plibs; $proj_libR = $plibr; $proj_libD = $plibd; } } # NAH, perhpas do NOT need to do this... sub rationalise_proj_lib_path($) { my ($stg); my $rh = space_split_to_rh($stg); my ($key,$nstg); $nstg = ''; foreach $key (keys %{$rh}) { $nstg .= ' ' if (length($nstg)); $nstg .= $key; } return $nstg; } # FIX20110323 - changed from 'get_user_defs:' to 'get_user_incs:' # should ALSO allow DEFINES (-D) to also be in a BY PROJECT basis # my %by_proj_includes = (); sub get_user_incs($$) { my ($flag,$proj) = @_; my $pi = ''; if (defined $by_proj_includes{$proj}) { $pi .= $by_proj_includes{$proj}; $pi .= ' ' if (!($pi =~ /\s+$/) && length($proj_incs) && !($proj_incs =~ /^\s+/)); } $pi .= $proj_incs; prt("[v9] get_user_incs: flag=$flag, proj=$proj, return=[$pi]\n") if (VERB9()); return $pi; } sub get_user_defs($$) { my ($flag,$proj) = @_; my $pd = ''; if (defined $by_proj_defines{$proj}) { $pd .= $by_proj_defines{$proj}; $pd .= ' ' if (!($pd =~ /\s+$/) && length($proj_defs) && !($proj_defs =~ /^\s+/)); $by_proj_defused{$proj} = 1; } $pd .= $proj_defs; prt("[v9] get_user_defs: flag=$flag, proj=$proj, return=[$pd]\n") if (VERB9()); return $pd; } # Auto output does the following - # For libaries # Debug: '/out:"lib\barD.lib"' # Release:'/out:"lib\barD.lib"' # for programs # Debug: '/out:"bin\fooD.exe"' # Release:'/out:"bin\foo.exe"' # our $auto_on_flag = BITS = ${$rparams}{'CURR_AUTO_ON_FLAG'} sub get_user_output($$) { my ($flag,$proj) = @_; my $line = ''; if ($flag & 1) { if (length($proj_outputR)) { $line = $proj_outputR; } } elsif (length($proj_outputD)) { $line = $proj_outputD; } prt("[v9] get_user_defs: flag=$flag, proj=$proj, return=[$line]\n") if (VERB9()); return $line; } sub get_user_inter($$) { my ($flag,$proj) = @_; my $line = ''; if ( $flag & 1 ) { if (length($proj_interR)) { $line = $proj_interR; } else { $line = 'Release'; } } else { if (length($proj_interD)) { $line = $proj_interD; } else { $line = 'Debug'; } } return $line; } # setting defines # FIX20110323 - All a global define like '-D PATH=C:\some\path sub add_defined_item($) { my $txt = shift; my $msg = ''; # if ($txt =~ /:/) { if (got_colon_split($txt)) { my (@a,$cnt,$pj); #@a = split(/:/,$txt); @a = colon_split($txt); $cnt = scalar @a; pgm_exit(1,"ERROR: Define [$txt] did NOT split in 2! Must be say -D TESTNUM=1:signal1...\n") if ($cnt != 2); $txt = '/D "'.$a[0].'"'; $pj = $a[1]; if (defined $by_proj_defines{$pj}) { $txt = " $txt"; $by_proj_defines{$pj} .= $txt; } else { $by_proj_defines{$pj} .= $txt; } $msg = "only for project [$pj]."; } else { $msg = "globally."; $txt = '/D "'.$txt.'"'; $proj_defs .= ' ' if (length($proj_defs)); $proj_defs .= $txt; $proj_defs = eliminate_dupes($proj_defs); } prt("Added [$txt] to compiler defines $msg.\n"); } # SET a /I "include\path" # FIX20110323 - allow on by project basis '-I SOME_VALUE:project_only' # FIX20110803 - allow simple -I path1;path2;path3 sub add_include_item($) { my $cmd = shift; my $txt = $cmd; my (@a,$cnt,$pj); if (got_colon_split($txt)) { @a = colon_split($txt); $cnt = scalar @a; pgm_exit(1,"ERROR: Define [$txt] did NOT split in 2! Must be say -I C:\\some\\path:project\n") if ($cnt != 2); $txt = '/I "'.$a[0].'"'; $pj = $a[1]; if (defined $by_proj_includes{$pj}) { $txt = " $txt"; $by_proj_includes{$pj} .= $txt; } else { $by_proj_includes{$pj} = $txt; } prt("Added [$txt] to compiler includes for project [$pj].\n"); } else { @a = split(/;+/,$txt); $txt = ''; foreach $pj (@a) { if (length($pj)) { $txt .= " " if (length($txt)); $txt .= '/I "'.$pj.'"'; } } if (length($txt)) { $proj_incs .= ' ' if (length($proj_incs)); $proj_incs .= $txt; $proj_incs = eliminate_dupes($proj_incs); prt("Added [$txt] to global compiler includes.\n"); } else { pgm_exit(1,"ERROR: -I options FAILED to yield any /I paths! cmd = [$cmd]\n") } } } # ########################################################### # ========================== sub valid_rp_hash($) { my $rp = shift; #my $temp_copy_bat = ${$rp}{'PROJECT_COPY_BAT'}; my @arr = qw(PROJECT_NAME PROJECT_TYPE PROJECT_SOURCES PROJECT_TARGET PROJECT_DBG_WRITE PROJECT_FIX_REL PROJECT_AM_RHASH PROJECT_USER_LIBS PROJECT_USER_OUTS ); my ($key); foreach $key (@arr) { if (!defined ${$rp}{$key}) { prt("ERROR: $key NOT defined in project hash\n"); return 0; } } return 1; } sub fix_dir_string($) { my ($rdir) = @_; if (! ( ${$rdir} =~ /(\\|\/)$/) ) { ${$rdir} .= "\\"; } } sub is_same_file($$) { my ($f1,$f2) = @_; my $len = length($f1); return 0 if ($len != length($f2)); my ($i,$c1,$c2); for ($i = 0; $i < $len; $i++) { $c1 = lc(substr($f1,$i,1)); $c2 = lc(substr($f2,$i,1)); return 0 if ($c1 ne $c2); } return 1; } my @missed_dir_cmp = (); sub mark_in_dir_scan($$) { my ($rparams,$relfile) = @_; return if (! ${$rparams}{'CURR_DONE_SCAN'} ); #my $dir = ${$rparams}{'CURR_FILE_DIR'}; my $dir = ${$rparams}{'TARGET_DIR'}; fix_dir_string(\$dir); my $ff = $dir.$relfile; $ff = path_u2d($ff); $ff = fix_rel_path($ff); my $rda = ${$rparams}{'CURR_DIR_SCAN'}; my $cnt = scalar @{$rda}; my ($i,$file); ### prt("Mark in dir scan [$relfile] [$ff] of $cnt files...\n"); for ($i = 0; $i < $cnt; $i++) { $file = ${$rda}[$i][1]; # get FULL FILE if (is_same_file($ff,$file)) { # 0 1 2 3 #push(@{$rda},[$file,$ff,0,0]); ${$rda}[$i][2] = 1; last; } } if ($i >= $cnt) { push(@missed_dir_cmp,$ff); ### prt("Missed in dir scan [$relfile] [$ff] in $i files...\n"); } } sub file_in_array($$) { my ($file,$rxarr) = @_; my ($itm); my ($fil,$dir) = fileparse($file); foreach $itm (@{$rxarr}) { return 1 if ($itm eq $fil); } return 0; } sub prune_excluded_libs($$$) { my ($rparams,$proj_name,$cval) = @_; # if project itself is eXcluded, then keep ALL libs return $cval if ((length($cval) == 0)||($cval =~ /^\s+$/)); return $cval if (is_project_all_excluded($proj_name)); if ( defined ${$rparams}{'REF_JOINED_EXCLUDED'} ) { my $rxj = ${$rparams}{'REF_JOINED_EXCLUDED'}; my $nval = ''; # else PRUNE list for EXLUDED items my @arr = space_split($cval); my ($key,$val,$lib,$add); my %hash = (); prt("[v9] Pruning library list for project [$proj_name] [$cval]\n") if (VERB9()); foreach $key (keys %{$rxj}) { $val = ${$rxj}{$key}; if ($val == 1) { $hash{$key} = 1; #$lib = $key.".lib"; #$hash{$lib} = 1; } } foreach $key (@arr) { # RESTRICTION - libraries should be added WITHOUT a PATH $add = 1; if (is_win_library($key)) { $add = 1; } elsif ($key =~ /\.lib$/i) { # && !($key =~ /(\\|\/)/) ) $lib = $key; $lib =~ s/\.lib$//i; $lib =~ s/D$//; $add = 0 if (defined $hash{$lib}); } if ($add) { $nval .= ' ' if (length($nval)); $nval .= $key; } } prt("[v9] Project libs adjusted to [$nval]\n") if (VERB9() && ($cval ne $nval)); return $nval; } return $cval; } # need better guard against DUPLICATE source being added sub create_proj_dsp($$$$) { my ($fil,$odir,$rparams,$rp) = @_; if ( ! valid_rp_hash($rp) ) { prtw("WARNING: INTERNAL ERROR: 'project' HAS INVALID HASH! Check script!\n"); return; } my ($line,$key,$group,$filter,$ok,$rdir,$cfil,$cdir,$sfil,$tdsp,$msg); my ($name,$type,$i,$conf,$rh2,$flag,$cnt,$i2); my ($confname,$var1,$rcfgs); my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'}; my $proj_name = ${$rp}{'PROJECT_NAME'}; my $proj_type = ${$rp}{'PROJECT_TYPE'}; my $rinp_srcs = ${$rp}{'PROJECT_SOURCES'}; my $proj_targ = ${$rp}{'PROJECT_TARGET'}; my $dbg_write = ${$rp}{'PROJECT_DBG_WRITE'}; #my $temp_copy_bat = ${$rp}{'PROJECT_COPY_BAT'}; my $fix_rel = ${$rp}{'PROJECT_FIX_REL'}; my $rhash = ${$rp}{'PROJECT_AM_RHASH'}; # get AM file PROJECT hash my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # get the EXCLUDED (if any!) my $amfil = ${$rhash}{':_AM_FILE_SRC_:'}; my ($n,$d) = fileparse($amfil); my $dir = sub_root_dir($d); $dir =~ s/\\$//; # remove TAIL $msg = (defined ${$rex}{$dir}) ? "EXCLUDED" : "ok"; my $xsrcs = ''; my $isinx = is_project_src_excluded($proj_name,\$xsrcs); $xsrcs = '' if ($xsrcs eq ''); my ($xit); my @xarr = split(/;/,$xsrcs); my ($nm,$dr,$ex) = fileparse($fil, qr/\.[^.]*/ ); my $hr = get_default_ref_hash($fil); # this it the VERSION 1 $name = $proj_name; $tdsp = $odir; $tdsp .= "\\" if (!($tdsp =~ /(\\|\/)$/)); $tdsp .= $proj_name.".dsp"; $key = 'PROJECT_NAME'; ${$hr}{$key} = $proj_name; #$key = 'PROJECT_TYPE'; $key = 'PROJECT_APTP'; if ( get_app_type_4_short($proj_type, \$type) ) { ${$hr}{$key} = $type; prt("[v2] Set project type to [$type], from [$proj_type] $msg (dw=$dbg_write)\n") if (VERB2()); } else { pgm_exit(1,"ERROR: INTERNAL: Unable to get project type from [$proj_type]! Only 'CA', 'SL', 'DLL', 'WA'!\n"); } if ($isinx) { if (length($xsrcs)) { prt("[v9] project [$proj_type] eXcludes: [$xsrcs]\n") if (VERB9()); } else { prt("[v9] project [$proj_type] eXclude WHOLE PROJECT!\n") if (VERB9()); } } elsif (length($xsrcs)) { prtw("WARNING: INTERNAL: Have eXclude list [$xsrcs], but \$isinx not SET! ($isinx)\n"); } else { prt("[v9] project [$proj_type] NOT in eXclude\n") if (VERB9()); } ${$rp}{'PROJECT_DSP'} = $tdsp; ${$rp}{'PROJECT_DSP_TMP'} = $fil; my @sources = (); my %dupe_srcs = (); foreach $line (@{$rinp_srcs}) { next if (defined $dupe_srcs{$line}); $ok = 0; if ($fix_rel) { ($cfil,$cdir) = fileparse($line); # $rdir = get_relative_path($cdir,$odir); $rdir = get_rel_dos_path($cdir,$odir); $sfil = $rdir.$cfil; #prt("From [$line], to [$proj_targ], got rel [$sfil]\n"); prt("[v5] for [$line],\n to [$proj_targ], got\n") if (VERB5()); } else { $sfil = $line; } prt("[v2] Relative source [$sfil]\n") if (VERB2()); mark_in_dir_scan($rparams,$line); if (is_c_source_extended($line)) { # if (($line =~ /\.cxx$/i) || ($line =~ /\.c$/i) || ($line =~ /\.cpp$/i) || ($line =~ /\.cc$/i)) $filter = get_def_src_filt(); $group = get_def_src_grp(); $ok = 1; } elsif (is_h_source_extended($line)) { # elsif ( ($line =~ /\.hxx$/i) || ($line =~ /\.h$/i) || ($line =~ /\.hpp$/i) ) $filter = get_def_hdr_filt(); $group = get_def_hdr_grp(); $ok = 1; } elsif (is_resource_file($line)) { $filter = get_def_rcs_filt(); $group = get_def_rcs_grp(); $ok = 1; } if ($ok) { $xit = 0; # failed with ($xsrcs =~ /\b$sfil\b/) if ($isinx && length($xsrcs) && file_in_array($sfil,\@xarr)) { $xit = 1; prt("[v2] Excluding from build source [$sfil]\n") if (VERB5()); } # 0 1 2 3 push(@sources, [ $sfil, $group, $filter, $xit, '' ]); } else { prtw("WARNING: CHECK Discarded SOURCE item [$line]\n"); } $dupe_srcs{$line} = 1; $dupe_srcs{$sfil} = 1; } if (@sources) { $key = 'PROJECT_SRCS'; ${$hr}{$key} = [@sources]; } else { # pgm_exit(1,"ERROR: Project: [$proj_name] No sources!!!\n"); prtw("WARNING: Project: [$proj_name] No sources!!!\n"); } set_default_configs_2($hr); # set Release and Debug $key = 'PROJECT_CFGS'; if (defined ${$hr}{$key}) { $rcfgs = ${$hr}{$key}; $cnt = scalar @{$rcfgs}; prt( "[v5] Project: [$proj_name], got $cnt CONFIGS...\n" ) if (VERB5()); for ($i = 0; $i < $cnt; $i++) { $i2 = $i + 1; # 0 1 2 3 # Debug -NEW_OUTD- Debug|WIN32 # push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); $confname = ${$rcfgs}[$i][0]; #$var1 = ${$rcfgs}[$i][1]; # has no meaning!!! $conf = ${$rcfgs}[$i][2]; $rh2 = ${$rcfgs}[$i][3]; if (($conf =~ /Release/i)||($confname =~ /Release/i)) { $flag = 1; } elsif (($conf =~ /Debug/i)||($confname =~ /Debug/i)) { $flag = 2; } else { pgm_exit(1,"ERROR: Can NOT set config type as 'Release' or 'Debug'! Got [$conf] [$confname]\n"); } prt("[v5] $i2: [$conf] [$confname] ($flag) [$proj_name]\n") if (VERB5()); foreach $key (keys %{$rh2}) { $line = ${$rh2}{$key}; $var1 = $line; # start the SAME $msg = ''; if ($key eq '-NEW_OUT-') { # of form '/out:"bin\foo.exe"' $var1 = ${$rp}{'PROJECT_USER_OUTS'}->($flag,$line);; } elsif (($key eq '-NEW_OUTD-') || ($key eq '-NEW_INTER-')) { # Intermediate or Output DIRECTORY $var1 = get_user_inter($flag,$proj_name); if ($auto_on & 1) { if ($proj_name =~ /[\w\.-]+/) { if ($var1 eq '"Debug"') { $var1 = "\"Debug\\$proj_name\""; } elsif ($var1 eq '"Release"') { $var1 = "\"Release\\$proj_name\""; } } else { prtw("WARNING: auto_on_flag=$auto_on, but prog name [$proj_name] NOT just [an,.,-]??? CHECK ME\n"); } } } elsif ($key eq '-NEW_POST-') { # -NEW_POST- = [] } elsif ($key eq '-NEW_INCS-') { $var1 = get_user_incs($flag,$proj_name); # -NEW_INCS- = [] } elsif ($key eq '-NEW_LIBS-') { $var1 = ''; #if (($proj_type ne 'SL') && ($proj_type ne 'DLL')) { if ($proj_type ne 'SL') { # $var1 = get_user_libs($flag,$line); # -NEW_LIBS- = [Winmm.lib ws2_32.lib] # $var1 = ${$rparams}{'CURR_USER_LIBS'}->($flag,$line); $var1 = ${$rp}{'PROJECT_USER_LIBS'}->($flag,$proj_name); # = get_user_libs $var1 = prune_excluded_libs($rparams,$proj_name,$var1); } } elsif ($key eq '-NEW_DEFS-') { $var1 = get_user_defs($flag,$proj_name); # -NEW_DEFS- = [/D "_CRT_SECURE_NO_WARNINGS"] } elsif ($key eq '-NEW_RT-') { $var1 = get_user_rt($flag,$proj_name); # -NEW_RT- = [/MT] } else { prtw("WARNING: Key [$key] NOT in if table!?!?\n"); } if ($line ne $var1) { $msg = "changed to [$var1]"; ${$rh2}{$key} = $var1; } prt("[v9] $key = [$line] $msg\n") if (VERB9()); } } } else { pgm_exit(1,"INTERNAL ERROR: Hash does NOT have key [$key]!\n"); } if ($only_dry_run) { prt("Write of DSP to [$fil] AVOIDED, due to DRY RUN ON!\n") if ($dbg_write); return; } # prt("Writing DSP...\n"); if ( write_hash_to_DSP3( $fil, $hr, $dbg_write ) ) { prt("Written DSP to [$fil]\n") if ($dbg_write); } else { prtw("WARNING: FAILED TO WRITE DSP FILE!\n"); } } # 1: $(MACRO) # 2: ${MACRO} # 3: @MACRO@ # 4: $MACRO sub get_macro_type_and_key($$) { my ($txt,$rkey) = @_; my $typ = 0; my $key = ''; if ($txt =~ /^\$\((\w+)\)$/) { $key = $1; $typ = 1; # $(MACRO) } elsif ($txt =~ /^\$\{(\w+)\}$/) { $key = $1; $typ = 2; # ${MACRO} } elsif ($txt =~ /^\@(\w+)\@$/) { $key = $1; $typ = 3; # @MACRO@ } elsif ($txt =~ /^\$(\w+)$/) { $key = $1; $typ = 4; # $MACRO } ${$rkey} = $key; return $typ; } sub get_macro_new_value($$$$$) { my ($key,$rparams,$rhash,$rnval,$all) = @_; my $rus = ${$rparams}{'CURR_USER_SUBS'}; my $rcomsubs = ${$rparams}{'CURR_COMMON_SUBS'}; my $rglobhash = ${$rparams}{'REF_GLOBAL_HASH'}; my $nval = ''; my $fnd = 0; my ($tmp,@arr,$k,$v,$cnt); my ($ckey,$copt,$trfa,$usrtf,$msg); if (defined ${$rus}{$key}) { $nval = ${$rus}{$key}; $fnd = 4; } elsif (defined ${$rcomsubs}{$key}) { $nval = ${$rcomsubs}{$key}; $fnd = 3; } elsif (defined ${$rglobhash}{$key}) { $nval = ${$rglobhash}{$key}; $fnd = 5; } elsif (defined ${$rhash}{$key}) { $nval = ${$rhash}{$key}; $fnd = 1; } else { my $res = key_in_cond_TRUE_or_FALSE($key,$rhash,\$tmp); if ($res) { my $rdef_conds = ${$rparams}{'REF_DEF_CONDITIONS'}; my $rmis_conds = ${$rparams}{'REF_MISSED_CONDITIONS'}; $cnt = scalar @{$tmp}; prt("[23] Found condition key(s) $cnt\n") if ($dbg_s23); foreach $k (@{$tmp}) { $v = ${$rhash}{$k}; #next if ( !(length($v) && ((length($nval) == 0) || ($v ne $nval))) ); if ($k =~ /^(\w+)\s+if\s+(\w+)\@_(TRUE|FALSE)\@$/) { $ckey = $1; $copt = $2; $trfa = $3; $msg = "Per key [$k], got value [$v] opt [$copt] trfa [$trfa] ($all)"; if (defined ${$rdef_conds}{$copt}) { $usrtf = ${$rdef_conds}{$copt}; $msg .= " usr [$usrtf]"; if ($usrtf eq $trfa) { if ( length($v) && ((length($nval) == 0) || ($v ne $nval))) { $nval .= ' ' if (length($nval)); $nval .= $v; $msg .= " added"; } else { if (length($v)) { $msg .= " NOT added"; } else { $msg .= " NULL"; } } } else { if ($all) { if ( length($v) && ((length($nval) == 0) || ($v ne $nval))) { $nval .= ' ' if (length($nval)); $nval .= $v; $msg .= " ADDED"; } else { if (length($v)) { $msg .= " NOT ADDED"; } else { $msg .= " null"; } } } else { if (length($v)) { $msg .= "\n Discarded [$v] because NOT per user [$usrtf]"; } else { $msg .= ' Null'; } } } } else { $msg .= " NUD"; if ($all) { if ( length($v) && ((length($nval) == 0) || ($v ne $nval))) { $nval .= ' ' if (length($nval)); $nval .= $v; $msg .= " Added"; } else { $msg .= " not added"; } } else { prtw("WARNING:[1] Discarded value [$v], since [$copt] NOT user defined! TF [$trfa]\n"); if (defined ${$rmis_conds}{$copt}) { $v = ${$rmis_conds}{$copt}; if ( !($v =~ /$trfa/) ) { ${$rmis_conds}{$copt} .= "|$trfa"; } } else { ${$rmis_conds}{$copt} = $trfa; } $msg .= " DISCARDED"; } } prt("[23] $msg\n") if ($dbg_s23); } else { pgm_exit(1,"ERROR INTERNAL: Condition key [$k] DOES NOT CONFORM!\n"); } } $fnd = 2; } } ${$rnval} = $nval; return $fnd; } sub do_all_substitutions($$$$) { my ($line,$rparams,$rhash,$all) = @_; if (($line =~ /\$/)||($line =~ /\@\w+\@/)) { my ($itm,$typ,$key,$fnd,$nval,$cnt); my $oline = $line; my @arr = am_macro_split($line,0); # get only MACROS $cnt = scalar @arr; prt("[23] Processing substitutions in [$line] split $cnt...\n") if ($dbg_s23); foreach $itm (@arr) { $key = ''; $typ = get_macro_type_and_key($itm,\$key); prt("[23] Got macro type $typ, for [$itm] key [$key]\n") if ($dbg_s23); next if ($typ == 0); $nval = 'What!'; $fnd = get_macro_new_value($key,$rparams,$rhash,\$nval,$all); prt("[23] For [$key], got $fnd, nval = [$nval]\n") if ($dbg_s23); if ($typ == 1) { # 1: $(MACRO) $line =~ s/\$\($key\)/$nval/; } elsif ($typ == 2) { # 2: ${MACRO} $line =~ s/\$\{$key\}/$nval/; } elsif ($typ == 3) { # 3: @MACRO@ $line =~ s/\@$key\@/$nval/; } elsif ($typ == 4) { # 4: $MACRO $line =~ s/\$$key/$nval/; } else { pgm_exit(2,"ERROR INTERNAL: get macro type and key returned BAD type [$typ]! Should be 1 to 4!! [$itm] [$key] [$nval]\n"); } } if ($oline eq $line) { pgm_exit(2,"Problem: MACRO substitution FAILED\n"); } else { prt("[23] Line IN [$oline]\n") if ($dbg_s23); prt("[23] Line OUT [$line]\n") if ($dbg_s23); } } return $line; } sub sanitise_subdir_value($) { my $val = shift; my @arr = split(/\s+/,$val); my %h = (); # clear the HASH my ($v); foreach $v (@arr) { if (length($v) && ($v ne '.')) { $h{$v} = 1; } } @arr = keys %h; $val = ''; foreach $v (@arr) { $val .= ' ' if (length($val)); $val .= $v; } return $val; } sub hoh_process_value($$$$$$$) { my ($val,$dir,$sdir,$rsd,$all,$rparams,$key) = @_; my @arr = split(/\s+/,$val); my ($v,$msg,$sdcnt); my ($ckey,$copt,$trfa,$usrtf); my ($ff,$f); $sdcnt = 0; if ($key =~ /^(\w+)\s+if\s+(\w+)\@_(TRUE|FALSE)\@$/) { $ckey = $1; $copt = $2; $trfa = $3; my $rdef_conds = ${$rparams}{'REF_DEF_CONDITIONS'}; my $rmis_conds = ${$rparams}{'REF_MISSED_CONDITIONS'}; foreach $v (@arr) { $ff = $dir.$v; $f = $sdir.$v; $msg = " Subdir [$f]"; if (-d $ff) { $msg .= " ok"; } else { $msg .= " NOT FOUND" } if (! defined ${$rsd}{$f}) { if (defined ${$rdef_conds}{$copt}) { $usrtf = ${$rdef_conds}{$copt}; $msg .= " usr [$usrtf]"; if ($usrtf eq $trfa) { ${$rsd}{$f} = $ff; $msg .= " added"; } else { if ($all) { ${$rsd}{$f} = $ff; $msg .= " ADDED"; } else { $msg .= " NOT ADDED"; $msg .= "\n Discarded [$v] because NOT per user [$usrtf]"; } } } else { # NOT USER DEFINED $msg .= " NUD"; if ($all) { ${$rsd}{$f} = $ff; $msg .= " Added"; } else { $msg .= " DISCARDED"; prtw("WARNING:2: Discarded value [$v], since [$copt] NOT user defined! TF [$trfa]\n"); if (defined ${$rmis_conds}{$copt}) { $v = ${$rmis_conds}{$copt}; if ( !($v =~ /$trfa/) ) { ${$rmis_conds}{$copt} .= "|$trfa"; $msg .= "+"; } } else { ${$rmis_conds}{$copt} = $trfa; } } } } else { # aleady defined in the subdir list $msg .= " repeat"; } prt("[23] $msg\n") if ($dbg_s23); } # for each subdir } else { # NOT a TRUE FALSE key, so add em all foreach $v (@arr) { $ff = $dir.$v; $f = $sdir.$v; $msg = " subdir [$f]"; if (! defined ${$rsd}{$f}) { # get a final (rel) SUBDIR list ${$rsd}{$f} = $ff; $msg .= " added"; if (-d $ff) { $msg .= " ok"; } else { $msg .= " NOT FOUND" } } else { $msg .= " repeat"; } $sdcnt++; prt("[23] $sdcnt: $msg\n") if ($dbg_s23); } } } sub process_hoh_all($$) { my ($rparams,$all) = @_; my $rprojh = ${$rparams}{'REF_PROJECTS_HASH'}; my $rhohsubs = ${$rparams}{'REF_HOH_SUBS'}; my $ramsdone = ${$rparams}{'REF_AMS_DONE'}; my $amcnt = scalar keys(%{$ramsdone}); my ($file,$href,$val,$sfil,$key); my ($proj,$rp,$rhash,$amfil,$fnd,$cnt,@arr,$v); my ($tit,$dir,$sdir); my %done = (); my %missed = (); $cnt = 0; my %subdirs = (); my $rsd = \%subdirs; prt("\n[23] ") if ($dbg_s23); prt("Display of HOH SUBS... total $amcnt AM files... ($all)\n") if ($dbg_s23 || $all); foreach $proj (keys %{$rprojh}) { $rp = ${$rprojh}{$proj}; $rhash = ${$rp}{'PROJECT_AM_RHASH'}; # add to PROJECT hash $amfil = ${$rhash}{':_AM_FILE_SRC_:'}; next if (defined $done{$amfil}); next if (defined $missed{$amfil}); $fnd = 0; foreach $file (keys %{$rhohsubs}) { if ($file eq $amfil) { $fnd = 1; last; } } if ($fnd) { $cnt++; $sfil = sub_root_dir($amfil); $href = ${$rhohsubs}{$amfil}; ($tit,$dir) = fileparse($amfil); ($tit,$sdir) = fileparse($sfil); $sdir = '' if ($sdir =~ /^\.(\\|\/)$/); prt("[23] $cnt: FILE: [$sfil] [$sdir] [$amfil]\n") if ($dbg_s23); foreach $key (keys %{$href}) { $val = ${$href}{$key}; prt(" [23] $cnt: key [$key] [$val]\n") if ($dbg_s23); $val = sanitise_subdir_value($val); $val = trim_all(do_all_substitutions($val,$rparams,$rhash,$all)) if (length($val)); if (length($val)) { prt(" [23] After SUBS [$key] = [$val] ($all)\n") if ($dbg_s23); hoh_process_value($val,$dir,$sdir,$rsd,$all,$rparams,$key); } else { prt(" [23] [$key] = \n") if ($dbg_s23); } # ${$href}{$key} = $val; } $done{$amfil} = 1; } else { $missed{$amfil} = 1; } } prt("[23] Done $cnt AM files, with projects...\n") if ($dbg_s23); $fnd = 0; foreach $file (keys %{$rhohsubs}) { next if (defined $done{$file}); $fnd++; } if ($fnd) { prt("[23] Got $fnd AM files, without projects...\n") if ($dbg_s23); foreach $amfil (keys %{$rhohsubs}) { next if (defined $done{$amfil}); $cnt++; $sfil = sub_root_dir($amfil); $href = ${$rhohsubs}{$amfil}; ($tit,$dir) = fileparse($amfil); ($tit,$sdir) = fileparse($sfil); $sdir = '' if ($sdir =~ /^\.(\\|\/)$/); prt("[23] $cnt: FILE: [$sfil] [$sdir] [$amfil]\n") if ($dbg_s23); foreach $key (keys %{$href}) { $val = ${$href}{$key}; $val = sanitise_subdir_value($val); $val = trim_all(do_all_substitutions($val,$rparams,$rhash,$all)) if (length($val)); if (length($val)) { prt(" [23] After SUBS2 [$key] = [$val]\n") if ($dbg_s23); hoh_process_value($val,$dir,$sdir,$rsd,$all,$rparams,$key); } else { prt(" [23] [$key] = \n") if ($dbg_s23); } # ${$href}{$key} = $val; } $done{$amfil} = 1; } prt("[23] Done total $cnt AM files, with and without projects...\n") if ($dbg_s23); } $fnd = scalar keys(%missed); if ($fnd) { prt("[23] Problem: missed $fnd files...\n") if ($dbg_s23); foreach $file (keys %missed) { $cnt++; prt(" [23] $cnt: [$file]\n") if ($dbg_s23); } } $fnd = scalar keys(%{$rsd}); prt("[23] END HOH - All $cnt files processed... ($amcnt) ($all)... $fnd subdirs...\n") if ($dbg_s23); return $rsd; } sub process_hoh_subs($) { my ($rparams) = @_; my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'}; my ($key,$cnt); $cnt = 0; my %excluded = (); my $rex = \%excluded; if ($auto_on & 256) { my $rsdall = process_hoh_all($rparams,1); my $rsddef = process_hoh_all($rparams,0); $key = scalar keys(%{$rsdall}); $cnt = scalar keys(%{$rsddef}); prt("[23] Got $key subdirs for all, and $cnt for reduced...\n") if ($dbg_s23); $cnt = 0; foreach $key (keys %{$rsdall}) { if (! defined ${$rsddef}{$key}) { $cnt++; } } if ($cnt) { prt("Got $cnt sub-directories EXCLUDED...\n"); $cnt = 0; foreach $key (keys %{$rsdall}) { if (! defined ${$rsddef}{$key}) { $cnt++; prt("[23] $cnt: [$key]\n") if ($dbg_s23); ${$rex}{$key} = 1; } } } else { prt("AH! Got NO subdirectories EXCLUDED...\n"); } } else { prt("EXCLUDE BIT:256 is OFF. No projects excluded.\n"); } ${$rparams}{'AM_EXCLUDED_DIRS'} = $rex; # store the EXCLUDED (if any!) return $rex; } sub get_EXCLUDE_msg($$$) { my ($rparams,$rp,$rex) = @_; my $proj_name = ${$rp}{'PROJECT_NAME'}; #prt("Checking $proj_name...\n") if ($proj_name =~ /libpangocairo/); return "EXCLUDED (by -x)" if (is_project_all_excluded($proj_name)); my $rhash = ${$rp}{'PROJECT_AM_RHASH'}; # get AM file PROJECT hash my $amfil = ${$rhash}{':_AM_FILE_SRC_:'}; my ($n,$d) = fileparse($amfil); my $dir = sub_root_dir($d); $dir =~ s/\\$//; # remove TAIL my $msg = "ok"; # $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # store the EXCLUDED (if any!) if (defined ${$rex}{$dir}) { $msg = "EXCLUDED (by dir)"; } #prt("Not all excluded $proj_name...\n") if ($proj_name =~ /libpangocairo/); if ( defined ${$rparams}{'REF_JOINED_EXCLUDED'} ) { my $rxj = ${$rparams}{'REF_JOINED_EXCLUDED'}; if ( defined ${$rxj}{$proj_name} ) { if ( ${$rxj}{$proj_name} == 1 ) { $msg = "EXCLUDED (by -j)"; #prt("Returning $msg\n") if ($proj_name =~ /libpangocairo/); #} else { # prt("WHY VALUE ".${$rxj}{$proj_name}."?\n") if ($proj_name =~ /libpangocairo/); } #} else { # my @arr = keys(%{$rxj}); # prt("WHY NOT DEFINED??? keys [".join(', ',@arr)."]\n") if ($proj_name =~ /libpangocairo/); } } return $msg; } sub get_excluded_by_joined($) { my ($rparams) = @_; my $rph = ${$rparams}{'REF_PROJECTS_HASH'}; my $pcnt = scalar keys(%{$rph}); my $rjp = ${$rparams}{'REF_JOINED_PROJS'}; # = \%joined_projects; my ($proj_name,$bad,$self,@arr,$cnt,$type,$list,$proj_type,$srcs,$fnd1,$key); my ($rp1,$prj,$fnd2,$rp,$ky2,$val,$msg); my $fndlist = ''; my %hexj = (); $list = ''; my $hr = \%hexj; $cnt = scalar keys(%{$rjp}); prt("[v9] get_excluded_by_joined: Got $cnt keys in rjp, $pcnt in rph...\n") if (VERB9()); return $hr if ($cnt == 0); foreach $proj_name (keys %{$rjp}) { $bad = 0; $self = 0; $val = ${$rjp}{$proj_name}; # prt("Get joined, thus excluded for [$proj_name], [$val]...\n"); @arr = space_split($val); $cnt = scalar @arr; if ($cnt != 2) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$val] did not split correctly! ($cnt)\n"); next; } $type = $arr[0]; $list = $arr[1]; @arr = split(/:/,$type); $cnt = scalar @arr; if (($cnt < 1)||($cnt > 2)) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$type] did not split correctly! ($cnt)\n"); next; } $proj_type = $arr[0]; $srcs = ($cnt == 2) ? $arr[1] : ''; # potential semicolon sep list, or nothing if ( !get_app_type_4_short($proj_type, \$msg) ) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] did resolve!\n"); next; } $fnd1 = 0; foreach $key (keys %{$rph}) { $rp1 = ${$rph}{$key}; $prj = ${$rp1}{'PROJECT_NAME'}; if ($prj eq $proj_name) { $fnd1 = 1; last; } } @arr = split(/;/,$list); my @parr = (); # prt("Scan rph for [$list] ".scalar @arr." ...($fnd1)\n"); foreach $ky2 (@arr) { $fnd2 = 0; foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $prj = ${$rp}{'PROJECT_NAME'}; if ($ky2 eq $prj) { $fnd2 = 1; if ($prj eq $proj_name) { $self++; # already have this project hash } else { push(@parr,$rp); # keep this for later } last; } } if (!$fnd2) { prtw("ERROR: WARNING: Joining [$proj_name], NOT FOUND [$ky2] in rph!\n"); $bad = 1; last; } } if ( $self && (! $fnd1 || ($self != 1)) ) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] found and not found!!! ($self vs $fnd1)\n"); $bad = 1; } if (!@parr) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] not found join projects!!!\n"); $bad = 1; } next if ($bad); ${$hr}{$proj_name} = 2; $fndlist .= ' ' if (length($fndlist)); $fndlist .= $proj_name; foreach $rp (@parr) { $prj = ${$rp}{'PROJECT_NAME'}; ${$hr}{$prj} = 1; $fndlist .= ";$prj"; } } $msg = ""; $cnt = 0; foreach $key (keys %{$hr}) { $val = ${$hr}{$key}; $msg .= ", " if (length($msg)); $msg .= "$key:$val"; $cnt++; } prt("[v9] Excluded by JOIN: $fndlist. k:v [$msg]\n") if (length($fndlist) && VERB9()); return $hr; # hash - keys is list of EXCLUDED by join if value = 1, joined name if 2 } # got destination project name - $proj,$type,$srcs or none,$list # $joined_projects{$proj} = "$type:$srcs $list"; sub process_joined_projects($) { my ($rparams) = @_; my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'}; my $rjp = ${$rparams}{'REF_JOINED_PROJS'}; # = \%joined_projects; my $rph = ${$rparams}{'REF_PROJECTS_HASH'}; my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # store the EXCLUDED (if any!) my $rlib_dupes = ${$rparams}{'REF_LIB_DUPES'}; # = \%lib_dupes; my ($prj,$proj_name,$rp1,$key,$val,$fnd1,$bad,$cnt,$type,$list); my ($srcs,$msg,$rp,$ky2,@arr,$fnd2,@parr,$self); my ($val2,$isexcl,$rhash,$src,$rinp_srcs,$rsrc); my ($proj_type,$tmp); $bad = 0; # issue a WARNING - FAILED IN JOIN foreach $proj_name (keys %{$rjp}) { $bad = 0; $self = 0; $val = ${$rjp}{$proj_name}; prt("\nJoining [$proj_name], [$val]... (dw=$project_dbg_write)\n"); @arr = space_split($val); $cnt = scalar @arr; if ($cnt != 2) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$val] did not split correctly! ($cnt)\n"); next; } $type = $arr[0]; $list = $arr[1]; @arr = split(/:/,$type); $cnt = scalar @arr; if (($cnt < 1)||($cnt > 2)) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$type] did not split correctly! ($cnt)\n"); next; } $proj_type = $arr[0]; $srcs = ($cnt == 2) ? $arr[1] : ''; # potential semicolon sep list, or nothing if ( !get_app_type_4_short($proj_type, \$msg) ) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] did resolve!\n"); next; } $fnd1 = 0; foreach $key (keys %{$rph}) { $rp1 = ${$rph}{$key}; $prj = ${$rp1}{'PROJECT_NAME'}; if ($prj eq $proj_name) { $fnd1 = 1; last; } } @arr = split(/;/,$list); @parr = (); foreach $ky2 (@arr) { $fnd2 = 0; foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $prj = ${$rp}{'PROJECT_NAME'}; if ($ky2 eq $prj) { $fnd2 = 1; if ($prj eq $proj_name) { $self++; # already have this project hash } else { push(@parr,$rp); # keep this for later } last; } } if (!$fnd2) { prtw("ERROR: WARNING: Joining [$proj_name], finding [$ky2] NOT FOUND!\n"); $bad = 1; last; } } if ( $self && (! $fnd1 || ($self != 1)) ) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] found and not found!!! ($self vs $fnd1)\n"); $bad = 1; } if (!@parr) { prtw("ERROR: INTERNAL: Joining [$proj_name] of [$proj_type] not found join projects!!!\n"); $bad = 1; } next if ($bad); if (!$fnd1) { if (defined ${$rph}{$proj_name}) { $rp1 = ${$rph}{$proj_name}; $prj = ${$rp1}{'PROJECT_NAME'}; ${$rp1}{'PROJECT_NAME'} = $proj_name; prtw("WARNING: Join [$proj_name], CONFLICT with existing [$prj] already in HASH\n". "may or may not be a PROBLEM?\n"); } else { # Must setup a NEW project reference, to pass inspection, like # my @arr = qw(PROJECT_NAME PROJECT_TYPE PROJECT_SOURCES PROJECT_TARGET PROJECT_DBG_WRITE # PROJECT_FIX_REL PROJECT_AM_RHASH PROJECT_USER_LIBS PROJECT_USER_OUTS ); my %p = (); my %h = (); $rp1 = \%p; ${$rph}{$proj_name} = $rp1; $rp = $parr[0]; ${$rp1}{'PROJECT_USER_LIBS'} = ${$rparams}{'CURR_USER_LIBS'}; # get_user_libs ${$rp1}{'PROJECT_USER_OUTS'} = ${$rparams}{'CURR_USER_OUTS'}; # normal fetch for 'out:puts' ${$rp1}{'PROJECT_SOURCES'} = [ ]; ${$rp1}{'PROJECT_TARGET'} = ${$rp}{'PROJECT_TARGET'}; ${$rp1}{'PROJECT_DBG_WRITE'} = ${$rp}{'PROJECT_DBG_WRITE'}; ${$rp1}{'PROJECT_FIX_REL'} = ${$rp}{'PROJECT_FIX_REL'}; ${$rp1}{'PROJECT_AM_RHASH'} = \%h; my $addsrcs = ''; # GET -T project:type[:source_list] $tmp = get_user_proj_type($proj_name,$proj_type,\$addsrcs); # get any additional user sources prtw("WARNING: -J type [$proj_type] NOT EQUAL -T type [$tmp]! Choosing -J type.\n") if ($tmp ne $proj_type); if (length($addsrcs)) { $srcs .= ';' if (length($srcs) && !($srcs =~ /;$/)); $srcs .= $addsrcs; prt("[15] Added sources from -T option [$addsrcs]\n") if ($dbg_s15); } # need to 'fix' CURR_USER_OUTS... if ($auto_on & 2) { # = $auto_on_flag set_new_user_outs($rp1,$proj_name,$proj_type); $msg = "Bit: 2: key [$key], pn [$proj_name] [$proj_type] - fetch R:'"; $msg .= ${$rp1}{'PROJECT_USER_OUTS'}->(1,$proj_name); $msg .= "' D:'"; $msg .= ${$rp1}{'PROJECT_USER_OUTS'}->(2,$proj_name); $msg .= "'"; prt("[15] $msg\n") if ($dbg_s15); if (($proj_type eq 'SL')||($proj_type eq 'DLL')) { if (! defined ${$rlib_dupes}{$proj_name}) { ${$rlib_dupes}{$proj_name} = 1; my %h = (); $h{$key} = $proj_name; ${$rparams}{'CURR_LIB_SUBS'} = [] if (!defined ${$rparams}{'CURR_LIB_SUBS'}); $tmp = ${$rparams}{'CURR_LIB_SUBS'}; push(@{$tmp}, \%h); } } } else { prt("[15] Bit: 2: auto output is OFF\n") if ($dbg_s15); } } } $rinp_srcs = ${$rp1}{'PROJECT_SOURCES'}; foreach $src (@{$rinp_srcs}) { if (length($src)) { $srcs .= ';' if (length($srcs)); $srcs .= $src; } } $rhash = ${$rp1}{'PROJECT_AM_RHASH'}; ${$rhash}{':_AM_FILE_SRC_:'} = "User INPUT"; ${$rp1}{'PROJECT_TYPE'} = $proj_type; ${$rp1}{'PROJECT_NAME'} = $proj_name; # phew - got project hash, for join name $proj, or not if NEW ($self set if same name # found each of the projects to be JOINED to $proj, in @parr... # NOW JOIN THEM $val2 = $dsp_out_dir."\\temp.$proj_name.dsp"; $msg = get_EXCLUDE_msg($rparams,$rp1,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; ${$rp1}{'PROJECT_TARGET'} = $target_dir; ${$rp1}{'PROJECT_DBG_WRITE'} = $project_dbg_write; ${$rp1}{'PROJECT_FIX_REL'} = 0; # source array already FIXED, relative to $target_dir foreach $rp (@parr) { $rsrc = ${$rp}{'PROJECT_SOURCES'}; $prj = ${$rp}{'PROJECT_NAME'}; set_exclude_project("-j",$prj,0); # exclude from DSW foreach $src (@{$rsrc}) { if (length($src)) { $srcs .= ';' if (length($srcs)); $srcs .= $src; } } # should ALSO check PROJECT_USER_LIBS and maybe fix } my @src_arr = (); push(@src_arr, split(/;/,$srcs)); ${$rp1}{'PROJECT_SOURCES'} = \@src_arr; prt("Create JOINED DSP for project [$proj_name]...$msg\nCombined sources [$srcs]\n"); create_proj_dsp($val2,$target_dir,$rparams,$rp1); prt("Done JOINED DSP for [$proj_name]\n"); # prtw("WARNING: JOIN CODE YET TO BE FULLY CHECKED!\n"); } } sub get_proj_user_libs($$$) { my ($rp,$rll,$rdeps) = @_; my $pnm = ${$rp}{'PROJECT_NAME'}; # get a list like # like $proj_libD .= " /libpath:\"Debug\" fooD.lib"; my $tmp = ${$rp}{'PROJECT_USER_LIBS'}->(1,$pnm); $tmp .= ${$rp}{'PROJECT_USER_LIBS'}->(2,$pnm); my @arr = space_split($tmp); my %liblist = (); my $retlibs = ''; my ($itm); foreach $itm (@arr) { next if ($itm =~ /^\/libpath/); $itm =~ s/\.lib$//; $itm =~ s/D$//; if (defined ${$rll}{$itm}) { if (!defined ${$rdeps}{$itm}) { if (!defined $liblist{$itm}) { $liblist{$itm} = 1; $retlibs .= ' ' if (length($retlibs)); $retlibs .= $itm; } } } } return $retlibs; } # if ( is_project_all_excluded($nm2) ) sub is_dependency_excluded($$$$) { my ($rparams,$pnm,$isexcl,$nm2) = @_; # if the prog itself is being eXclude, then ADD ALL dependencies #prt("Checking add $nm2, to $pnm...\n") if ($nm2 =~ /libpangocairo/); return 0 if ($isexcl); # else, if the depedencey is ALL eXclude, then do NOT add this return 1 if (is_project_all_excluded($nm2)); # else, check if dependency is now eXcluded, by virtue is joined to another #prt("Dep $nm2 not all excluded...\n") if ($nm2 =~ /libpangocairo/); if ( defined ${$rparams}{'REF_JOINED_EXCLUDED'} ) { my $rxj = ${$rparams}{'REF_JOINED_EXCLUDED'}; if ( defined ${$rxj}{$nm2} ) { if ( ${$rxj}{$nm2} == 1 ) { #prt("Dep not added to $pnm...\n") if ($nm2 =~ /libpangocairo/); return 1; #} else { # prt("Dep added to $pnm, due ".${$rxj}{$nm2}." value\n") if ($nm2 =~ /libpangocairo/); } #} else { # prt("Dep $nm2 not DEFINED?...\n") if ($nm2 =~ /libpangocairo/); } } return 0; # ok to ADD this dependency to MAIN DSW } # ================================================================ # Now add 'missed' headers # ================================================================ sub write_project_DSP_DSW_files($) { my ($rparams) = @_; my $rph = ${$rparams}{'REF_PROJECTS_HASH'}; my $cnt = scalar keys(%{$rph}); my ($key,$rp,$val,$val2,$dsp,$msg,$n,$d); $key = 'PROJECT_NAME'; # should have been set by AC_INIT(...) MACRO my $proj_title = 'tempprojname'; if (defined ${$rparams}{$key}) { $proj_title = ${$rparams}{$key}; } my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'}; my $rex = process_hoh_subs($rparams); # get EXCLUDED sub-directories my ($proj_type,$xcnt,$pnm,$tmp,$nm2,@arr); prt("\nCreating DSP files for $cnt projects [$proj_title]...\n"); $xcnt = 0; #my %lib_list = (); # list of LIBRARIES written my $rlib_lists = ${$rparams}{'REF_LIB_LISTS'}; # make list of LIBRARIES written my $sl_cnt = 0; my $ca_cnt = 0; my $dll_cnt = 0; my $wa_cnt = 0; my $ot_cnt = 0; my ($tot_libs,$tot_apps); my $lab = ''; my ($rdtxt,$isexcl,$lkey); # ***TBD*** this should be MOVED to lib_params ${$rparams}{'REF_JOINED_PROJS'} = \%joined_projects; ${$rparams}{'REF_JOINED_EXCLUDED'} = get_excluded_by_joined($rparams); $ot_cnt = scalar keys(%{$rph}); prt("[v9] Scanning, and typing $ot_cnt keys in rph...\n") if (VERB9()); foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $val = ${$rp}{'PROJECT_NAME'}; $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; $val2 = ''; $proj_type = ${$rp}{'PROJECT_TYPE'}; get_app_type_4_short($proj_type, \$val2); $dsp = ${$rp}{'PROJECT_USER_OUTS'}->(1,""); prt("[v9] key [$key] name [$val] [$val2] [$dsp] $msg\n") if (VERB9()); $xcnt++ if ($isexcl); #my $RLO_MSG = 0; #my $RLO_PRJ = 1; #my $RLO_VAL = 2; #my $RLO_NAM = 3; #my $RLO_EXC = 4; if ($proj_type eq 'SL') { # 0 1 2 3 4 ${$rlib_lists}{$val} = [ $msg, $rp, 0, $val, $isexcl ]; # keep library LIST written, and whether ok or EXCLUDED $sl_cnt++; } elsif ($proj_type eq 'CA') { $ca_cnt++; } elsif ($proj_type eq 'DLL') { ${$rlib_lists}{$val} = [ $msg, $rp, 0, $val, $isexcl ]; # keep library LIST written, and whether ok or EXCLUDED $dll_cnt++; } elsif ($proj_type eq 'WA') { $wa_cnt++; } else { prtw("WARNING: Binary [$val] NOT 'SL', 'CA', 'DLL', 'WA'! It is [$proj_type]?\n") if ($ot_cnt == 0); $ot_cnt++; } } $tot_libs = $sl_cnt + $dll_cnt; $tot_apps = $ca_cnt + $wa_cnt; if ($do_joined_first) { # create DSP for JOINED, if any # ============================= process_joined_projects($rparams); # ============================= } prt("Doing DSP for SL=$sl_cnt, DLL=$dll_cnt, CA=$ca_cnt, WA=$wa_cnt.\n"); prt("NOTE: $xcnt projects are EXCLUDED from the DSW.\n") if ($xcnt); # create DSP for LIBRARIES foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $proj_type = ${$rp}{'PROJECT_TYPE'}; next if ( !(($proj_type eq 'SL')||($proj_type eq 'DLL')) ); $val = ${$rp}{'PROJECT_NAME'}; $val2 = $dsp_out_dir."\\temp.$val.dsp"; $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; prt("\nCreate DSP for project [$val]...$msg\n") if ($project_dbg_write); ${$rp}{'PROJECT_TARGET'} = $target_dir; ${$rp}{'PROJECT_DBG_WRITE'} = $project_dbg_write; ${$rp}{'PROJECT_FIX_REL'} = 0; # source array already FIXED, relative to $target_dir create_proj_dsp($val2,$target_dir,$rparams,$rp); $dsp = ${$rp}{'PROJECT_DSP'}; } # create DSP for APPS foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $proj_type = ${$rp}{'PROJECT_TYPE'}; next if (($proj_type eq 'SL')||($proj_type eq 'DLL')); $val = ${$rp}{'PROJECT_NAME'}; $val2 = $dsp_out_dir."\\temp.$val.dsp"; $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; prt("\nCreate DSP for project [$val]...$msg\n") if ($project_dbg_write); ${$rp}{'PROJECT_TARGET'} = $target_dir; ${$rp}{'PROJECT_DBG_WRITE'} = $project_dbg_write; ${$rp}{'PROJECT_FIX_REL'} = 0; # source array already FIXED, relative to $target_dir create_proj_dsp($val2,$target_dir,$rparams,$rp); $dsp = ${$rp}{'PROJECT_DSP'}; } if (!$do_joined_first) { # create DSP for JOINED, if any # ============================= process_joined_projects($rparams); # ============================= } # done DSP, and joined DSP, now DSW $rph = ${$rparams}{'REF_PROJECTS_HASH'}; my $dswreal = "$proj_title.dsw"; my $dswfull = $target_dir.$dswreal; my $dswtemp = $dsp_out_dir."\\temp.$dswreal"; my $dswtexc = $dsp_out_dir."\\temp.excluded.$dswreal"; my $dswexcl = $target_dir."excluded.$dswreal"; my $cbtemp = $temp_copy_bat; # = $dsp_out_dir."tempcopy.bat"; $cnt = scalar keys(%{$rph}); if ($cnt) { if ($only_dry_run) { prt("\nSummary of $cnt project DSP files that would be written, if NOT DRY RUN!\n"); } elsif (VERB1()) { prt("\n[v1] Summary of $cnt project DSP files written...\n"); } } else { prt("\nEEK! It looks like NO project DSP files written!\n"); } # =============================================== # Ouput the DSW file my $dswtxt = get_dsw_head(); my $dswtxt2 = get_dsw_head(); my $cbtxt = "\@echo Copy of $cnt DSP, plus the DSW to target directory\n"; $cbtxt .= "\@echo Target is [$target_dir]\n"; $cbtxt .= "\@if EXIST $target_dir".". goto GOTTARG\n"; $cbtxt .= "\@echo ERROR: Appears TARGET directory does NOT EXIST!\n"; $cbtxt .= "\@goto END\n"; $cbtxt .= ":GOTTARG\n"; $cbtxt .= "\@if \"%1x\" == \"x\" goto DNCMD\n"; $cbtxt .= "\@if \"%1x\" == \"NOPAUSEx\" goto DNCMD\n"; $cbtxt .= "\@echo ERROR: Only input allowed is 'NOPAUSE'\n"; $cbtxt .= "\@goto END\n"; $cbtxt .= ":DNCMD\n"; $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" (\n"; $cbtxt .= "\@echo Due to TEMPNP, will unconditionally OVERWRITE existing files, if any.\n"; $cbtxt .= ") else (\n"; $cbtxt .= "\@echo Setting TEMPNP=yes in the environment will skip more pauses, if file exists.\n"; $cbtxt .= ")\n"; $cbtxt .= "\@if \"\%1x\" == \"NOPAUSEx\" goto DNP1\n"; $cbtxt .= "\@echo *** CONTINUE? ***\n"; $cbtxt .= "\@pause\n"; $cbtxt .= ":DNP1\n"; $cbtxt .= "\n"; # need to add copying EXCLUDE, if any $cnt = 0; my %depends = (); my %dupe_in_dsw = (); # Do LIBRARIES first foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $proj_type = ${$rp}{'PROJECT_TYPE'}; next if ( !(($proj_type eq 'SL')||($proj_type eq 'DLL')) ); $pnm = ${$rp}{'PROJECT_NAME'}; next if (defined $dupe_in_dsw{$pnm}); $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; $dupe_in_dsw{$pnm} = "$key:$proj_type:$msg:$isexcl"; $dsp = "$pnm.dsp"; $val = ${$rp}{'PROJECT_DSP'}; ($n,$d) = fileparse($val); $val2 = ${$rp}{'PROJECT_DSP_TMP'}; $val = '"'.$val.'"' if ($val =~ /[\s\+]+/); $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/); $cnt++; $lab = "DOCOPY$cnt"; $cbtxt .= "\@if NOT EXIST $val goto $lab\n"; $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n"; $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n"; $cbtxt .= "\@pause\n"; $cbtxt .= ":$lab\n"; $cbtxt .= "\@echo Copying $n...\n"; $cbtxt .= "\@copy $val2 $val >nul\n"; # ==================================================================== $rdtxt = \$dswtxt; # default to MAIN DSW for $proj_title $rdtxt = \$dswtxt2 if ($isexcl); # if eXcluded, switch to excluded DSW # ==================================================================== ${$rdtxt} .= get_proj_begin( $pnm, $dsp ); %depends = (); # INSERT PROJECT DEPENDENCIES *** if (defined ${$rp}{'PROJECT_DEPENDS'}) { if ($auto_on & 16) { my $rpda = ${$rp}{'PROJECT_DEPENDS'}; $msg .= ' with deps ['; # CHECK if this is NOT EXCLUDED foreach $nm2 (@{$rpda}) { $msg .= " $nm2"; if (defined ${$rlib_lists}{$nm2}) { $tmp = ${$rlib_lists}{$nm2}; if (${$tmp}[$RLO_MSG] =~ /EXCLUDE/) { prtw("WARNING: Dependent name [$nm2] is EXCLUDED!\n"); } ${$tmp}[$RLO_VAL] = 1; ${$rlib_lists}{$nm2} = $tmp; } else { prtw("WARNING: This name [$nm2] NOT in LIBRARY LIST!\n"); } # now, joined, done just before this, can ADD to excluded, so... # if ( is_project_all_excluded($nm2) ) if ( is_dependency_excluded($rparams,$pnm,$isexcl,$nm2) ) { $msg .= " EXCLUDED"; } elsif (!defined $depends{$nm2}) { ${$rdtxt} .= " Begin Project Dependency\n"; ${$rdtxt} .= " Project_Dep_Name $nm2\n"; ${$rdtxt} .= " End Project Dependency\n"; $depends{$nm2} = 1; } } $msg .= ']'; } else { $msg .= " add depend NOT enabled (16)"; } } else { # ***TBD*** FIX20101029 - But should ALWAYS add -L lib_name:[D|R|B] with NO specific PROJECT # if ($proj_type ne 'SL') $msg .= ' NO depends'; if (($proj_type ne 'SL') && ($auto_on & 16) && ($auto_on & 2048)) { $tmp = get_proj_user_libs($rp,$rlib_lists,\%depends); if (length($tmp)) { @arr = split(/ /,$tmp); $tmp = scalar @arr; $msg .= " Bit:2048 + $tmp"; foreach $nm2 (@arr) { if (!defined $depends{$nm2}) { if ( is_dependency_excluded($rparams,$pnm,$isexcl,$nm2) ) { $msg .= " +$nm2:EXLCUDED"; } else { ${$rdtxt} .= " Begin Project Dependency\n"; ${$rdtxt} .= " Project_Dep_Name $nm2\n"; ${$rdtxt} .= " End Project Dependency\n"; $depends{$nm2} = 1; $msg .= " +$nm2"; } } } } } } ${$rdtxt} .= get_proj_end(); prt("Project [$key], for [".sub_root_dir(strip_quotes($val))."]\n") if (VERB1()); prt("[v9] Written [$val2] $msg\n") if (VERB9()); } # Do APPLICATIONS second my $dcnt = 0; foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $proj_type = ${$rp}{'PROJECT_TYPE'}; next if (($proj_type eq 'SL')||($proj_type eq 'DLL')); $pnm = ${$rp}{'PROJECT_NAME'}; next if (defined $dupe_in_dsw{$pnm}); $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; $dupe_in_dsw{$pnm} = "$key:$proj_type:$msg:$isexcl"; $dsp = "$pnm.dsp"; $val = ${$rp}{'PROJECT_DSP'}; ($n,$d) = fileparse($val); $val2 = ${$rp}{'PROJECT_DSP_TMP'}; $val = '"'.$val.'"' if ($val =~ /[\s\+]+/); $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/); $dcnt++; $cnt++; $lab = "DOCOPY$cnt"; $cbtxt .= "\@if NOT EXIST $val goto $lab\n"; $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n"; $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n"; $cbtxt .= "\@pause\n"; $cbtxt .= ":$lab\n"; $cbtxt .= "\@echo Copying $n...\n"; $cbtxt .= "\@copy $val2 $val >nul\n"; # ==================================================================== $rdtxt = \$dswtxt; # default to MAIN DSW for $proj_title $rdtxt = \$dswtxt2 if ($isexcl); # if eXcluded, switch to excluded DSW # ==================================================================== ${$rdtxt} .= get_proj_begin( $pnm, $dsp ); # INSERT PROJECT DEPENDENCIES *** %depends = (); if (defined ${$rp}{'PROJECT_DEPENDS'}) { if ($auto_on & 16) { my $rpda = ${$rp}{'PROJECT_DEPENDS'}; $msg .= ' with deps ['; # CHECK if this is NOT EXCLUDED foreach $nm2 (@{$rpda}) { $msg .= " $nm2"; if (defined ${$rlib_lists}{$nm2}) { $tmp = ${$rlib_lists}{$nm2}; if (${$tmp}[$RLO_MSG] =~ /EXCLUDE/) { prtw("WARNING: Dependent name [$nm2] is EXCLUDED!\n"); } ${$tmp}[$RLO_VAL] = 1; ${$rlib_lists}{$nm2} = $tmp; } else { prtw("WARNING: This name [$nm2] NOT in LIBRARY LIST!\n"); } # now, joined, done just before this, can ADD to excluded, so... # if ( is_project_all_excluded($nm2) ) if ( is_dependency_excluded($rparams,$pnm,$isexcl,$nm2) ) { $msg .= " EXCLUDED"; } elsif (!defined $depends{$nm2}) { ${$rdtxt} .= " Begin Project Dependency\n"; ${$rdtxt} .= " Project_Dep_Name $nm2\n"; ${$rdtxt} .= " End Project Dependency\n"; $depends{$nm2} = 1; } } $msg .= ']'; if (($dcnt + 1) == $tot_apps) { # this is the LAST application if ($auto_on & 512) { # check the LIBRARY DEPENDANCE $dcnt = 0; foreach $lkey (keys %{$rlib_lists}) { $tmp = ${$rlib_lists}{$lkey}; if (${$tmp}[2] == 0) { $msg = ${$tmp}[0]; if ($msg =~ /ok/) { $nm2 = ${$tmp}[$RLO_NAM]; # now, joined, done just before this, can ADD to excluded, so... # if ( is_project_all_excluded($nm2) ) if ( is_dependency_excluded($rparams,$pnm,$isexcl,$nm2) ) { $msg .= " EXCLUDED"; } elsif (!defined $depends{$nm2}) { ${$rdtxt} .= " Begin Project Dependency\n"; ${$rdtxt} .= " Project_Dep_Name $nm2\n"; ${$rdtxt} .= " End Project Dependency\n"; $depends{$nm2} = 1; } ${$tmp}[$RLO_VAL] = 1; } } ${$rlib_lists}{$lkey} = $tmp; } } } } else { $msg .= " add depend NOT enabled (16)"; } } else { # ***TBD*** FIX20101029 - But should ALWAYS add -L lib_name:[D|R|B] with NO specific PROJECT # if ( is_project_all_excluded($nm2) ) { # if ($proj_type ne 'SL') $msg .= ' NO depends'; if (($proj_type ne 'SL') && ($auto_on & 16) && ($auto_on & 2048)) { $tmp = get_proj_user_libs($rp,$rlib_lists,\%depends); if (length($tmp)) { @arr = split(/ /,$tmp); $tmp = scalar @arr; $msg .= " Bit:2048 + $tmp"; foreach $nm2 (@arr) { if (!defined $depends{$nm2}) { if ( is_dependency_excluded($rparams,$pnm,$isexcl,$nm2) ) { $msg .= " +$nm2:EXLCUDED"; } else { ${$rdtxt} .= " Begin Project Dependency\n"; ${$rdtxt} .= " Project_Dep_Name $nm2\n"; ${$rdtxt} .= " End Project Dependency\n"; $depends{$nm2} = 1; $msg .= " $nm2"; if (defined ${$rlib_lists}{$nm2}) { $tmp = ${$rlib_lists}{$nm2}; ${$tmp}[$RLO_VAL] = 1; } } } } } } } ${$rdtxt} .= get_proj_end(); prt("Project [$key], for [".sub_root_dir(strip_quotes($val))."]\n written [$val2] $msg\n") if (VERB1()); } if ($cnt) { # check the LIBRARY DEPENDANCE $dcnt = 0; foreach $lkey (keys %{$rlib_lists}) { $tmp = ${$rlib_lists}{$lkey}; if (${$tmp}[$RLO_VAL] == 0) { $msg = ${$tmp}[$RLO_MSG]; if ($msg =~ /ok/) { prtw("WARNING: No dependence on library [$lkey] created!\n"); $dcnt++; } else { prt("No dependence on library [$lkey] created, but $msg!\n"); } } } if ($dcnt) { prtw("WARNING: Need to add a project to use the $dcnt library dependency! ***TBD**\n"); } $dswtxt .= get_dsw_tail(); $dswtxt2 .= get_dsw_tail(); $cnt++; $lab = "DOCOPY$cnt"; $val = $dswfull; ($n,$d) = fileparse($val); $val2 = $dswtemp; $val = '"'.$val.'"' if ($val =~ /[\s\+]+/); $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/); prt("\nFor project [$proj_title] DSW [".sub_root_dir(strip_quotes($val))."]\n") if (VERB1()); $cbtxt .= "\@if NOT EXIST $val goto $lab\n"; $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n"; $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n"; $cbtxt .= "\@pause\n"; $cbtxt .= ":$lab\n"; $cbtxt .= "\@echo Copying $n...\n"; $cbtxt .= "\@copy $val2 $val >nul\n"; $cnt++; $lab = "DOCOPY$cnt"; $val = $dswexcl; $val2 = $dswtexc; ($n,$d) = fileparse($val); $val = '"'.$val.'"' if ($val =~ /[\s\+]+/); $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/); prt("For project [$proj_title] DSW [".sub_root_dir(strip_quotes($val))."]\n") if (VERB1() && $xcnt); $cbtxt .= "\@if NOT EXIST $val goto $lab\n"; $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n"; $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n"; $cbtxt .= "\@pause\n"; $cbtxt .= ":$lab\n"; $cbtxt .= "\@echo Copying $n...\n"; $cbtxt .= "\@copy $val2 $val >nul\n"; # ===================================================================== # finish OFF copy batch file $cbtxt .= "\@echo All $cnt copied, done...\n"; $cbtxt .= "\@echo Change to [$target_dir], and run MSVC... Good luck ;=))\n"; $cbtxt .= ":END\n"; if ($only_dry_run) { prt(" would write [$dswtemp]...if NOT DRY RUN\n") if (VERB1()); } else { # primary DSW file rename_2_old_bak_plus($dswtemp); write2file($dswtxt,$dswtemp); prt("[v9] Written [$dswtemp]...\n") if (VERB9()); # EXCLUDED DSW file rename_2_old_bak_plus($dswtexc); write2file($dswtxt2,$dswtexc); prt("[v9] Written [$dswtexc]...\n") if (VERB9() && $xcnt); write2file($cbtxt,$cbtemp); prt("Written BATCH file [$cbtemp], to COPY the $cnt 'temp' DSW/DSP files\n to TARGET [$target_dir]... "); if (-d $target_dir) { prt("ok\n"); } else { prt("WARNING: DOES NOT EXIST!\n"); } } } else { prt("No project DSP files written, nor a DSW! Sorry...\n"); } } sub process_am_list($) { my ($rparams) = @_; my ($key,$val,$cnt,$ky2,$val2,$len,$min,$ff,$ok); my $inf = ${$rparams}{'CURR_FILE'}; my $rh = ${$rparams}{'CURR_HASH'}; my $supp_make_in = ${$rparams}{'SUPP_MAKE_IN'}; my ($in_name, $in_dir) = fileparse($inf); $key = 'A_MAKE_INPUT_LIST'; if (defined ${$rh}{$key}) { $val = ${$rh}{$key}; $cnt = scalar @{$val}; prt("\nprocess_am_list: $key with $cnt items in array..."); prt(" NOTE: NO ITEMS TO PROCESS!") if ($cnt == 0); # 25/12/2010 - really show NO 'am' files prt("\n"); # try to get the ROOT AM FILE foreach $ky2 (@{$val}) { $ff = $in_dir.$ky2.".am"; if (-f $ff) { if (!($ky2 =~ /(\\|\/)/)) { ${$rparams}{'ROOT_AM_FILE'} = $ff; last; } } elsif ($supp_make_in) { $ff = $in_dir.$ky2.".in"; if (-f $ff) { if (!($ky2 =~ /(\\|\/)/)) { ${$rparams}{'ROOT_AM_FILE'} = $ff; last; } } } } foreach $ky2 (@{$val}) { $ff = path_u2d($in_dir.$ky2.".am"); if (-f $ff) { $ok = ".am ok"; ${$rparams}{'AM_FILE'} = $ff; } elsif ($supp_make_in) { $ff = path_u2d($in_dir.$ky2.".in"); if (-f $ff) { $ok = ".in ok"; ${$rparams}{'AM_FILE'} = $ff; } else { $ok = "'am' or 'in' NOT FOUND [$ff]"; } } else { $ok = "'am' NOT FOUND [$ff]"; } if ($ok =~ /ok/) { process_an_am_file($rparams); } else { prtw("WARNING: Missing AM File: [$ky2] $ok\n"); } } } if (defined ${$rparams}{'ROOT_AM_FILE'}) { ${$rparams}{'AM_FILE'} = ${$rparams}{'ROOT_AM_FILE'}; } } sub get_perl_temp_dir() { if (! -d $perl_temp_dir) { mkdir $perl_temp_dir; if (! -d $perl_temp_dir) { pgm_exit(1,"ERROR: Unable to create directory [$perl_temp_dir]\nMaybe there is already a file of that name, or...\n"); } } } sub do_sanity_check() { pgm_exit(1,"ERROR: Problem with lib_acscan DEBUG!\n Count ".ac_get_dbg_range()." versus dbg_lac_check=$dbg_lac_check\n") if (ac_get_dbg_range() != $dbg_lac_check); pgm_exit(1,"ERROR: Problem with lib_amscan DEBUG!\nCount ".am_get_dbg_range()." versus am_check_tot=$am_check_tot\n") if (am_get_dbg_range() != $am_check_tot ); get_perl_temp_dir(); } sub set_out_file_names($) { my $dir = shift; $dir .= "\\" if (!($dir =~ /(\\|\/)$/)); $conf_file = $dir."temp.$pgmname.conf"; $amlistfile = $dir."amlist.txt"; $temp_copy_bat = $dir."tempcopy.bat"; $miss_mac_file = $dir."missed_mscro_list.txt"; $missing_list_file = $dir."missed_defined_list.txt"; $missed_source_list = $dir."missed_source_list.txt"; $missed_source_dsp = $dir."missed_source_dsp.txt"; $missed_cond_list = $dir."missed_cond_list.txt"; } sub module_intialisation($) { my ($fil) = @_; set_out_file_names($dsp_out_dir); #my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'}; set_blank_header_group(0) if ( !($auto_on_flag & 64) ); # my $proj_defs = '/D "_CRT_SECURE_NO_WARNINGS"'; add_defined_item('HAVE_CONFIG_H') if ($auto_on_flag & 128); my $rparams = init_common_subs($fil); ${$rparams}{'CURR_MISSED_SOURCES'} = $missed_source_list; ${$rparams}{'CURR_MISSED_SRCDSP'} = $missed_source_dsp; return $rparams; } ######################################### ### MAIN ### # check the DEBUG stuff is ok do_sanity_check(); parse_args(@ARGV); my $rph = module_intialisation($in_file); # establish $root_folder, and init %g_common_subs process_ac_file($rph); # mainly to get substitutions, and get the Makefile AM file output list process_am_list($rph); # process EACH Makefile.AM individually # 25/12/2010 - check for existance of the 'Makefile.am' to scan #if (defined ${$rph}{'AM_FILE'}) { # my $in_fil = ${$rparams}{'AM_FILE'}; am_list_to_arrays($rph); # move the AM information into 'project' HASHES #} else { # # 25/12/2010 - indication of FAILURE to find anything to scan... # pgm_exit(3,"ERROR: No 'Makefile' am/in/or ? to scan..."); #} write_project_DSP_DSW_files($rph); # write the 'project' HASHES to DSP, and finally a DSW am_out_dir_scan_info($rph); if ($exit_value) { pgm_exit($exit_value,"Exit, with error $exit_value"); } else { pgm_exit($exit_value,"Normal exit(0)"); } ######################################## ### COMMAND LINE PARSING ### sub show_dbg_ranges() { my ($max,$tmp); $max = ac_get_dbg_range(); prt(" --dbg (-d) = Set DEBUG flag of this value.\n"); prt(" For AC lib_acscan, numbers in range 101 to 1$max\n"); $max = am_get_dbg_range(); prt(" For AM lib_amscan, numbers in range 201 to 2$max\n"); $tmp = ac_get_dbg_stg(); prt(" Presently $tmp are ON in lib_acscan.\n") if (length($tmp)); $tmp = am_get_dbg_stg(); prt(" Presently $tmp are ON in lib_amscan.\n") if (length($tmp)); prt(" Text setting are 'all', 'none', 'extra', and 'help'.\n"); } sub give_help { my ($tmp); prt("$pgmname: $my_version\n"); prt("Usage: $pgmname [options] in-file\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt("Purpose:\n"); prt(" Scan the input file as a configure.ac file, then scan the Makefile.am entries indicated by the\n"); prt(" AC_OUTPUT macro, and output MSVC DSW/DSP build files for the contents found.\n"); prt("NOTES:\n"); prt(" Auto output does the following, and more: For libraries: D:'/out:\"lib\\barD.lib\"'; R:\n"); prt(" '/out:\"lib\\barD.lib\"'. For programs: D:'/out:\"bin\\fooD.exe\"'; R:'/out:\"bin\\foo.exe\"'\n"); prt(" Use '-a help' for fuller list of this 'auto' feature BIT effects.\n"); prt(" Do NOT add the /D or /I to the macro defined or included. This will be added internally,\n"); prt(" and note the upper case for -D, -I and -L.\n"); prt(" Setting a macro is 3 entries, like '-m item value', thus if set a blank is required, use\n"); prt(" '-m item \"\"'. Macros substitutions found missing are written to the file\n"); prt(" [$miss_mac_file] for review, and then use\n"); prt(" as a '-r ' response input file.\n"); prt(" The debug switch is strictly for that. It adds no functionality, just a noisier output,\n"); prt(" and thus allow a DEBUG view of what the script 'saw', and 'did' to potentially\n"); prt(" 'fix' the script.\n"); prt(" Unless there are two commands using the same letter, normally case, and after the first\n"); prt(" letter are ignored.\n"); prt(" The LIB consists of . The 'name' can be a single name, or\n"); prt(" a semicolon separated list of library names. The 'path' can be blank, absolute, or\n"); prt(" relative to the 'target' directory of the program DSP. D=Debug, R=Release, B=Both. If no optional\n"); prt(" project name is given, then the library (or libs) are added to all, except Static Libraries (SL).\n"); prt(" RESTRICTION - libraries should be added WITHOUT a PATH. The 'path' should only be given as 2nd value.\n"); prt("Options:\n"); prt(" --auto on|off|v (-a) = Automate certain preferred outputs. '-a help' for MORE. (def=$auto_on_flag)\n"); prt(" --cond item (-c) = Set a CONDITIONAL item. Can add [:1|0]. Default is 1 (TRUE).\n"); show_dbg_ranges(); prt(" --DEF mac[:nam] (-D) = Add a global defined macro, OR to a specific ':project', if given.\n"); prt(" --INC (-I) = Add an include macro, like '/I \"path\"', to the DSP compile.\n"); prt(" Add :project to add an include on a per project basis.\n"); prt(" --join nam list (-j) = Join the semicolon separated 'list', to project of type, like 'nam:type'.\n"); prt(" Can be 'a:t a;b;c', or 'd:t a;b;c'. Type is per -T below, and\n"); prt(" can have semicolon separated sources following another colon.\n"); prt(" --LIB (-L) = Add a global dependant libraries, to programs being built,\n"); prt(" OR to just to a specific project, if given. See NOTES:\n"); prt(" --load-log (-l) = Load log file at end. (def=".($load_log ? "On" : "Off").")\n"); prt(" --mac item val (-m) = Store a MACRO, item=value, for substitution. (use '-d 13' to list missing).\n"); prt(" --name (-n) = Overrride any name in the AC_INIT/AM_INIT_AUTOMAKE.\n"); prt(" --out (-o) = Give existing DSP output directory, relative or absolute.\n"); prt(" Will NOT be created. (def=$dsp_out_dir).\n"); # prt(" --previous (-p) = Load previous commands from [$conf_file]\n") if (-f $conf_file); prt(" --resp (-r) = Commands from a reponse/input file.\n"); prt(" --RT [D|T] (-R) = Set global RUNTIME. D=/MD|/MDd T=/MT|/MTd (def=$proj_rt).\n"); # FIX20110306 - Set project RUNTIME - either 'T'=static, or 'D'=DLL (default) prt(" --supp_in (-s) = Support Makefile.in, if NO Makefile.am found. (def=$supp_make_in)\n"); prt(" --TYPE nm:type (-T) = Set other than default types for project name : types CA|WA|SL|DLL, and\n"); prt(" the type can be followed with additional 'sources'. name:type:src1;src2;...\n"); prt(" --targ (-t) = Establish a target directory for the DSW/DSP files.\n"); prt(" --verbosity (-v) = Bump verbosity of this module. Default [$verbosity] to 9 (-vvvvvvvvv)\n"); prt(" --wr_dbg (-w) = Add debug during the DSP write output. Bit values. -1 for all.\n"); prt(" --xclude (-x) = Exclude a 'project', or sources, from a project. A 'set' consists of\n"); prt(" a project names, optionally followed, after a colon,\n"); prt(" by a semi-colon separated list of sources. eg proj:src1;src2'...\n"); } sub show_dbg_help() { my $file = $0; my ($line,$max,$tmp,$cnt,$tmp2); show_dbg_ranges(); if (open INF, "<$file") { my @lines = ; close INF; prt(" Detailed list, with some 'notes' indicating what each does.\n"); $cnt = 0; my @ac_dbg = (); my @am_dbg = (); foreach $line (@lines) { $line = trim_all($line); if ($line =~ /^our\s+\$dbg_lac(\d+)\s*=\s*\d+\s*;\s*#(.+)$/) { $tmp = $1; $tmp2 = $2; push(@ac_dbg,"1$tmp: $tmp2"); $cnt++; } elsif ($line =~ /^our\s+\$dbg_s(\d+)\s*=\s*\d+\s*;\s*#(.+)$/) { $tmp = $1; $tmp2 = $2; push(@am_dbg,"2$tmp: $tmp2"); $cnt++; } } if ($cnt) { if (@ac_dbg) { $cnt = scalar @ac_dbg; prt("For DEBUG of AC file scan... $cnt\n"); foreach $tmp (@ac_dbg) { prt(" $tmp\n"); } } else { prt("PROBLEM: NO lib_acscan ADDITIONAL debug HELP!\n"); } if (@am_dbg) { $cnt = scalar @am_dbg; prt("For DEBUG of AM file scans... $cnt\n"); foreach $tmp (@am_dbg) { prt(" $tmp\n"); } } else { prt("PROBLEM: NO lib_amscan ADDITIONAL debug HELP!\n"); } prt("NOTE: Adding DEBUG output only serves to DEBUG what the script 'saw', and 'did'!\n"); } else { prt("\nPROBLEM: Found no \$dbg?? vars in file [$file], so NO DEBUG ADDITIONAL HELP!\n"); } } else { prt("ERROR: Unable to open file [$file], so NO ADDITIONAL DEBUG HELP!\n"); } } sub local_strip_both_quotes($) { my $txt = shift; if ($txt =~ /^'(.+)'$/) { return $1; } if ($txt =~ /^"(.+)"$/) { return $1; } return '' if ($txt eq '""'); return '' if ($txt eq "''"); #prt("Stripping [$txt] FAILED\n"); return $txt; } sub load_input_file($$) { my ($arg,$file) = @_; if (open INF, "<$file") { my @lines = ; close INF; my @carr = (); my ($line,@arr,$tmp,$i); my $lncnt = scalar @lines; for ($i = 0; $i < $lncnt; $i++) { $line = $lines[$i]; $line = trim_all($line); next if (length($line) == 0); next if ($line =~ /^#/); while (($line =~ /\\$/)&&(($i+1) < $lncnt)) { $i++; $line =~ s/\\$//; $line .= trim_all($lines[$i]); } @arr = split(/\s/,$line); foreach $tmp (@arr) { $tmp = local_strip_both_quotes($tmp); push(@carr,$tmp); } } $in_input_file++; parse_args(@carr); $in_input_file--; } else { pgm_exit(1,"ERROR: Unable to 'open' file [$file]!\n") } } sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av); } sub add_2_commands($) { my ($ra) = @_; # = \@av my ($itm); foreach $itm (@{$ra}) { $curr_command .= ' ' if (length($curr_command)); $curr_command .= $itm; } } sub show_auto_help() { my $file = $0; my ($line,$max,$tmp,$cnt,$tmp2); my $auto_on = $auto_on_flag; if (open INF, "<$file") { my @lines = ; close INF; prt("Bit list, with some 'notes', indicating what each BIT does.\n"); $cnt = 0; foreach $line (@lines) { chomp $line; if ($line =~ /\#Bit:/) { prt("$line\n"); $cnt++; } } prt("ERROR: Not able to find auto on flag lines!\n") if ($cnt == 0); } else { prt("Unable to open file [$file], no auto help NOT available!\n"); } $tmp = 1; $tmp2 = ''; while ($tmp) { if ($auto_on & $tmp) { $tmp2 .= ' ' if (length($tmp2)); $tmp2 .= "$tmp"; } $tmp = $tmp << 1; last if ($tmp > $auto_max_bit); } prt("Current auto on = $auto_on. Bits: [$tmp2]\n"); prt("The flag can be SET by '-a on' to enable all, and '-a off' to disable all.\n"); prt("Or set to a specific value, '-a 64', '-a 255', or groups, '-a 2+4+8+64'.\n"); prt("\n"); prt("ALSO bits can be MODIFIED using the command...\n"); prt(" --auto-mod [-]v (-am)= Add bit if positive, remove bit if negative.\n"); prt("For example '-am -512' would remove this bit from the value.\n"); prt("\n"); pgm_exit(0,"End AUTO help ($cnt)\n"); } sub set_auto_flag($$) { my ($arg,$sarg) = @_; my $ok = -1; my $num = 0; my $sa = substr($arg,1) if ($arg =~ /^-/); $sa = substr($sa,1) while ($sa =~ /^-/); my $caf = $auto_on_flag; if ($sarg =~ /^\d+\+\d+/) { my @arr = split(/\+/,$sarg); $num = 0; foreach (@arr) { $num += $_; } $sarg = $num; } if ($sarg =~ /^-(\d+)$/) { $num = $1; $num *= -1; $ok = 2; } elsif ($sarg =~ /^(\d+)$/) { $num = $1; if ($num > 0) { $ok = 1; } else { $ok = 0; } } else { if (($sa eq 'am')||($sa eq 'auto-mod')) { pgm_exit(1,"ERROR: Unknown command '$arg $sarg'! Can NOT be '-am' or '--auto-mod' with text 'on', 'off', or integer. (or -1 for all)\n"); } else { if ($sarg =~ /^on$/i) { $ok = 1; $num = -1; } elsif ($sarg =~ /^off$/i) { $ok = 0; $num = 0; } elsif ($sarg =~ /^help$/i) { show_auto_help(); } else { pgm_exit(1,"ERROR: Unknown command '$arg $sarg'! Can only be 'on', 'off', or integer. (or -1 for all)\n"); } } } if (($sa eq 'am')||($sa eq 'auto-mod')) { # ONLY MODIFY THE CURRENT FLAG if ($ok == 2) { $auto_on_flag &= ~(-$num); } else { $auto_on_flag |= $num; } $ok = 'MOD'; } else { if ($ok) { $ok = 'ON'; $auto_on_flag = $num; } else { $auto_on_flag = $num; $ok = 'OFF'; } } prt("Set auto on flag [$sa] $ok - From [$caf] to [$auto_on_flag] "); $ok = 1; my $msg = ''; $num = 0; while($ok) { if ($auto_on_flag & $ok) { $msg .= "+" if (length($msg)); $msg .= "$ok"; $num += $ok; } $ok = $ok << 1; last if ($ok > $auto_max_bit); } prt("Value [$msg] ($num)\n"); } # SET -L dependent libraries option # like $proj_lib .= " /libpath:\"lib\"; # like $proj_libD .= " fooD.lib"; # like $proj_libR .= " foo.lib"; # sub in line ADD LINK32 kernel32.lib ... -NEW_LIBS- /nologo ... #my $proj_libs = 'Winmm.lib ws2_32.lib'; #my $proj_libD = ''; #my $proj_libR = ''; # FIX20110327 - -L Allow the 'set' to include MULTIPLE libraries, for multiple project sub add_user_libs($$) { my ($arg,$libs) = @_; # FIX20101118 - Watch out for static.lib:C:\path\to\lib:D[:project] #my @arr = split(":",$libs); my @arr = colon_split($libs); my $cnt = scalar @arr; my ($lib,$path,$dest,$rtarg,$stg,$typ,$proj); if (VERB9()) { prt("[v9] add_user_libs: Got array of $cnt "); foreach $proj (@arr) { prt("[$proj]"); } prt("\n"); } if ($cnt == 3) { # no project - set GLOBAL $lib = strip_quotes($arr[0]); $path = strip_quotes($arr[1]); $dest = $arr[2]; if ($dest eq 'D') { $rtarg = \$proj_libD; $typ = 'Debug'; } elsif ($dest eq 'R') { $rtarg = \$proj_libR; $typ = 'Release'; } elsif ($dest eq 'B') { $rtarg = \$proj_libs; $typ = 'Both'; } else { pgm_exit(1,"ERROR: For '$arg $libs', the 3rd item MUST be 'D', 'R', or 'B', NOT '$dest'!\n"); } $stg = ''; @arr = split(/;+/,$lib); # FIX20110327 if (VERB9()) { $cnt = scalar @arr; prt("[v9]3: Got library split $cnt "); foreach $lib (@arr) { $lib = strip_quotes(trim_ends($lib)); $stg .= "[$lib] "; } prt("$stg\n"); } $stg = ''; foreach $lib (@arr) { $lib = strip_quotes(trim_ends($lib)); if (length($lib)) { $stg .= ' ' if (length($stg)); if ($lib =~ /\s/) { $stg .= "\"$lib\""; } else { $stg .= "$lib"; } } } if (length($path)) { $stg .= " /libpath:\"$path\""; } if (length(${$rtarg})) { ${$rtarg} .= ' '; } ${$rtarg} .= $stg; prt("Added '$stg' to $typ program library dependence.\n"); rationalise_lib_paths(); } elsif ($cnt == 4) { # given a specific PROJECT to add this specific LIBRARY to... # FIX20110327 - allow MULTIPLE libraries #my %by_proj_libraries = (); #my %by_proj_libraryD = (); #my %by_proj_libraryR = (); $lib = strip_quotes($arr[0]); $path = strip_quotes($arr[1]); $dest = strip_quotes($arr[2]); $proj = strip_quotes($arr[3]); pgm_exit(1,"ERROR: For '$arg $libs', the 4th item MUST be a 'project' name! Not blank!\n") if ((length($proj) == 0) || ($proj =~ /^\s+$/)); if ($dest eq 'D') { $rtarg = \%by_proj_libraryD; $typ = 'Debug'; } elsif ($dest eq 'R') { $rtarg = \%by_proj_libraryR; $typ = 'Release'; } elsif ($dest eq 'B') { $rtarg = \%by_proj_libraries; $typ = 'Both'; } else { pgm_exit(1,"ERROR: For '$arg $libs', the 3rd item MUST be 'D', 'R', or 'B', NOT '$dest'!\n"); } @arr = split(/;/,$lib); # FIX20110327 $stg = ''; if (VERB9()) { $cnt = scalar @arr; prt("[v9]4: Got library split $cnt "); foreach $lib (@arr) { $lib = strip_quotes(trim_ends($lib)); $stg .= "[$lib] "; } prt("$stg\n"); } $stg = ''; foreach $lib (@arr) { $lib = strip_quotes(trim_ends($lib)); if (length($lib)) { $stg .= ' ' if (length($stg)); if ($lib =~ /\s/) { $stg .= "\"$lib\""; } else { $stg .= "$lib"; } } } if (length($path)) { $stg .= " /libpath:\"$path\""; } @arr = split(/;+/,$proj); # FIX20110327 foreach $proj (@arr) { $proj = strip_quotes(trim_ends($proj)); if (length($proj)) { if (defined ${$rtarg}{$proj}) { ${$rtarg}{$proj} .= ' ' if (length(${$rtarg}{$proj})); ${$rtarg}{$proj} .= $stg; } else { ${$rtarg}{$proj} = $stg; } prt("For project [$proj], added '$stg' to $typ library dependence\n"); $stg = ${$rtarg}{$proj}; prt("[v9] Got full [$stg]\n") if (VERB9()); } } } else { pgm_exit(1,"ERROR: For '$arg $libs', the 'set' did NOT split into 3 or 4 items!\n". " The LIB consists of . The 'path' can be blank, absolute, or relative\n". " to the 'target' directory of the program DSP. D=Debug, R=Release, B=Both. It will be\n". " added to ALL if no 'project', else ONLY to that project.\n"); } } sub set_cond_item($$) { my ($arg,$sarg) = @_; my @arr = split(":",$sarg); my $item = $arr[0]; my $val = 'TRUE'; my ($tmp); if (scalar @arr > 1) { $tmp = $arr[1]; if ( ($tmp =~ /^\d+$/) && (($tmp == 1)||($tmp == 0)) ) { $val = 'FALSE' if ($tmp == 0); } else { pgm_exit(2,"ERROR: Argument can only be $item + :1 or :0, not [$tmp]\n"); } } if (defined $g_user_condits{$item}) { prt("Resetting conditional [$item] to [$val]\n"); } else { prt("Setting conditional [$item] to [$val]\n"); } $g_user_condits{$item} = $val; # stored as ${$rparams}{'REF_DEF_CONDITIONS'} } # SET -T project:type[:source_list] sub set_project_type($$) { my ($arg,$sarg) = @_; my @arr = split(/:/,$sarg); my $cnt = scalar @arr; my $bad = 0; my $msg = ''; my ($proj,$type,$srcs,@ts); if (($cnt >= 2)&&($cnt <= 3)) { $proj = $arr[0]; $type = $arr[1]; $srcs = ($cnt == 3) ? $arr[2] : ''; if ( get_app_type_4_short($type, \$msg) ) { $by_proj_types{$proj} = $type; if (length($srcs)) { $by_proj_types{$proj} .= ':'.$srcs; $msg .= " + srcs [$srcs]"; } } else { $msg = "FAILED conversion on type [$type] to string! Only 'CA', 'WA', 'SL', 'DLL' allowed!"; $bad = 1; } } else { $bad = 1; $msg = "Did not split to 2 (or 3) on ':' char! Must be 'name:type[:src_list]'"; } if ($bad) { pgm_exit(2,"ERROR: Command [$arg $sarg] FAILED! $msg\n"); } else { prt("Set project [$proj], to type [$type] $msg\n"); } } sub add_joined_projects($$) { my ($arg,$sarg) = @_; my (@arr,$bad,$cnt,$proj,$list,$type,$msg,$srcs,$emsg); @arr = space_split($sarg); $bad = 1; $cnt = scalar @arr; $emsg = "Splitting [$sarg] per space to 2 ($cnt)"; goto FAILED if ($cnt != 2); $proj = $arr[0]; $list = $arr[1]; @arr = split(/:/,$proj); $cnt = scalar @arr; $emsg = "Splitting [$proj] per colon to 2 or 3 ($cnt)"; goto FAILED if (($cnt < 2)||($cnt > 3)); $proj = $arr[0]; $type = $arr[1]; $srcs = ($cnt == 3) ? $arr[2] : ''; $emsg = "Converting [$type] to string"; goto FAILED if ( !get_app_type_4_short($type, \$msg) ); # got destination project name - $proj,$type,$srcs or none,$list $joined_projects{$proj} = "$type:$srcs $list"; @arr = split(/;/,$list); $cnt = scalar @arr; $msg = "Join [$list]($cnt), to project [$proj], type [$type] ($msg)"; $msg .= ", plus srcs [$srcs]" if (length($srcs)); $bad = 0; FAILED: if($bad) { pgm_exit(2,"ERROR: Command [$arg $sarg] FAILED! $emsg\n Not of form '-j prj:typ[:srcs] prj1;prj2;...'\n"); } prt("$msg\n"); } sub parse_args { my (@av) = @_; my ($arg,$sarg,$tmp,$rngac,$rngam); add_2_commands(\@av); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); $conf_string = ""; pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^a/) { need_arg(@av); shift @av; $sarg = $av[0]; set_auto_flag($arg,$sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^c/) { need_arg(@av); shift @av; $sarg = $av[0]; set_cond_item($arg,$sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^D/) { need_arg(@av); shift @av; $sarg = $av[0]; add_defined_item($sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^d/) { need_arg(@av); shift @av; $sarg = $av[0]; $conf_string .= "$arg $sarg\n"; if ($sarg =~ /^(\d+)$/) { $tmp = $1; $rngac = ac_get_dbg_range(); $rngam = am_get_dbg_range(); if (($tmp > 200) && (($tmp - 200) <= $rngam)) { if (am_set_dbg_var($tmp - 200)) { prt("Set AM lib Debug $tmp ON!\n"); } else { pgm_exit(1,"ERROR: FAILED to set AM lib Debug $tmp ON!\n"); } } elsif (($tmp > 100) && (($tmp - 100) <= $rngac)) { if (ac_set_dbg_var($tmp - 100)) { prt("Set AC lib Debug $tmp ON!\n"); } else { pgm_exit(1,"ERROR: FAILED to set AC lib Debug $tmp ON!\n"); } } else { $rngac += 100; $rngam += 200; pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Is numerical, but not range 101 to $rngac, nor 202 to $rngam!\n"); } } elsif ($sarg =~ /^-(\d+)$/) { $tmp = $1; $rngac = ac_get_dbg_range(); $rngam = am_get_dbg_range(); if (($tmp > 200) && (($tmp - 200) <= $rngam)) { if (am_clear_dbg_var($tmp - 200)) { prt("Clear AM lib Debug $tmp OFF!\n"); } else { pgm_exit(1,"ERROR: FAILED to clear AM lib Debug $tmp OFF!\n"); } } elsif (($tmp > 100) && (($tmp - 100) <= $rngac)) { if (ac_clear_dbg_var($tmp - 100)) { prt("Clear AC lib Debug $tmp OFF!\n"); } else { pgm_exit(1,"ERROR: FAILED to clear AC lib Debug $tmp OFF!\n"); } } else { $rngac += 100; $rngam += 200; pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Is numerical, but not range 101 to $rngac, nor 202 to $rngam!\n"); } } else { if ($sarg =~ /^help$/i) { show_dbg_help(); $conf_string = ""; pgm_exit(0,"DEBUG Help exit(0)\n"); } elsif ($sarg =~ /^all$/i) { prt("Setting ALL debug ON!\n"); set_all_dbg_on(); } elsif ($sarg =~ /^none$/i) { prt("Setting ALL debug OFF!\n"); set_all_dbg_off(); } elsif ($sarg =~ /^dry-run$/i) { prt("Setting DRY RUN ONLY!\n"); $only_dry_run = 1; } elsif ($sarg =~ /^extra$/i) { prt("Setting ALL debug ON, plus EXTRA!\n"); set_max_debug_on(); } else { pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Not numerical, nor 'all', 'none', or 'help' !\n"); } } } elsif ($sarg =~ /^I/) { need_arg(@av); shift @av; $sarg = $av[0]; add_include_item($sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^j/i) { need_arg(@av); shift @av; $sarg = $av[0]; need_arg(@av); shift @av; $sarg .= " $av[0]"; add_joined_projects($arg,$sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^l/) { $load_log = 1; $conf_string .= "$arg\n"; } elsif ($sarg =~ /^L/) { need_arg(@av); shift @av; $sarg = $av[0]; add_user_libs($arg,$sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^m/i) { # store a macro need_arg(@av); shift @av; $sarg = $av[0]; need_arg(@av); shift @av; $tmp = $av[0]; $g_user_subs{$sarg} = $tmp; # supplied by USER INPUT prt("Set MACRO [$sarg] = [$tmp] in common subs...\n"); $tmp = '""' if ((length($tmp) == 0)||($tmp =~ /^\s+$/)); $conf_string .= "$arg $sarg $tmp\n"; } elsif ($sarg =~ /^n/i) { need_arg(@av); shift @av; $sarg = $av[0]; $project_name = $sarg; prt("Set default over-all project name to [$project_name]\n"); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^o/i) { need_arg(@av); shift @av; $sarg = $av[0]; $dsp_out_dir = File::Spec->rel2abs($sarg); prt("Set DSP out directory to [$dsp_out_dir]\n"); $conf_string .= "$arg $sarg\n"; if (! -d $dsp_out_dir) { pgm_exit(1,"ERROR: The OUTPUT directory given, $dsp_out_dir does NOT EXIST!\n". "Give only an output directory that already EXISTS.\n"); } # } elsif ($sarg =~ /^p/) { # if (-f $conf_file) { # prt("Loading previous commands from [$conf_file]\n"); # load_input_file($arg,$conf_file); # $no_conf_write = 1; # } else { # pgm_exit(1,"ERROR: No previous config file [$conf_file] to load!\n"); # } } elsif ($sarg =~ /^r/) { need_arg(@av); shift @av; $sarg = $av[0]; prt("Loading from response file [$sarg]...\n"); load_input_file($arg,$sarg); } elsif ($sarg =~ /^R/) { # FIX20110306 - Set project RUNTIME - either 'T'=static, or 'D'=DLL (default) need_arg(@av); shift @av; $sarg = $av[0]; if (($sarg eq 'T')||($sarg eq 'D')) { $proj_rt = $sarg; prt("Set RUNTIME to [$sarg]... "); if ($proj_rt eq 'D') { prt("i.e. /MD release, /MDd debug DLL libs\n"); } else { prt("i.e. /MT release, /MTd debug static libs\n"); } } else { pgm_exit(1,"ERROR: Runtime can ONLY be 'T', for static, or 'D' for DLL! Not [$sarg]!\n"); } } elsif ($sarg =~ /^s/) { $supp_make_in = 1; prt("Added support for Makefile.in.\n"); $conf_string .= "$arg\n"; } elsif ($sarg =~ /^t/) { # target directory for DSP file(s) need_arg(@av); shift @av; $sarg = $av[0]; $target_dir = File::Spec->rel2abs($sarg); $fix_relative_sources = 1; prt("Set to TARGET folder to [$target_dir].\n"); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^T/) { # set TYPE SL->DLL, or CA->WA for a project need_arg(@av); shift @av; $sarg = $av[0]; set_project_type($arg,$sarg); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^v/i) { while ($sarg =~ /^v/i) { $verbosity++; $sarg = substr($sarg,1); } prt("Set verbosity to [$verbosity]\n"); $conf_string .= "$arg\n"; } elsif ($sarg =~ /^w/i) { need_arg(@av); shift @av; $sarg = $av[0]; $project_dbg_write = $sarg; prt("Set write debug to $project_dbg_write\n"); $conf_string .= "$arg $sarg\n"; } elsif ($sarg =~ /^x/i) { need_arg(@av); shift @av; $sarg = $av[0]; set_exclude_project($arg,$sarg,1); $conf_string .= "$arg $sarg\n"; } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $in_file = File::Spec->rel2abs($arg); if (-f $in_file) { $conf_string .= "$arg\n"; prt("Set input to [$in_file]\n"); } else { pgm_exit(1,"ERROR: Unable to locate file [$in_file]! Check name, location...\n"); } } shift @av; } if ($in_input_file == 0) { if ((length($in_file) == 0) && $debug_on) { my @carr = (); push(@carr,"-d"); push(@carr,"extra"); #push(@carr,"-d"); push(@carr,"dry-run"); push(@carr,"$def_file"); # for libxm2 push(@carr,"-s"); # $supp_make_in = 1; # Support Makefile.in scanning push(@carr,"-I"); push(@carr,"..\\include"); push(@carr,"-D"); push(@carr,"LIBXML_STATIC"); push(@carr,"-m"); push(@carr,'THREAD_W32'); push(@carr,'Win32'); push(@carr,"-d"); push(@carr,113); # for libgif #push(@carr,"-I"); push(@carr,"..\\lib"); #push(@carr,"-I"); push(@carr,"..\\windows"); # for sigc++ # $g_user_subs{'SIGCXX_API_VERSION'} = 2; # supplied by USER INPUT # for pcre #push(@carr,"-s"); # $supp_make_in = 1; # Support Makefile.in scanning #push(@carr,"-D"); push(@carr,"PCRE_STATIC"); #push(@carr,"-l\n"); # $load_log = 1; if ((length($target_dir) == 0) && length($def_targ)) { push(@carr,"-t"); push(@carr,"$def_targ"); # $target_dir = $def_targ; } if (length($def_name) && (length($project_name) == 0)) { push(@carr,"-n"); push(@carr,$def_name); } $in_input_file++; parse_args(@carr); $in_input_file--; } if (length($in_file) == 0) { pgm_exit(2,"ERROR: No 'configure.ac' input file found in command!\n"); } if (! -f $in_file) { pgm_exit(2,"ERROR: Can NOT find file [$in_file]! Check name, location!\n"); } } if (! -d $dsp_out_dir) { pgm_exit(2,"ERROR: Directory [$dsp_out_dir] does NOT exist!\n Maybe it needs to be corrected, or created...\n"); } #wait_key(); #if ($in_input_file == 0) { # pgm_exit(1, "Check results...\n"); #} } # ============================================================================================= # TO BE DONE - ***TBD*** Other items thought of, but not yet implemented # # - Add DEFINE differently for Debug and Release, GLOBALLY or per PROJECT # # - Adding headers - ok this is good, but most headers get attached to the LIBRARIES, # since they are processed FIRST. There should be a better scheme for this. But can not # immediately see how to handle it, yet. # And in one instance in Glib-1.24.2 I saw one header added twice - I though I had BLOCK this! # Need to check later projects, before/while adding headers... # # AND, since I now know all the headers included by a file, the script SHOULD make sure # the additional include directories is updated to find this/these headers. # # - noinst_PROGRAMS, check_PROGRAMS versus bin_PROGRAMS # Maybe the DSP for no-install prograsm could be still written, BUT not included in # the main DSW file. Maybe a 2nd DSW file could be written for these 'check' and 'no-install' # programs. 2010-10-26 - Add a -x (eXclude) option, which maybe help with this. # # - There are times when combining some static libraries could be good, but care should be taken with # this, because this separation is important in most cases. Maybe # --join a:b:c d (-j) = Join projects named 'a', 'b', and 'c', and make a project 'd' # # - config.h - When it is noted that the source uses a 'config.h', maybe generate a common file # in the target directory, and make sure it is added to the most important library/programs, if pos. # # - missing source - certain Makefile.am will have a $host switch to INCLUDE say MAC or Windows # sources in say a library, but these will not always get picked up and put in the library. # Conversely, sometimes say MAC items will get picked up when they should not. Need a way to # (a) Force the INCLUSION of certain source to a project, and # (b) Force the EXCLUSION of certain sources from a project. # These sources are presently only written to the $missed_source_list file, # but this seems now well handled, at least partially, by the new --cond item:[0|1] option # # Be able to ADD use dependencies to the DSW file, especially for additional libraries that # may NOT be in a LDADD entries - like they are only for WIN32 # Maybe --PROJ #int main(int argc, char **argv) { return 0; } #EOF # my $name = $target_dir.'aaa_msvc_dummy.c'; # write2file($prog,$name); # return 1; #} # Or MAYBE add this dependence to one of the test/example built exes # # Scanning of m4 files - maybe re-enable this # from : http://stackoverflow.com/questions/1970926/whats-the-point-of-aclocal # However, the latest documentation from both sets of tools suggests that the # entire aclocal/acinclude paradigm is now obsolete, in favor of a newer method # of specifying a directory containing m4 macro files. The current recommendation # is that you create a directory in your project directory called simply m4 # (acinclude seems more appropriate to this author), and add macros in the form # of individual .m4 files to this directory. All files in this directory will be # gathered into aclocal.m4 before Autoconf processes your configure.ac file. # Ultimately, aclocal will be replaced by functionality in Autoconf itself # Mentions : http://www.lrde.epita.fr/~adl/autotools.html # # 2011-03-14 - Perhaps REMOVE the '_a', example PLIB Makefile.am for pui # lib_LIBRARIES = libplibpu.a # libplibpu_a_SOURCES = ... # This correctly generate a 'libplibpu_a' project, but maybe it could be just 'plibpu' # It is noted in exe project that inlcude this library it will just use -lplibpu to name this library # # 2011-03-14 The comparison of the full directory scan outputs 'files' NOT used anywhere, # but perhaps this could be reduced by any EXTRA_DIST = some.dsp files. The EXTRA_DIST does # mean the file is NOT used elsewhere thus should not show up as 'un-referenced'... # # 21/04/2011 - Add say an -A alias flag, somewhat like the -L option # -A alias:lib:path:[RDB] example # -A sgio:libsgio_a.lib:path:R, then when the item - # project_LDADD = -lsgio, then the library/path libsgio_a.lib and are added for Release build # That is tell the script what to expect in a LDADD Makefile.am statement, and supply the # appropriate library, and path to add to the project. # # ============================================================================================= # eof - amsrcs04.pl