#!/usr/bin/perl #< lib_cmake.pl - 20120418 - Take a project hash, and write a set of CMakeLists.txt files # 29/04/2012 - Moved CMake READ to its OWN library # 28/04/2012 - begin adding CMake READING # 23/04/2012 - starting to look SOLID ;=)) use strict; use warnings; my $os = $^O; my $PATH_SEP = '/'; if ($os =~ /win/i) { $PATH_SEP = "\\"; } my @my_cmake_proj_hashes = (); our ($RLO_MSG,$RLO_PRJ,$RLO_VAL,$RLO_NAM,$RLO_EXC); my $add_exe_install = 1; my $add_exe_postfix = "d"; my $add_lib_install = 1; my $use_single_inc_list = 1; # 18/05/2012 put back to a SINGLE list my $add_target_msg = 0; # add diagnostic message output my $max_set_line_len = 70; my $def_to_shared = 0; my $add_proj_bin_dir = 0; # This worked for SOME, but not all - need to locate header, and put relative path my $use_just_file_name = 1; sub get_cmake_proj_hash_ref() { return \@my_cmake_proj_hashes; } sub set_cmake_exe_install($) { $add_exe_install = shift; } sub set_cmake_exe_postfix($) { $add_exe_postfix = shift; } sub set_cmake_lib_install($) { $add_lib_install = shift; } sub set_cmake_def_library($) { $def_to_shared = shift; } sub set_cmake_add_bin_dir($) { $add_proj_bin_dir = shift; } sub set_rpath_per_os($) { my $rff = shift; my $ff = ${$rff}; $ff = ($os =~ /win/i) ? path_u2d($ff) : path_d2u($ff); ${$rff} = $ff; } my $max_output_line = 95; sub set_max_output_line($) { $max_output_line = shift; } sub max_output_line($) { my $line = shift; my $len = length($line); if ($len > $max_output_line) { my $hlen = ($max_output_line - 3) / 2; $line = substr($line,0,$hlen)."...".substr($line,($len-$hlen)); } return $line; } # my @keys_used = qw(PROJECT_ROOT PROJECT_CFGS PROJECT_NAME PROJECT_APTP PROJECT_SRCS PROJECT_AM_FILE); sub test_ref_hash($$$$$$$) { my ($rh,$rpr,$rcfg,$rpn,$rpt,$rps,$ram) = @_; my ($tmp,$cnt); my $key = 'PROJECT_ROOT'; if (defined ${$rh}{$key}) { ${$rpr} = ${$rh}{$key}; } else { prt("CMAKE:ERROR:1: $key not set in HASH!\n"); return 1; } $key = 'PROJECT_CFGS'; if (defined ${$rh}{$key}) { $tmp = ${$rh}{$key}; $cnt = scalar @{$tmp}; if ($cnt > 0) { ${$rcfg} = $tmp; } else { prt("CMAKE:ERROR:2: $key is set in HASH, but ZERO cfgs!\n"); return 1; } } else { prt("CMAKE:ERROR:2: $key not set in HASH!\n"); return 1; } $key = 'PROJECT_NAME'; if (defined ${$rh}{$key}) { ${$rpn} = ${$rh}{$key}; } else { prt("CMAKE:ERROR:3: $key not set in HASH!\n"); return 1; } #$key = 'PROJECT_TYPE'; $key = 'PROJECT_APTP'; if (defined ${$rh}{$key}) { $tmp = ${$rh}{$key}; if ($tmp && (length($tmp) > 0)) { ${$rpt} = $tmp; } else { prt("CMAKE:ERROR:4: $key set in HASH, but NO LENGTH!\n"); return 1; } } else { prt("CMAKE:ERROR:4: $key not set in HASH!\n"); return 1; } $key = 'PROJECT_SRCS'; if (defined ${$rh}{$key}) { $tmp = ${$rh}{$key}; # = [@vc_c_sources] or [@dsp_sources]; $cnt = scalar @{$tmp}; if ($cnt > 0) { ${$rps} = $tmp; } else { prt("CMAKE:ERROR:5: $key is set in HASH, but ZERO sources!\n"); return 1; } } else { prt("CMAKE:ERROR:5: $key not set in HASH!\n"); return 1; } $key = 'PROJECT_AM_FILE'; if (defined ${$rh}{$key}) { $tmp = ${$rh}{$key}; $cnt = length($tmp); if ($cnt > 0) { ${$ram} = $tmp; } else { prt("CMAKE:ERROR:6: $key is set in HASH, but ZERO length!\n"); return 1; } } else { prt("CMAKE:ERROR:6: $key not set in HASH!\n"); return 1; } ###$key = 'CURR_AUTO_ON_FLAG'; ###if (defined ${$rh}{$key}) { ### $tmp = ${$rh}{$key}; ###} else { ### prt("CMAKE:ERROR:7: $key not set in HASH!\n"); ### return 1; ###} return 0; } sub do_hash_cmake_test($) { my $rh = shift; my ($proot,$rcfgs,$pname,$ptype,$psrcs,$amfile,$ao); return 1 if (test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile)); return 0; # success } sub get_gui_message_txt() { my $txt = < 1, '_USE_MATH_DEFINES' => 2, '_CRT_SECURE_NO_WARNINGS' => 3, '_SCL_SECURE_NO_WARNINGS' => 4, '__CRT_NONSTDC_NO_WARNINGS' => 5, 'HAVE_CONIFG_H' => 6 ); sub get_last_directory($) { my $dir = shift; $dir = path_u2d($dir); $dir =~ s/\\$//; $dir =~ s/^\\//; my @arr = split(/\\/,$dir); return $arr[-1]; } sub is_in_depends($$) { my ($lib,$rpda) = @_; my ($tst); foreach $tst (@{$rpda}) { return 1 if ($tst eq $lib); # if windows return 1 if (lc($tst) eq lc($lib)); if ($lib =~ /d$/i) { $lib =~ s/d$//i; return 1 if ($tst eq $lib); # if windows return 1 if (lc($tst) eq lc($lib)); } } return 0; } # $tmp = path_d2u($tmp); # # $cmake .= "FIND_LIBRARY( GETOPT_LIBRARY NAMES $val PATHS $tmp )\n"; # # $cmake .= "TARGET_LINK_LIBRARIES( $pname \${GETOPT_LIBRARY} )\n"; # $cmake .= "FIND_LIBRARY( GETOPT_DEBUG_LIBRARY NAMES $val2 PATHS $tmp )\n"; # $cmake .= "FIND_LIBRARY( GETOPT_RELEASE_LIBRARY NAMES $val PATHS $tmp )\n"; # $cmake .= "TARGET_LINK_LIBRARIES( $pname debug \${GETOPT_DEBUG_LIBRARY} optimized \${GETOPT_RELEASE_LIBRARY} )\n"; # CMake Warning (dev) at tools/CMakeLists.txt:132 (TARGET_LINK_LIBRARIES): # Link library type specifier "debug" is followed by specifier "optimized" # instead of a library name. The first specifier will be ignored. # This warning is for project developers. Use -Wno-dev to suppress it. # It appears if need to find more than ONE library this needs to be done SEPARATELY # BUT could NOT get that RIGHT exactly, so a third try # could MAYBE add # INSTALL_RPATH_USE_LINK_PATH Add paths to linker search and installed rpath. # INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will append directories # in the linker search path and outside the project to the INSTALL_RPATH. # also LINK_DIRECTORIES() like - # LINK_DIRECTORIES(C:/external/lib) # ADD_EXECUTABLE(Main main.cpp) # but then I read # The best way to do this is to not use LINK_DIRECTORIES. Instead use # target_link_libraries, and give the FULL path to the library you want to # link to. CMake should then do the right thing. my $temp_count = 0; my %find_libs = (); sub get_cmake_lib_finds($) { my ($rp) = @_; my $pnm = ${$rp}{'PROJECT_NAME'}; my $ptyp = ${$rp}{'PROJECT_TYPE'}; my $rpda = ${$rp}{'PROJECT_DEPENDS'}; my $inst = ${$rp}{'PROJECT_INST'}; # install indication like noinst_LIBRARIES, sbin_PROGRAMS my $rels = get_proj_libs_rel($rp); my $dbgs = get_proj_libs_dbg($rp); if (VERB9()) { prt("[v9] For project [$pnm] [$ptyp]\n"); prt("Release libs [$rels]\n"); prt("Debug libs [$dbgs]\n"); } my ($itm,$lcitm,@arr,$i); my %dpaths = (); my %dnames = (); my %rpaths = (); my %rnames = (); my %duperel = (); my %dupedbg = (); @arr = space_split($rels); foreach $itm (@arr) { $itm = trim_all($itm); next if (length($itm) == 0); $lcitm = lc($itm); next if (defined $duperel{$lcitm}); $duperel{$lcitm} = 1; if ($itm =~ /^\/libpath:/i) { $itm = strip_quotes(substr($itm,9)); set_rpath_per_os(\$itm); $rpaths{$itm} = 1; ###} elsif (is_win_library($itm)) { # what to do about these try nothing } else { my ($n,$d,$e) = fileparse($itm, qr/\.[^.]*/); if (!is_in_depends($n,$rpda)) { $rnames{$itm} = 1; } } } @arr = space_split($dbgs); foreach $itm (@arr) { $itm = trim_all($itm); next if (length($itm) == 0); $lcitm = lc($itm); next if (defined $dupedbg{$lcitm}); $dupedbg{$lcitm} = 1; if ($itm =~ /^\/libpath:/i) { $itm = strip_quotes(substr($itm,9)); $dpaths{$itm} = 1; ###} elsif (is_win_library($itm)) { ### # what about these??? tyr do nothing } else { my ($n,$d,$e) = fileparse($itm, qr/\.[^.]*/); if (!is_in_depends($n,$rpda)) { $dnames{$itm} = 1; } } } # check counts my @rarr = sort keys(%rnames); my @darr = sort keys(%dnames); my $rcnt = scalar @rarr; my $dcnt = scalar @darr; if (($rcnt == 0)&&($dcnt == 0)) { return ''; # nothing to add } if (($rcnt == 0)&& $dcnt) { prtw("WARNING:$pnm: Have no REL libraries but $dcnt DBG!!! R:[$rels] D:[$dbgs]\n"); return ''; } if ($rcnt && ($dcnt == 0)) { prtw("WARNING:$pnm: Have no DBG libraries but $rcnt REL!!! R:[$rels] D:[$dbgs]\n"); return ''; } if ($rcnt != $dcnt) { prtw("WARNING:$pnm: Have $rcnt REL libraries but $dcnt DBG!!! R:[$rels] D:[$dbgs]\n"); return ''; } my $cmake = ''; my $dvar = uc($pnm)."_DEBUG_LIBRARY"; my $rvar = uc($pnm)."_RELEASE_LIBRARY"; my ($rlib,$dlib); # $rcnt and $dcnt are the SAME so... if ($rcnt == 1) { $i = 0; $rlib = $rarr[$i]; $dlib = $darr[$i]; $cmake .= "find_library( $rvar $rlib "; @arr = keys(%rpaths); if (@arr) { $cmake .= "PATHS "; foreach $itm (@arr) { ### set_rpath_per_os(\$itm); $itm = path_d2u($itm); # cmake LIKES unix paths, ;=)), else must ESCAPE the '\', like "\\" $itm = '"'.$itm.'"' if ($itm =~ /\s/); # add QUOTES only if path contains a SPACE $cmake .= "$itm "; } } $cmake .= ")\n"; # Debug library processing $cmake .= "find_library( $dvar $dlib "; @arr = keys(%dpaths); if (@arr) { $cmake .= "PATHS "; foreach $itm (@arr) { $itm = path_d2u($itm); # cmake LIKES unix paths, ;=)), else must ESCAPE the '\', like "\\" $itm = '"'.$itm.'"' if ($itm =~ /\s/); # add QUOTES only if path contains a SPACE $cmake .= "$itm "; } } $cmake .= ")\n"; $cmake .= "message( \"Proj $pnm, found debug \${".$dvar."} optimized \${".$rvar."} libraries.\" )\n" if (VERB9() || $add_target_msg); $cmake .= "target_link_libraries( $pnm debug \${".$dvar."} optimized \${".$rvar."} )\n\n"; } else { my ($tdvar,$trvar); for ($i = 0; $i < $rcnt; $i++) { # Release library processing (to a 'temp' var) $temp_count++; # cmake REFUSES to refind something, so MUST change the name each time !!! $tdvar = "TEMP".$temp_count."_DEBUG_LIBRARY"; $trvar = "TEMP".$temp_count."_RELEASE_LIBRARY"; $rlib = $rarr[$i]; $dlib = $darr[$i]; $cmake .= "\nfind_library( $trvar $rlib "; @arr = keys(%rpaths); if (@arr) { $cmake .= "PATHS "; foreach $itm (@arr) { $itm = path_d2u($itm); # cmake LIKES unix paths, ;=)), else must ESCAPE the '\', like "\\" $itm = '"'.$itm.'"' if ($itm =~ /\s/); # add QUOTES only if path contains a SPACE $cmake .= "$itm "; } } $cmake .= ")\n"; # Debug library processing (to a 'temp' var) $cmake .= "find_library( $tdvar $dlib "; @arr = keys(%dpaths); if (@arr) { $cmake .= "PATHS "; foreach $itm (@arr) { $itm = path_d2u($itm); # cmake LIKES unix paths, ;=)), else must ESCAPE the '\', like "\\" $itm = '"'.$itm.'"' if ($itm =~ /\s/); # add QUOTES only if path contains a SPACE $cmake .= "$itm "; } } $cmake .= ")\n"; $cmake .= "message( \"Proj $pnm, found debug \${".$tdvar."} optimized \${".$trvar."} libraries.\" )\n" if (VERB9() || $add_target_msg); $cmake .= "set( $rvar \${$rvar} \${$trvar} )\n"; $cmake .= "set( $dvar \${$dvar} \${$tdvar} )\n"; } $cmake .= "\ntarget_link_libraries( $pnm\n"; $cmake .= " debug \${".$dvar."}\n"; $cmake .= " optimized \${".$rvar."} )\n\n"; } return $cmake; } sub debug_enum_ref_proj_hash($) { my ($rparams) = @_; my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # get stored EXCLUDED directory HASH (if any!) my $rph = ${$rparams}{'REF_PROJECTS_HASH'}; my $rlib_lists = ${$rparams}{'REF_LIB_LISTS'}; # make list of LIBRARIES written my %depends = (); my $cnt = scalar keys(%{$rph}); my ($key,$rp,$val,$pnm,$ptype,$msg,$isexcl,$rpda,$nm2,$tmp,$inst); my ($rhash,$am_file); $cnt = 0; foreach $key (keys %{$rph}) { $rp = ${$rph}{$key}; $val = ${$rp}{'PROJECT_NAME'}; $pnm = $val; $ptype = ${$rp}{'PROJECT_TYPE'}; $inst = ${$rp}{'PROJECT_INST'}; $rhash = ${$rp}{'PROJECT_AM_RHASH'}; # get PROJECT hash $am_file = ${$rhash}{':_AM_FILE_SRC_:'}; # get AM file name $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; $msg = '['; if (defined ${$rp}{'PROJECT_DEPENDS'}) { $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}) { $depends{$nm2} = 1; } } $msg = trim_all($msg); } $msg .= ']'; $cnt++; prt("$cnt: [$val] [$ptype] $msg AM [$am_file]\n"); } prt("Done list of $cnt items...\n\n"); } sub find_in_directory_scan($$) { my ($rparams,$file) = @_; return '' if (!${$rparams}{'CURR_DONE_SCAN'}); my $rda = ${$rparams}{'CURR_DIR_SCAN'}; # 0 1 2 3 #push(@{$rda},[$file,$ff,0,0]); my $cnt = scalar @{$rda}; my ($i,$ra,$tst,$lcf); $lcf = lc($file); for ($i = 0; $i < $cnt; $i++) { $ra = ${$rda}[$i]; return ${$ra}[1] if ($file eq ${$ra}[0]); return ${$ra}[1] if ($lcf eq lc(${$ra}[0])); } return ''; } sub add_options_block($) { my $type = shift; my $txt = < $minn); $len = length($ptype); $mint = $len if ($len > $mint); } } } my $PATH_SEP = get_PATH_SEP(); my $dsp_out_dir = get_dsp_out_dir(); my %added_lists = (); my $add_2_root = ''; # AVOID 2 CMakeLists.txt - temp..txt and temp.root.txt my @srcarr = (); my @hdrarr = (); my ($line); my $indent = 3; foreach $am_key (sort keys %am_hash) { $ra = $am_hash{$am_key}; $cnt = scalar @{$ra}; $amdir = $proj_root.$am_key.$PATH_SEP."CMakeLists.txt"; if (length($am_key)) { $tmp = $am_key; $tmp = path_d2u($tmp); # cmake LIKES unix paths # or s/\\/\\\\/g; $added_lists{$tmp} = 1; # this is again sort of EACH subdirectory } $tmp = $am_key; $tmp =~ s/\\/_/g; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.$tmp.txt"; ### if ((defined $cmake_thash{$tmpout}) || (defined $cmake_files{$tmpout})) { ### pgm_exit(1,"ERROR: A hash has like a DUPLICATE key [$am_key]! Check how to make [$tmpout] UNIQUE!\n"); ###} prt("cmake: $amdir has $cnt projects\n"); # set INTITAL CMakeLists.txt entry $tmp = ""; # $tmp = "\n# $amdir, generated by $pgmname on ".lu_get_YYYYMMDD_hhmmss(time())."\n\n"; #$tmp .= "include_directories( \"\${PROJECT_BINARY_DIR}\" $inc_dirs )\n\n"; #$tmp .= "INCLUDE_DIRECTORIES( \${PROJECT_BINARY_DIR}\ )\n"; #$tmp .= "INCLUDE_DIRECTORIES( $inc_dirs )\n" if (length($inc_dirs)); #$tmp .= "\n"; #if (length($am_key)) { # $cmake_thash{$tmpout} = $tmp; # start cmake text for this file # $cmake_files{$tmpout} = $amdir; # map 'tmp' to real target file #} else { $add_2_root .= $tmp; # $key of NO length == root stuff #} foreach $rh (@{$ra}) { if ( ! test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile) ) { if (is_project_all_excluded($pname)) { # if the PROJECT is EXCLUDED forget it prtw("WARNING: An EXCLUDED project has been added! FIX THIS\n"); next; } $rp = ${$rh}{'PROJECT_RP'}; # extract $rp; # all keep REF PROJECT HASH in REF HASH $inst = ${$rp}{'PROJECT_INST'}; $cmake = ''; $rpda = ${$rh}{'PROJECTS_DEPENDS_ARRAY'}; # = \@deps; # Project DEPENDS array - can be none $deps = ''; my %extra_libs = (); foreach $tmp (@{$rpda}) { $deps .= ' ' if (length($deps)); $deps .= $tmp; $extra_libs{$tmp} = 1; } #$cmake .= "MESSAGE(\"Current build directory \${CMAKE_CURRENT_BUILD_DIR}\")\n"; #$cmake .= "INCLUDE_DIRECTORIES( \"\${CMAKE_CURRENT_BUILD_DIR}\" )\n"; #$cmake .= "MESSAGE(\"Current binary directory [\${PROJECT_BINARY_DIR}]\")\n"; #$cmake .= "INCLUDE_DIRECTORIES( \"\${PROJECT_BINARY_DIR}\" )\n"; $var = $pname."_SRCS"; $var2 = $pname."_HDRS"; $slist = ''; $hlist = ''; $scnt = 0; my %dupes = (); ## 0 1 2 3 #push(@sources, [ $sfil, $group, $filter, $xit, '' ]); # ${$rph}{'PROJECT_SRCS'} my $relhlist = ''; my $hcnt = 0; @srcarr = (); # clear source array @hdrarr = (); foreach $rsa (@{$psrcs}) { $tmp = ${$rsa}[0]; $xit = ${$rsa}[3]; next if ($xit); # excluded SOURCE file my ($n,$d) = fileparse($tmp); next if ($n eq 'unistd.h'); # why MUST I exclude this?????? TODO if (!defined $dupes{$n}) { $dupes{$n} = 1; if (is_c_source_extended($tmp)) { $slist .= ' ' if (length($slist)); $slist .= $n; push(@srcarr,$n); # store in SOURCE $scnt++; } elsif (is_h_source($tmp)) { $hlist .= ' ' if (length($hlist)); $hlist .= $n; ###$scnt++; $relhlist .= ' ' if (length($relhlist)); $relhlist .= $tmp; $hcnt++; } else { prtw("WARNING: SOURCE [$tmp] NOT ADDED! Not 'C' or 'H'! WHat is IT?\n"); } } } prt("cmake: project [$pname] has $scnt sources, $hcnt headers\n"); prt("cmake: sources: [$slist] headers [$relhlist]\n"); if ($scnt) { @hdrarr = (); # header array if (length($relhlist)) { @arr = space_split($relhlist); $relhlist = ''; foreach $tmp (@arr) { if ($use_just_file_name) { ($tmp,$tdir) = fileparse($tmp); $relhlist .= "$tmp "; push(@hdrarr,"$tmp"); } else { $tmp = path_d2u($tmp); # TODO **TBD** really need to LOCATE this HEADER, in source # and ADD appropriate relative path to it! if ($add_proj_bin_dir) { $relhlist .= "\${PROJECT_BINARY_DIR}/$tmp "; push(@hdrarr,"\${PROJECT_BINARY_DIR}/$tmp"); } else { $relhlist .= "$tmp "; push(@hdrarr,"$tmp"); } } } } $msg = ''; $cmake .= "# Project [$pname] [$ptype] [$inst], with $scnt sources."; $cmake .= " $hcnt hdrs." if ($hcnt); @arr = keys(%extra_libs); if (@arr) { $tmp = scalar @arr; $cmake .= " deps [".join(" ",@arr)."]$tmp"; } $cmake .= "\n"; if (length($slist)) { ###$msg .= "set( $var $slist )\n"; $line = ''; $msg .= "set( $var "; foreach $tmp (@srcarr) { $line .= "$tmp "; if (length($line) > $max_set_line_len) { $msg .= "$line\n"; $line = ' ' x $indent; # indent say 3 spaces } } if (length($line) > $indent) { $msg .= $line; } else { $msg =~ s/\n$//; # clear new line } $msg .= ")\n"; } if (length($relhlist)) { ###$msg .= "set( $var2 $relhlist )\n"; $msg .= "set( $var2 "; $line = ''; # clear line accumulation foreach $tmp (@hdrarr) { $line .= "$tmp "; if (length($line) > $max_set_line_len) { $msg .= "$line\n"; $line = ' ' x $indent; # indent } } if (length($line) > $indent) { $msg .= $line; } else { $msg =~ s/\n$//; # remove trailing new line } $msg .= ")\n"; } $cmake .= "$msg"; ### prt("$msg\n"); if ($ptype eq 'Console Application') { # DO AN EXE # ========= $msg = "\nadd_executable( $pname "; $msg .= "\${$var} " if (length($slist)); $msg .= "\${$var2} " if (length($hlist)); $msg .= ")\n"; $cmake .= "$msg"; # if (($proj_type ne 'SL') && ($auto_on & 16) && ($auto_on & 2048)) { if (($auto_on & 16) && ($auto_on & 2048)) { # target_link_libraries(mylib public1 public2 PRIVATE private1 private2) # $cmake .= "TARGET_LINK_LIBRARIES( $pname PRIVATE getopt.lib )\n"; # need to eliminate (s) system libs, (b) dependent libs, in $rpda (ref proj dep array), # and separate balance into lib and path $tmp = get_cmake_lib_finds($rp); if (length($tmp)) { $cmake .= $tmp; prt("$tmp\n") if (VERB9()); } else { prt("Project [$pname] has NO dependent libraries.\n") if (VERB9()); } } else { prtw("WARNING: ((\$auto_on & 16) && (\$auto_on & 2048)) bit NOT set, so NO library FIX! value is [$auto_on]\n"); } # try - AND IT WORKED - phew ;=)) # set_target_properties (helloDemo PROPERTIES DEBUG_POSTFIX "d") if (length($add_exe_postfix)) { # we have a CMAKE_DEBUG_POSTFIX for an EXE $msg = "set_target_properties( $pname PROPERTIES DEBUG_POSTFIX \"$add_exe_postfix\" )\n"; $cmake .= $msg; } $msg = "install(TARGETS $pname DESTINATION $ibinp)\n"; $msg .= "install(FILES \${$var2} DESTINATION $ihdrp)\n" if (length($hlist)); if ($inst =~ /noinst/) { $cmake .= "\n# NO INSTALL [$inst]\n"; } else { $cmake .= $msg if ($add_exe_install); } } elsif ($ptype eq 'Static Library') { # DO A STATIC LIBRARY # =================== $msg = "\nadd_library( $pname \${LIB_TYPE} "; $msg .= "\${$var} " if (length($slist)); $msg .= "\${$var2} " if (length($hlist)); $msg .= ")\n"; $cmake .= "$msg\n"; # # add the install targets # ============================================== # DEAL WITH LIBRARY INSTALL # ============================================== # install (TARGETS Hello DESTINATION lib) # install (FILES ${HELLO_HDRS} DESTINATION include) # $msg = "install(TARGETS $pname DESTINATION $ilibp)\n"; $msg = "\n# deal with install \n"; $msg .= "install( TARGETS $pname\n"; $msg .= " RUNTIME DESTINATION bin\n"; $msg .= " LIBRARY DESTINATION lib\n"; $msg .= " ARCHIVE DESTINATION lib )\n"; # install( FILES ${apr_HEADERS} DESTINATION include ) # OOPS, sometimes the header can be 'local', like # tiffconf.h, tif_config.h are in "\${PROJECT_BINARY_DIR}, and NOT in # "\${PROJECT_SOURCE_DIR}/libtiff where CMake will think they should be... if ($use_single_inc_list) { $msg .= "install(FILES \${$var2} DESTINATION $ihdrp)\n" if (length($hlist)); } elsif (length($hlist)) { my ($itm,$hfile); my @narr = (); my @sarr = (); @arr = space_split($hlist); foreach $itm (@arr) { # maybe get each file from the scan list, or if (length($am_key)) { $hfile = $proj_root.$am_key.$PATH_SEP.$itm; } else { $hfile = $proj_root.$itm; } if (-f $hfile) { push(@narr,$itm); # found in 'normal' place } else { push(@sarr,"\${PROJECT_BINARY_DIR}/$itm"); } } $msg .= "install(FILES ".join(" ",@narr)." DESTINATION $ihdrp)\n" if (@narr); $msg .= "install(FILES ".join(" ",@sarr)." DESTINATION $ihdrp)\n" if (@sarr); #if ($pname eq 'tiff') { # prt("Need to examine this list [$hlist], and have separate installs!\n"); # prt("$msg\n"); # pgm_exit(1,"TEMP EXIT"); #} } if ($inst =~ /noinst/) { $cmake .= "\n# NO INSTALL [$inst]\n"; } else { $cmake .= $msg if ($add_lib_install); } } else { # OTHERS TODO ***TBD*** prtw("WARNING: Unhandled project type [$ptype]! FIX ME\n"); } @arr = keys %extra_libs; if (@arr) { $cmake .= "\ntarget_link_libraries( $pname "; $cmake .= join(" ",@arr); $cmake .= " )\n"; } $cmake .= "\n"; # separate from the next # STORE THIS CMAKE TEXT UNDER THE FILE NAME # ========================================= ## if (length($am_key)) { ## $cmake_thash{$tmpout} .= $cmake; # accumulate the CMake text ##} else { $add_2_root .= $cmake; ##} # ========================================= # display ONLY # ------------------------------------------------- $dnm = $pname; $typ = $ptype; $dnm .= ' ' while (length($dnm) < $minn); $typ .= ' ' while (length($typ) < $mint); $msg = " $dnm [$typ] srcs $scnt"; $msg .= ", deps [$deps]" if (length($deps)); prt("$msg\n"); prt($cmake) if (VERB9()); # ------------------------------------------------ $cmake = ''; # clean this 'cmake' } else { prtw("WARNING: No SOURCES found for [$pname]!\n"); } } } } # this SHOULD have been done before her, but better late than never # compare ADDED subdirectories - my %added_subs = (); # with ADDED CMakeLists.txt files - my %added_lists = (); # Added SUBDIRS # contrib/addtiffo contrib/dbs contrib/iptcutil libtiff port test tools # Added CMAKE LISTS # contrib/addtiffo contrib/dbs libtiff port tools my ($skey); foreach $skey (keys %added_subs) { next if (length($skey) == 0); # donot deal with a blank if (!defined $added_lists{$skey}) { # need to generate a CMakeLists.txt for here $tmp = $skey; $tmp =~ s/\\/_/g; $tmp =~ s/\//_/g; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.$tmp.txt"; ## if ((defined $cmake_thash{$tmpout}) || (defined $cmake_files{$tmpout})) { ## pgm_exit(1,"ERROR: A hash has like a DUPLICATE key [$skey]! Check how to make [$tmpout] UNIQUE!\n"); ## } ## $amdir = $proj_root.$skey.$PATH_SEP."CMakeLists.txt"; ## set INTITAL CMakeLists.txt entry ## $tmp = "\n# $amdir, generated by $pgmname on ".lu_get_YYYYMMDD_hhmmss(time())."\n\n"; $tmp = "# $amdir - deliberately BLANK\n\n"; ## $cmake_thash{$tmpout} = $tmp; # start cmake text for this file ## $cmake_files{$tmpout} = $amdir; # map 'tmp' to real target file $add_2_root .= $tmp; } } if ($write_cmake_files) { my $target_dir = ${$rparams}{'TARGET_DIR'}; my $battxt = "\@setlocal\n"; $battxt .= "\@set COUNT=0\n"; my ($real); $cnt = 0; @arr = (); #foreach $tmp (keys %cmake_thash) { # $val = $cmake_thash{$tmp}; # $real = $cmake_files{$tmp}; # $val .= "\n# eof\n"; # $battxt .= "\@set /A COUNT+=1\n"; # $battxt .= "\@copy \"$tmp\" \"$real\" >nul\n"; # write2file($val,$tmp); # $cnt++; # prt("$cnt: Written [$tmp] for [$real]\n"); # push(@arr,$real); #} $cmake_root .= $add_2_root; # FINALISE CMakeLists.txt for ROOT $cmake_root .= "\n# eof\n"; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.root.$proj_title.txt"; $real = $proj_root."CMakeLists.txt"; # $tmpout = $dsp_out_dir.$PATH_SEP."temp.root.$proj_title.txt"; write2file($cmake_root,$tmpout); push(@arr,$real); $cnt++; prt("$cnt: Written final [$tmpout] for [$real]\n"); $battxt .= "\@set /A COUNT+=1\n"; $battxt .= "\@copy \"$tmpout\" \"$real\" >nul\n"; $battxt .= "\@echo Copied \%COUNT\% CMakeLists.txt files into place\n"; # Write a simple CMakeLists.txt list to $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.list.$proj_title.txt"; write2file(join("\n",@arr)."\n",$tmpout); $real = $target_dir."cmakelist.txt"; $battxt .= "\@copy \"$tmpout\" \"$real\" >nul\n"; $battxt .= "\@echo And copied a list file '$real'.\n"; $tmp = "C:\\MDOS"; $tmpout = $dsp_out_dir; $tmpout = $tmp if (-d $tmp); fix_dir_string(\$tmpout); $tmpout .= "tempcmake.bat"; write2file($battxt,$tmpout); prt("Written [$tmpout] batch file to copy CMake files into place.\n"); } else { prt("Write CMake CMakeLists.txt files disabled. Used -cmake to enable.\n"); } # pgm_exit(1,"TEMP EXIT"); return 0; # success } sub write_project_cmake_files_OK($) { my $rparams = shift; my $prhs = get_cmake_proj_hash_ref(); my $cnt = scalar @{$prhs}; # = @my_cmake_proj_hashes; prt("\nStarted CMake write for $cnt projects...\n"); return 1 if ($cnt == 0); # failed my ($rh,$proot,$rcfgs,$pname,$ptype,$psrcs,$amfile,$name,$amdir); my ($ra,@arr,$rp,$val,$rpda,$nm2,$tmp,$msg,$pnm,$isexcl,$pst); my ($var,$cmake,$tmpout,$rsa,$inst,$tdir); my ($rprojsh); my ($pkey); my $errs = ''; $errs .= "No 'AM_EXCLUDED_DIRS' " if (!defined ${$rparams}{'AM_EXCLUDED_DIRS'}); $errs .= "No 'ROOT_FOLDER' " if (!defined ${$rparams}{'ROOT_FOLDER'}); $errs .= "No 'PROJECT_NAME_MASTER' " if (!defined ${$rparams}{'PROJECT_NAME_MASTER'}); if (defined ${$rparams}{'REF_PROJECTS_HASH'}) { $rprojsh = ${$rparams}{'REF_PROJECTS_HASH'}; @arr = keys(%{$rprojsh}); $cnt = scalar @arr; if ($cnt) { foreach $pkey (keys %{$rprojsh}) { $rp = ${$rprojsh}{$pkey}; if (!defined ${$rp}{'PROJECT_NAME'}) { $errs .= "At least one proj with no 'PROJECT_NAME' "; last; } } } else { $errs .= "No count of REF_PROJECTS_HASH "; } } else { $errs .= "No 'REF_PROJECTS_HASH' "; } $errs .= "No 'REF_LIB_LISTS' " if (!defined ${$rparams}{'REF_LIB_LISTS'}); # make list of LIBRARIES written if (length($errs)) { prt("ABORTING cmake write due to errors [$errs]\n"); return 1; } ### my $rex = process_hoh_subs($rparams); # get EXCLUDED sub-directories my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # get stored EXCLUDED directory HASH (if any!) my $proj_root = ${$rparams}{'ROOT_FOLDER'}; ###my $proj_root = ''; my $proj_title = ${$rparams}{'PROJECT_NAME_MASTER'}; my $ihdrp = get_inst_hdr_path(); # { return $inst_hdr_path; } = 'include' my $ilibp = get_inst_lib_path(); # { return $inst_lib_path; } my $inst_lib_path = 'lib'; my $ibinp = get_inst_hdr_bin(); # { return $inst_bin_path; } my $inst_bin_path = 'bin'; ###my $proj_title = ''; my $auto_on = get_curr_auto_flag(); # $auto_on_flag; $cnt = 0; my %am_hash = (); my %depends = (); my $rlib_lists = ${$rparams}{'REF_LIB_LISTS'}; # make list of LIBRARIES written my $write_cmake_files = get_write_cmake_files(); # Establish USER include directories my %usrincs = (); # -NEW_INCS- my $glob_user_incs = get_user_incs("NOT USED","*NO*PROJECT*NAME*"); # get GLOBAL user INCS @arr = space_split($glob_user_incs); foreach $tmp (@arr) { next if ($tmp =~ /^\/I/); $tmp = strip_quotes($tmp); $tmp = trim_all($tmp); next if (length($tmp) == 0); ##$tmp = path_d2u($tmp); set_rpath_per_os(\$tmp); $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); $usrincs{$tmp} = 1; } my %usrdefs = (); # -NEW_DEFS- my $glob_user_defs = get_user_defs("NOT USED",,"*NO*PROJECT*NAME*"); # get GLOBAL user DEFS @arr = space_split($glob_user_defs); foreach $tmp (@arr) { next if ($tmp =~ /^\/D/); $tmp = strip_quotes($tmp); $tmp = trim_all($tmp); next if (length($tmp) == 0); next if (defined $defines_added{$tmp}); $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); next if (defined $defines_added{$tmp}); $usrdefs{$tmp} = 1; } $cnt = 0; ###foreach $rh (@g_cmake_proj_hashes) { ### if (!test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile)) { ### $proj_title = ${$rh}{'PROJECT_TITLE'}; ### $proj_root = ${$rh}{'PROJECT_ROOT'}; ### last; ### } ###} # 13/05/2012 - ERROR if NO project title if ((length($proj_title) == 0)||($proj_title =~ /^\s+$/)||($proj_title =~ /\s/)) { pgm_exit(1,"ERROR: Have NO (or bad) project title [$proj_title]!\nCan ONLY abort!\n"); } # pre-process the set of per project REF HASH my %sub_dirs = (); my ($rhash,$am_file); #foreach $rh (@my_cmake_proj_hashes) { foreach $rh (@{$prhs}) { ### show_ref_hash($rh,1); $cnt++; if (test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile)) { prtw("WARNING:$cnt: HASH REF INVALID!\n"); } else { if (length($amfile) == 0) { prtw("WARNING: $cnt: [$pname] [$ptype] [$amdir] AM filename nul!\n"); next; } ($name,$amdir) = fileparse($amfile); # we have the AM file directory # $proot = ${$rh}{'PROJECT_FDIR'}; $amdir = sub_common_folder($amdir,$proj_root); # subtract the project root - hmmm WHY??? $amdir =~ s/(\\|\/)$//; $msg = 'NF'; $pst = ''; my @deps = (); my ($pkey); foreach $pkey (keys %{$rprojsh}) { $rp = ${$rprojsh}{$pkey}; $pnm = ${$rp}{'PROJECT_NAME'}; if ($pnm eq $pname) { ${$rh}{'PROJECT_RP'} = $rp; # all keep REF PROJECT HASH in REF HASH $rhash = ${$rp}{'PROJECT_AM_RHASH'}; # get PROJECT hash $am_file = ${$rhash}{':_AM_FILE_SRC_:'}; # get AM file name prtw("WARNING: Got conflickting AM files [$am_file] vs [$amfile]!\n") if ($amfile ne $am_file); $sub_dirs{$amdir} = 1; $pst = ${$rp}{'PROJECT_TYPE'}; $inst = ${$rp}{'PROJECT_INST'}; $msg = get_EXCLUDE_msg($rparams,$rp,$rex); $isexcl = ($msg =~ /EXCLUDE/) ? 1 : 0; prt("[v9] cmake: proj_name [$pname], from [$am_file]\n") if (VERB9()); # $tmp = get_user_incs("NOT USED",$pname); # -NEW_INCS- for this project $tmp = get_project_incs($pname); # -NEW_INCS- for this project $val = ''; if (length($tmp)) { @arr = space_split($tmp); foreach $tmp (@arr) { next if ($tmp =~ /^\/I/); $tmp = strip_quotes($tmp); $tmp = trim_all($tmp); next if (length($tmp) == 0); $tmp = path_d2u($tmp); # cmake LIKES unix paths $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); next if (defined $usrincs{$tmp}); # already in GLOBAL $val .= ' ' if (length($val)); $val .= $tmp; } } prtw("WARNING: By project user INCLUDES [$val] pesently NOT ADDED!\n") if (length($val)); $tmp = get_project_defs($pname); # -NEW_DEFS- for this project $val = ''; if (length($tmp)) { @arr = space_split($tmp); foreach $tmp (@arr) { next if ($tmp =~ /^\/I/); $tmp = strip_quotes($tmp); $tmp = trim_all($tmp); next if (length($tmp) == 0); $tmp = path_d2u($tmp); # cmake LIKES unix paths $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); $val .= ' ' if (length($val)); $val .= $tmp; } } prtw("WARNING: By project user DEFINES [$val] pesently NOT ADDED!\n") if (length($val)); $msg = '['; if (defined ${$rp}{'PROJECT_DEPENDS'}) { $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"; } else { push(@deps,$nm2); $depends{$nm2} = 1; } } $msg = trim_all($msg); } $msg .= ']'; $msg = 'No Depends' if ($msg eq '[]'); last; } } ${$rh}{'PROJECTS_DEPENDS_ARRAY'} = \@deps; if (is_project_all_excluded($pname)) { # if the PROJECT is EXCLUDED forget it prt("$cnt: EXCLUDED [$pname] $pst"."[$ptype] [$amdir] $msg\n"); # if (VERB5()); } else { $am_hash{$amdir} = [] if (!defined $am_hash{$amdir}); $ra = $am_hash{$amdir}; push(@{$ra},$rh); # get REF HASH on a SUBDIRECTORY BASIS prt("$cnt: [$pname] $pst"."[$ptype] [$amdir] $msg\n") if (VERB5()); # || $dbg_cmake); } } } # NOW each REF HASH has been stored PER SOURCE DIRECTORY in a REF ARRAY @arr = sort keys(%am_hash); $cnt = scalar @arr; my $subcount = 0; foreach $tmp (@arr) { $tmp = trim_all($tmp); next if (length($tmp) == 0); $subcount++; } prt("\nCMake Project [$proj_title], root [$proj_root], with $cnt SUBDIRS ($subcount)\n"); my ($inc_dirs); my %cmake_thash = (); # CMakeFile.txt text hash, per (tmp) output file my %cmake_files = (); # mapping REAL file to tmp output file my $pgmname = get_pgmname(); my $lib_type = ($def_to_shared ? "ON" : "OFF"); my $cmake_root = "\n# $proj_root"."CMakeLists.txt, generated $pgmname, on "; $cmake_root .= lu_get_YYYYMMDD_hhmmss(time())."\n\n"; $cmake_root .= "cmake_minimum_required( VERSION 2.6 )\n\n"; $cmake_root .= "project( $proj_title )\n\n"; $cmake_root .= "# The version number.\n"; # TODO ***TBD*** This VERSION stuff MUST BE FIXED ONE DAY # ======================================================= $cmake_root .= "set( ${proj_title}_VERSION_MAJOR 3 )\n"; $cmake_root .= "set( ${proj_title}_VERSION_MINOR 0 )\n"; $cmake_root .= "set( ${proj_title}_VERSION_POINT 0 )\n\n"; $cmake_root .= add_options_block($lib_type); $cmake_root .= get_definitions_block(); # setup global DEFINES @arr = keys(%usrdefs); $val = ''; foreach $tmp (@arr) { $tmp = trim_all($tmp); next if (length($tmp) == 0); next if (defined $defines_added{$tmp}); $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); $defines_added{$tmp} = 1; $val .= ' ' if (length($val)); $val .= "-D$tmp"; } $cmake_root .= "add_definitions( $val )\n" if (length($val)); # setup INCLUDE directories @arr = keys(%usrincs); $inc_dirs = ''; my @last_dirs = (); # 20120524 - always put /3rdparty/ LAST foreach $tmp (@arr) { $tmp = trim_all($tmp); next if (length($tmp) == 0); $tmp = path_d2u($tmp); if ( !($tmp =~ /^\w{1}:(\\|\/)/) ) { # not absolute - add prefix $tmp = "\${PROJECT_BINARY_DIR}/$tmp"; } $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); if ($tmp =~ /(\\|\/)3rdParty(\\|\/)/i) { push(@last_dirs,$tmp); } else { $inc_dirs .= ' ' if (length($inc_dirs)); $inc_dirs .= $tmp; } } if (@last_dirs) { $inc_dirs .= ' ' if (length($inc_dirs)); $inc_dirs .= join(" ",@last_dirs); } my ($minn,$mint,$len,$dnm,$typ,$deps,$scnt,$xit); my ($var2,$slist,$hlist,$val2); # separate by is_c_source_extended() or is_h_source() @arr = sort keys(%sub_dirs); $val = ''; @last_dirs = (); # clear last foreach $tmp (@arr) { $tmp = trim_all($tmp); next if (length($tmp) == 0); $tmp = path_d2u($tmp); # cmake LIKES unix paths # or s/\\/\\\\/g; #if ( !($tmp =~ /^\w{1}:\//) ) { # # not absolute - add prefix # $tmp .= "\${PROJECT_BINARY_DIR}/$tmp"; #} $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); if ($tmp =~ /(\\|\/)3rdParty(\\|\/)/i) { push(@last_dirs,$tmp); } else { $val .= ' ' if (length($val)); $val .= $tmp; } } if (@last_dirs) { $val .= ' ' if (length($val)); $val .= join(" ",@last_dirs); } #$cmake_root .= "INCLUDE_DIRECTORIES( SYSTEM $inc_dirs )\n" if (length($inc_dirs)); #$cmake_root .= "message( \"*** Current binary directory [\${PROJECT_BINARY_DIR}] ***\" )\n"; $cmake_root .= "\ninclude_directories( SYSTEM \"\${PROJECT_BINARY_DIR}\" $val )\n\n"; ### $cmake_root .= "ADD_SUBDIRECTORY( $val )\n"; # NO WAY - seems each must ONLY BE ONE AT A TIME my %added_subs = (); foreach $tmp (@arr) { $tmp = trim_all($tmp); next if (length($tmp) == 0); $tmp = path_d2u($tmp); # or =~ s/\\/\\\\/g; next if (defined $added_subs{$tmp}); # skip if already added $added_subs{$tmp} = 1; $tmp = '"'.$tmp.'"' if ($tmp =~ /\s/); $cmake_root .= "add_subdirectory( $tmp )\n"; # Add ONE AT A TIME } # NOTE: Fully EXCLUDED projects are NOT in the REF ARRAY for EACH HASH directory of the SOURCE $minn = 0; $mint = 0; my ($am_key); foreach $am_key (keys %am_hash) { $ra = $am_hash{$am_key}; foreach $rh (@{$ra}) { if ( ! test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile) ) { $len = length($pname); $minn = $len if ($len > $minn); $len = length($ptype); $mint = $len if ($len > $mint); } } } my $PATH_SEP = get_PATH_SEP(); my $dsp_out_dir = get_dsp_out_dir(); my %added_lists = (); my $add_2_root = ''; # AVOID 2 CMakeLists.txt - temp..txt and temp.root.txt my @srcarr = (); my @hdrarr = (); my ($line); my $indent = 3; foreach $am_key (sort keys %am_hash) { $ra = $am_hash{$am_key}; $cnt = scalar @{$ra}; $amdir = $proj_root.$am_key.$PATH_SEP."CMakeLists.txt"; if (length($am_key)) { $tmp = $am_key; $tmp = path_d2u($tmp); # cmake LIKES unix paths # or s/\\/\\\\/g; $added_lists{$tmp} = 1; # this is again sort of EACH subdirectory } $tmp = $am_key; $tmp =~ s/\\/_/g; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.$tmp.txt"; if ((defined $cmake_thash{$tmpout}) || (defined $cmake_files{$tmpout})) { pgm_exit(1,"ERROR: A hash has like a DUPLICATE key [$am_key]! Check how to make [$tmpout] UNIQUE!\n"); } prt("cmake: $amdir has $cnt projects\n"); # set INTITAL CMakeLists.txt entry $tmp = "\n# $amdir, generated by $pgmname on ".lu_get_YYYYMMDD_hhmmss(time())."\n\n"; $tmp .= "include_directories( \"\${PROJECT_BINARY_DIR}\" $inc_dirs )\n\n"; #$tmp .= "INCLUDE_DIRECTORIES( \${PROJECT_BINARY_DIR}\ )\n"; #$tmp .= "INCLUDE_DIRECTORIES( $inc_dirs )\n" if (length($inc_dirs)); $tmp .= "\n"; if (length($am_key)) { $cmake_thash{$tmpout} = $tmp; # start cmake text for this file $cmake_files{$tmpout} = $amdir; # map 'tmp' to real target file } else { $add_2_root .= $tmp; # $key of NO length == root stuff } foreach $rh (@{$ra}) { if ( ! test_ref_hash($rh,\$proot,\$rcfgs,\$pname,\$ptype,\$psrcs,\$amfile) ) { if (is_project_all_excluded($pname)) { # if the PROJECT is EXCLUDED forget it prtw("WARNING: An EXCLUDED project has been added! FIX THIS\n"); next; } $rp = ${$rh}{'PROJECT_RP'}; # extract $rp; # all keep REF PROJECT HASH in REF HASH $inst = ${$rp}{'PROJECT_INST'}; $cmake = ''; $rpda = ${$rh}{'PROJECTS_DEPENDS_ARRAY'}; # = \@deps; # Project DEPENDS array - can be none $deps = ''; my %extra_libs = (); foreach $tmp (@{$rpda}) { $deps .= ' ' if (length($deps)); $deps .= $tmp; $extra_libs{$tmp} = 1; } #$cmake .= "MESSAGE(\"Current build directory \${CMAKE_CURRENT_BUILD_DIR}\")\n"; #$cmake .= "INCLUDE_DIRECTORIES( \"\${CMAKE_CURRENT_BUILD_DIR}\" )\n"; #$cmake .= "MESSAGE(\"Current binary directory [\${PROJECT_BINARY_DIR}]\")\n"; #$cmake .= "INCLUDE_DIRECTORIES( \"\${PROJECT_BINARY_DIR}\" )\n"; $var = $pname."_SRCS"; $var2 = $pname."_HDRS"; $slist = ''; $hlist = ''; $scnt = 0; my %dupes = (); ## 0 1 2 3 #push(@sources, [ $sfil, $group, $filter, $xit, '' ]); # ${$rph}{'PROJECT_SRCS'} my $relhlist = ''; my $hcnt = 0; @srcarr = (); # clear source array @hdrarr = (); foreach $rsa (@{$psrcs}) { $tmp = ${$rsa}[0]; $xit = ${$rsa}[3]; next if ($xit); # excluded SOURCE file my ($n,$d) = fileparse($tmp); next if ($n eq 'unistd.h'); # why MUST I exclude this?????? TODO if (!defined $dupes{$n}) { $dupes{$n} = 1; if (is_c_source_extended($tmp)) { $slist .= ' ' if (length($slist)); $slist .= $n; push(@srcarr,$n); # store in SOURCE $scnt++; } elsif (is_h_source($tmp)) { $hlist .= ' ' if (length($hlist)); $hlist .= $n; ###$scnt++; $relhlist .= ' ' if (length($relhlist)); $relhlist .= $tmp; $hcnt++; } else { prtw("WARNING: SOURCE [$tmp] NOT ADDED! Not 'C' or 'H'! WHat is IT?\n"); } } } prt("cmake: project [$pname] has $scnt sources, $hcnt headers\n"); prt("cmake: sources: [$slist] headers [$relhlist]\n"); if ($scnt) { @hdrarr = (); # header array if (length($relhlist)) { @arr = space_split($relhlist); $relhlist = ''; foreach $tmp (@arr) { if ($use_just_file_name) { ($tmp,$tdir) = fileparse($tmp); $relhlist .= "$tmp "; push(@hdrarr,"$tmp"); } else { $tmp = path_d2u($tmp); # TODO **TBD** really need to LOCATE this HEADER, in source # and ADD appropriate relative path to it! if ($add_proj_bin_dir) { $relhlist .= "\${PROJECT_BINARY_DIR}/$tmp "; push(@hdrarr,"\${PROJECT_BINARY_DIR}/$tmp"); } else { $relhlist .= "$tmp "; push(@hdrarr,"$tmp"); } } } } $msg = ''; $cmake .= "# Project [$pname] [$ptype] [$inst], with $scnt sources."; $cmake .= " $hcnt hdrs." if ($hcnt); @arr = keys(%extra_libs); if (@arr) { $tmp = scalar @arr; $cmake .= " deps [".join(" ",@arr)."]$tmp"; } $cmake .= "\n"; if (length($slist)) { ###$msg .= "set( $var $slist )\n"; $line = ''; $msg .= "set( $var "; foreach $tmp (@srcarr) { $line .= "$tmp "; if (length($line) > $max_set_line_len) { $msg .= "$line\n"; $line = ' ' x $indent; # indent say 3 spaces } } if (length($line) > $indent) { $msg .= $line; } else { $msg =~ s/\n$//; # clear new line } $msg .= ")\n"; } if (length($relhlist)) { ###$msg .= "set( $var2 $relhlist )\n"; $msg .= "set( $var2 "; $line = ''; # clear line accumulation foreach $tmp (@hdrarr) { $line .= "$tmp "; if (length($line) > $max_set_line_len) { $msg .= "$line\n"; $line = ' ' x $indent; # indent } } if (length($line) > $indent) { $msg .= $line; } else { $msg =~ s/\n$//; # remove trailing new line } $msg .= ")\n"; } $cmake .= "$msg"; ### prt("$msg\n"); if ($ptype eq 'Console Application') { # DO AN EXE # ========= $msg = "\nadd_executable( $pname "; $msg .= "\${$var} " if (length($slist)); $msg .= "\${$var2} " if (length($hlist)); $msg .= ")\n"; $cmake .= "$msg"; # if (($proj_type ne 'SL') && ($auto_on & 16) && ($auto_on & 2048)) { if (($auto_on & 16) && ($auto_on & 2048)) { # target_link_libraries(mylib public1 public2 PRIVATE private1 private2) # $cmake .= "TARGET_LINK_LIBRARIES( $pname PRIVATE getopt.lib )\n"; # need to eliminate (s) system libs, (b) dependent libs, in $rpda (ref proj dep array), # and separate balance into lib and path $tmp = get_cmake_lib_finds($rp); if (length($tmp)) { $cmake .= $tmp; prt("$tmp\n") if (VERB9()); } else { prt("Project [$pname] has NO dependent libraries.\n") if (VERB9()); } } else { prtw("WARNING: ((\$auto_on & 16) && (\$auto_on & 2048)) bit NOT set, so NO library FIX! value is [$auto_on]\n"); } # try - AND IT WORKED - phew ;=)) # set_target_properties (helloDemo PROPERTIES DEBUG_POSTFIX "d") if (length($add_exe_postfix)) { # we have a CMAKE_DEBUG_POSTFIX for an EXE $msg = "set_target_properties( $pname PROPERTIES DEBUG_POSTFIX \"$add_exe_postfix\" )\n"; $cmake .= $msg; } $msg = "install(TARGETS $pname DESTINATION $ibinp)\n"; $msg .= "install(FILES \${$var2} DESTINATION $ihdrp)\n" if (length($hlist)); if ($inst =~ /noinst/) { $cmake .= "\n# NO INSTALL [$inst]\n"; } else { $cmake .= $msg if ($add_exe_install); } } elsif ($ptype eq 'Static Library') { # DO A STATIC LIBRARY # =================== $msg = "\nadd_library( $pname \${LIB_TYPE} "; $msg .= "\${$var} " if (length($slist)); $msg .= "\${$var2} " if (length($hlist)); $msg .= ")\n"; $cmake .= "$msg\n"; # # add the install targets # ============================================== # DEAL WITH LIBRARY INSTALL # ============================================== # install (TARGETS Hello DESTINATION lib) # install (FILES ${HELLO_HDRS} DESTINATION include) # $msg = "install(TARGETS $pname DESTINATION $ilibp)\n"; $msg = "\n# deal with install \n"; $msg .= "install( TARGETS $pname\n"; $msg .= " RUNTIME DESTINATION bin\n"; $msg .= " LIBRARY DESTINATION lib\n"; $msg .= " ARCHIVE DESTINATION lib )\n"; # install( FILES ${apr_HEADERS} DESTINATION include ) # OOPS, sometimes the header can be 'local', like # tiffconf.h, tif_config.h are in "\${PROJECT_BINARY_DIR}, and NOT in # "\${PROJECT_SOURCE_DIR}/libtiff where CMake will think they should be... if ($use_single_inc_list) { $msg .= "install(FILES \${$var2} DESTINATION $ihdrp)\n" if (length($hlist)); } elsif (length($hlist)) { my ($itm,$hfile); my @narr = (); my @sarr = (); @arr = space_split($hlist); foreach $itm (@arr) { # maybe get each file from the scan list, or if (length($am_key)) { $hfile = $proj_root.$am_key.$PATH_SEP.$itm; } else { $hfile = $proj_root.$itm; } if (-f $hfile) { push(@narr,$itm); # found in 'normal' place } else { push(@sarr,"\${PROJECT_BINARY_DIR}/$itm"); } } $msg .= "install(FILES ".join(" ",@narr)." DESTINATION $ihdrp)\n" if (@narr); $msg .= "install(FILES ".join(" ",@sarr)." DESTINATION $ihdrp)\n" if (@sarr); #if ($pname eq 'tiff') { # prt("Need to examine this list [$hlist], and have separate installs!\n"); # prt("$msg\n"); # pgm_exit(1,"TEMP EXIT"); #} } if ($inst =~ /noinst/) { $cmake .= "\n# NO INSTALL [$inst]\n"; } else { $cmake .= $msg if ($add_lib_install); } } else { # OTHERS TODO ***TBD*** prtw("WARNING: Unhandled project type [$ptype]! FIX ME\n"); } @arr = keys %extra_libs; if (@arr) { $cmake .= "\ntarget_link_libraries( $pname "; $cmake .= join(" ",@arr); $cmake .= " )\n"; } $cmake .= "\n"; # separate from the next # STORE THIS CMAKE TEXT UNDER THE FILE NAME # ========================================= if (length($am_key)) { $cmake_thash{$tmpout} .= $cmake; # accumulate the CMake text } else { $add_2_root .= $cmake; } # ========================================= # display ONLY # ------------------------------------------------- $dnm = $pname; $typ = $ptype; $dnm .= ' ' while (length($dnm) < $minn); $typ .= ' ' while (length($typ) < $mint); $msg = " $dnm [$typ] srcs $scnt"; $msg .= ", deps [$deps]" if (length($deps)); prt("$msg\n"); prt($cmake) if (VERB9()); # ------------------------------------------------ $cmake = ''; # clean this 'cmake' } else { prtw("WARNING: No SOURCES found for [$pname]!\n"); } } } } # this SHOULD have been done before her, but better late than never # compare ADDED subdirectories - my %added_subs = (); # with ADDED CMakeLists.txt files - my %added_lists = (); # Added SUBDIRS # contrib/addtiffo contrib/dbs contrib/iptcutil libtiff port test tools # Added CMAKE LISTS # contrib/addtiffo contrib/dbs libtiff port tools my ($skey); foreach $skey (keys %added_subs) { next if (length($skey) == 0); # donot deal with a blank if (!defined $added_lists{$skey}) { # need to generate a CMakeLists.txt for here $tmp = $skey; $tmp =~ s/\\/_/g; $tmp =~ s/\//_/g; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.$tmp.txt"; if ((defined $cmake_thash{$tmpout}) || (defined $cmake_files{$tmpout})) { pgm_exit(1,"ERROR: A hash has like a DUPLICATE key [$skey]! Check how to make [$tmpout] UNIQUE!\n"); } $amdir = $proj_root.$skey.$PATH_SEP."CMakeLists.txt"; # set INTITAL CMakeLists.txt entry $tmp = "\n# $amdir, generated by $pgmname on ".lu_get_YYYYMMDD_hhmmss(time())."\n\n"; $tmp .= "# Page deliberately BLANK\n\n"; $cmake_thash{$tmpout} = $tmp; # start cmake text for this file $cmake_files{$tmpout} = $amdir; # map 'tmp' to real target file } } if ($write_cmake_files) { my $target_dir = ${$rparams}{'TARGET_DIR'}; my $battxt = "\@setlocal\n"; $battxt .= "\@set COUNT=0\n"; my ($real); $cnt = 0; @arr = (); foreach $tmp (keys %cmake_thash) { $val = $cmake_thash{$tmp}; $real = $cmake_files{$tmp}; $val .= "\n# eof\n"; $battxt .= "\@set /A COUNT+=1\n"; $battxt .= "\@copy \"$tmp\" \"$real\" >nul\n"; write2file($val,$tmp); $cnt++; prt("$cnt: Written [$tmp] for [$real]\n"); push(@arr,$real); } $cmake_root .= $add_2_root; # FINALISE CMakeLists.txt for ROOT $cmake_root .= "\n# eof\n"; $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.root.$proj_title.txt"; $real = $proj_root."CMakeLists.txt"; # $tmpout = $dsp_out_dir.$PATH_SEP."temp.root.$proj_title.txt"; write2file($cmake_root,$tmpout); push(@arr,$real); $cnt++; prt("$cnt: Written final [$tmpout] for [$real]\n"); $battxt .= "\@set /A COUNT+=1\n"; $battxt .= "\@copy \"$tmpout\" \"$real\" >nul\n"; $battxt .= "\@echo Copied \%COUNT\% CMakeLists.txt files into place\n"; # Write a simple CMakeLists.txt list to $tmpout = $dsp_out_dir; fix_dir_string(\$tmpout); $tmpout .= "temp.list.$proj_title.txt"; write2file(join("\n",@arr)."\n",$tmpout); $real = $target_dir."cmakelist.txt"; $battxt .= "\@copy \"$tmpout\" \"$real\" >nul\n"; $battxt .= "\@echo And copied a list file '$real'.\n"; $tmp = "C:\\MDOS"; $tmpout = $dsp_out_dir; $tmpout = $tmp if (-d $tmp); fix_dir_string(\$tmpout); $tmpout .= "tempcmake.bat"; write2file($battxt,$tmpout); prt("Written [$tmpout] batch file to copy CMake files into place.\n"); } else { prt("Write CMake CMakeLists.txt files disabled. Used -cmake to enable.\n"); } # pgm_exit(1,"TEMP EXIT"); return 0; # success } 1; # eof