📄 tmake
字号:
#!/usr/bin/perl############################################################################# $Id: tmake,v 1.72 1999/08/02 16:31:06 hanord Exp $## Creates a Makefile from a template and a project file.## Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.## Permission to use, copy, modify, and distribute this software and its# documentation for any purpose and without fee is hereby granted, provided# that this copyright notice appears in all copies.# No representations are made about the suitability of this software for any# purpose. It is provided "as is" without express or implied warranty.### Some important, global variables in tmake:# cpp_ext C++ extension added to moc output (.cpp)# obj_ext Object file extension (.o on Unix, .obj otherwise)# moc_aware Will scan for files containing Qt signals/slots# moc_pre Moc prefix for generated moc file: x.h -> moc_x.cpp# moc_ext Moc extension for generated moc file: x.cpp -> x.moc# moc_cmd The moc command in your makefile, $(MOC)# linebreak Line break character (\)# dir_sep Directory separator (/ on Unix, \ on Windows)# is_unix Autodetected. If not Unix, assume Windows (Win32).## If you need to customize any of these settings, do it before# calling StdInit() in the template file.#############################################################################$TMAKE_VERSION = "1.3";if ($] < 5.0) { &tmake_error("This program requires perl version 5 or newer");}$cpp_ext = "cpp";$moc_aware = 0;$moc_pre = "moc_";$moc_ext = "moc";$moc_cmd = '$(MOC)';$linebreak = "\\";$really_unix = &check_unix();$is_unix = $really_unix;$dir_sep = $is_unix ? "/" : "\\";$obj_ext = $is_unix ? "o" : "obj";$depend_path = "";$nodepend = 0;$output_count = 0;$notrim_whitespace = 0;$read_tmakeconf = 0; $template_name = "";$project_name = "";$outfile = "";%project = ();$eval_quit = 0;$project{"TMAKEPATH"} = $ENV{"TMAKEPATH"} . ";" . $ENV{"HOME"} . "/.tmake/";while ( @ARGV ) { # parse command line args $_ = shift @ARGV; if ( s/^-// ) { if ( /^e(.*)/ ) { if ( ! $read_tmakeconf ) { $read_tmakeconf = 1; &ScanProject( &find_template("tmake.conf") ); } $text = ""; eval( ($1 eq "") ? shift @ARGV : $1 ); die $@ if $@; print $text . "\n" if ($text ne ""); $eval_quit = 1; } elsif ( /^t(.*)/ ) { $template_name = ($1 eq "") ? shift @ARGV : $1; } elsif ( /^o(.*)/ ) { $outfile = ($1 eq "") ? shift @ARGV : $1; ($outfile eq "-") && ($outfile = ""); if ( $outfile ne "" ) { open(STDOUT,">" . fix_path($outfile)) || &tmake_error("Can't create \"$outfile\""); } } elsif ( /^p(.*)/ ) { # # The -p option is obsolete and will be removed in the next # tmake release. # &tmake_warning( "-p option obsolete, instead use \"tmake file1.pro file2.pro ...\""); my($pf) = ($1 eq "") ? shift @ARGV : $1; if ( ! $read_tmakeconf ) { $read_tmakeconf = 1; &ScanProject( &find_template("tmake.conf") ); } if ( ! ($pf =~ /\.pro$/i) && -f fix_path($pf . ".pro") ) { $pf .= ".pro"; } if ( $project_name eq "" ) { $project_name = $pf; $project{"PROJECT"} = $project_name; $project{"PROJECT"} =~ s/\.pro$//i; $project{"TARGET"} = $project{"PROJECT"}; } if ( !&ScanProject($pf) ) { &tmake_error("Can't open project file \"$pf\""); } } elsif ( /^unix$/ ) { $is_unix = 1; $dir_sep = "/"; $obj_ext = "o"; } elsif ( /^win32$/ ) { $is_unix = 0; $dir_sep = "\\"; $obj_ext = "obj"; } elsif ( /^nodepend$/ ) { $nodepend = 1; # don't generate dependencies } elsif ( /^v$/ ) { $verbose = 1; } else { &tmake_usage(); } } elsif ( /^\s*((?:[^:\s]*?:)?)(\w+)\s*(\+=|\*=|\-=|\/=|=)/ ) { if ( ! $read_tmakeconf && ! (/^\s*TMAKEPATH/) ) { $read_tmakeconf = 1; &ScanProject( &find_template("tmake.conf") ); } Project( $_ ); # manual project setting } else { my($pf) = $_; if ( ! $read_tmakeconf ) { $read_tmakeconf = 1; &ScanProject( &find_template("tmake.conf") ); } if ( ! ($pf =~ /\.pro$/i) && -f fix_path($pf . ".pro") ) { $pf .= ".pro"; } if ( $project_name eq "" ) { $project_name = $pf; $project{"PROJECT"} = $project_name; $project{"PROJECT"} =~ s/\.pro$//i; $project{"TARGET"} = $project{"PROJECT"}; } if ( !&ScanProject($pf) ) { &tmake_error("Can't open project file \"$pf\""); } }}&tmake_verb("Version $TMAKE_VERSION (runtime environment: " . ($really_unix ? "Unix" : "Win32") . ")\n" );if ( $eval_quit ) { &tmake_verb("Done!"); exit 0;}($project_name eq "") && &tmake_usage();if ( $template_name eq "" ) { $template_name = $project{"TEMPLATE"} ? $project{"TEMPLATE"} : "default.t";}$template_name = &find_template($template_name);&IncludeTemplate($template_name);&tmake_verb("Done!");exit 0; # finished!############################################################################### Subroutines from here################################################################################ tmake_usage()## Prints a message about program usage and exits#sub tmake_usage { print STDERR "Usage:\n tmake [options] project-files\n"; print STDERR "Options:\n"; print STDERR " -e expr Evaluate expression, ignore template file\n"; print STDERR " -nodepend Don't generate dependency information\n"; print STDERR " -o file Write output to file\n"; print STDERR " -t file Specify a template file\n"; print STDERR " -unix Create output for Unix (auto detects)\n"; print STDERR " -v Verbose/debug mode\n"; print STDERR " -win32 Create output for Win32 (auto detects)\n"; exit 1;}## tmake_error(msg)## Prints the message and exits#sub tmake_error { my($msg) = @_; print STDERR "tmake error: " . $msg . "\n"; exit 1;}## tmake_warning(msg)## Prints the warning message#sub tmake_warning { my($msg) = @_; print STDERR "tmake warning: " . $msg . "\n";}## tmake_verb()## Prints a verbose message#sub tmake_verb { my($msg) = @_; $verbose && print STDERR "tmake: " . $msg . "\n";}## check_unix()## Returns 1 if this is a Unix, 0 otherwise.#sub check_unix { my($r); $r = 0; if ( -f "/bin/uname" ) { $r = 1; (-f "\\bin\\uname") && ($r = 0); } if ( -f "/usr/bin/uname" ) { $r = 1; (-f "\\usr\\bin\\uname") && ($r = 0); } return $r;}## find_template(filename)## Looks for the template file.# 1. search the current directory# 2. search the directories in TMAKEPATH# 3. search in $HOME/.tmake#sub find_template { my($filename) = @_; my($tb,$d,$p,@dirs); if ( !defined($template_base) || ($template_base eq "") ) { $tb = ""; } else { $tb = $template_base . ";"; } $d = $tb . $project{"TMAKEPATH"}; @dirs = (""); push @dirs, &split_path( $d ); $filename .= ".t" unless ($filename =~ /\.\w+$/); for $d ( @dirs ) { $p = $d . $filename; if ( -f fix_path($p) ) { if ( $filename eq "tmake.conf" ) { $tmake_platform = $d; $tmake_platform =~ s-.*[/\\]([^/\\]*)[/\\]-$1-; &tmake_verb("Detected platform $tmake_platform"); } return $p; } return ($d . $filename) if ( -f fix_path($d . $filename) ); } &tmake_error("Template file " . $filename . " not found");}############################################################################### User functions################################################################################ StdInit()## Standard initialization#sub StdInit { my($p); return if $stdinit_done; $stdinit_done = 1; if ( defined($project{"OBJECTS_DIR"}) ) { $project{"OBJECTS_DIR"} = FixPath($project{"OBJECTS_DIR"}); &mkdirp($project{"OBJECTS_DIR"},0777); } if ( defined($project{"MOC_DIR"}) ) { $project{"MOC_DIR"} = FixPath($project{"MOC_DIR"}); &mkdirp($project{"MOC_DIR"},0777); } if ( defined($project{"DESTDIR"}) ) { $project{"DESTDIR"} = FixPath($project{"DESTDIR"}); &mkdirp($project{"DESTDIR"},0777); } $project{"OBJECTS"} = &Objects($project{"SOURCES"}); if ( $moc_aware ) { $project{"_HDRMOC"} = &list_moc($project{"HEADERS"},$moc_pre,$cpp_ext); $project{"_SRCMOC"} = &list_moc($project{"SOURCES"},"",$moc_ext); $project{"OBJMOC"} = &Objects($project{"_HDRMOC"}); $p = $project{"_HDRMOC"} . " " . $project{"_SRCMOC"}; $p =~ s/(^\s+|\s+$)//g; $project{"SRCMOC"} = $p; } &AddIncludePath("");}sub FixPath { my($p) = @_; if ( !defined($p) || ($p eq "") || ($p eq ".") ) { $p = ""; } else { $p .= $dir_sep; $p =~ s-[\\/]+-${dir_sep}-g; } return $p;}## Config(name)## Returns true if the project variable CONFIG contains the# configuration name.#sub Config { my($name) = @_; return $project{"CONFIG"} =~ /\b\Q$name\E\b/;}## DisableOutput()## Disables tmake output. Must be restored by calling a corresponding# EnableOutput().#sub DisableOutput { $output_count++;}## EnableOutput()## Enables tmake output again after DisableOutput() has been called.#sub EnableOutput { $output_count--;}## Now() - sets $text## Sets $text to the current date and time.#sub Now { my($sec,$min,$hour,$mday,$mon,$year); ($sec,$min,$hour,$mday,$mon,$year) = localtime(time()); $text = sprintf("%02d:%02d, %4d/%02d/%02d", $hour, $min, 1900+$year, 1+$mon, $mday);}## expand_project_var(var)## Internal function for Project().# Expands a project value string.#sub expand_project_var { my($v) = @_; my($c); return "" if !defined($v); $c = 0; while ( $c < 100 ) { # expand $$ if ( $v =~ s/(\$\$\w+)/\035/ ) { $_ = $1; s/\$\$//g; if ( !defined($project{$_}) ) { $v =~ s/\035//g; } else { $v =~ s/\035/$project{$_}/g; } $c++; } else { $c = 100; } } return $v;}## Project(strings)## This is a powerful function for setting or reading project variables.# Returns the resulting project variables (joined with space between).## Get a project variable:# $s = Project("TEMPLATE"); -> $s = "TEMPLATE"## Set a project variable:# Project("TEMPLATE = lib"); -> TEMPLATE = lib# Project("CONFIG =";) -> CONFIG empty## Append to a project variable:# Project("CONFIG = qt"); -> CONFIG = qt# Project("CONFIG += debug"); -> CONFIG = qt debug## Append to a project variable if it does not contain the value already:# Project("CONFIG = qt release"); -> CONFIG = qt release# Project("CONFIG *= qt"); -> CONFIG = qt release# Project("CONFIG *= opengl"); -> CONFIG = qt release opengl## Subtract from a project variable:# Project("THINGS = abc xyz"); -> THINGS = abc xyz# Project("THINGS -= abc"); -> THINGS = xyz## Search/replace on a project variable:# Project("CONFIG = tq opengl"); -> CONFIG = tq opengl# Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl## The operations can be performed on several project variables at a time.## Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm");#sub Project { my @settings = @_; my($r,$if_var,$t,$s,$v,$p,$c); $r = ""; foreach ( @settings ) { $v = $_; if ( $v =~ s/^\s*((?:[^:\s]*?:)?)(\w+)\s*(\+=|\*=|\-=|\/=|=)// ) { $if_var = $1; if ( $if_var ne "" ) { chop $if_var; if ( $if_var eq "unix" ) { return "" if !$is_unix; } elsif ( $if_var eq "win32" ) { return "" if $is_unix; } elsif ( ($if_var ne $tmake_platform) && !Config($if_var) ) { return ""; } } $t = $2; $s = $3; if ( ! $notrim_whitespace ) { $v =~ s/^\s+//; # trim white space $v =~ s/\s+$//; } $v = expand_project_var($v); $p = $project{$t}; if ( $s ne "=" && $v eq "" ) { # nothing to append, subtract or sed } elsif ( $s eq "=" ) { # set variable $p = $v; } elsif ( $s eq "+=" ) { # append if ( $p eq "" ) { $p = $v; } else { $p .= " " . $v; } } elsif ( $s eq "*=" ) { # append if not contained if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) { if ( $p eq "" ) { $p = $v; } else { $p .= " " . $v; } } } elsif ( $s eq "-=" ) { # subtract $p =~ s/$v//g; } elsif ( $s eq "/=" ) { # sed $cmd = '$p =~ ' . $v; eval $cmd; } $project{$t} = expand_project_var($p); } else { $p = expand_project_var($project{$v}); } if ( $p ne "" ) { $r = ($r eq "") ? $p : ($r . " " . $p); } } return $r;}## Substitute(string)## This function substitutes project variables in a text.## Example:# Substitute('The project name is "$$PROJECT"')#sub Substitute { my($subst) = @_; $text = expand_project_var($subst); return $text;}## ScanProject(file)## Scans a project file. Inserts project variables into the global# associative project array.#sub ScanProject { my($file) = @_; my($var,$val,@v,$more,$line,$endmark); $var = ""; $line = 0; open(TMP,fix_path($file)) || return 0; &tmake_verb("Reading the project file $file"); while ( <TMP> ) { $line++; s/\#.*//; # strip comment s/^\s+//; # strip white space s/\s+$//; if ( /^\s*((?:(?:[^:\s]*?:)?)\w+\s*(\+|\-|\*|\/)?=)/ ) { $var = $1; # var also contains the ".=" s/^.*?=\s*//; if ( /^\<\<(.*)$/ ) { $endmark = $1; $val = ""; while ( <TMP> ) { $line++; if ( /^\Q$endmark\E$/ ) { $endmark = ""; last; } $val .= $_; } if ( $endmark ne "" ) { tmake_error("$file:$line: End marker $endmark not found"); } chop $val if ( $val ne "" ); $notrim_whitespace++; Project( $var . $val ); $notrim_whitespace--; $var = ""; $_ = ""; } } if ( $var ne "" ) { $more = ( $_ =~ s/\s*\\\s*$// ); # more if \ at end of line push( @v, split( /\s+/, $_ ) ); if ( ! $more ) { $val = join(" ",@v); Project( $var . $val ); $var = ""; @v = (); } } elsif ( $_ ne "" ) { tmake_error("$file:$line: Syntax error"); } } close(TMP); &tmake_verb("Done reading the project file $file"); return 1;}## IncludeTemplate(template_name)## Includes and processes a template file.## Below, we read the template file and executes any perl code found.# Perl code comes after "#$". The variable $text contains the text# to replace the perl code that was executed.# Template comments begin with "#!".#sub IncludeTemplate { my($t_name) = @_; my($cmd,$cmd_block,$cmd_end,$is_cmd_block,$saveline,$spaceonly); local($text); local(*T); $t_name = &find_template($t_name); if ( $tmake_template_dict{$t_name} ) { &tmake_error("Cyclic template inclusion for $t_name"); } else { $tmake_template_dict{$t_name} = 1; } $template_base = $t_name; $template_base =~ s-(.*[/\\]).*-$1-; &tmake_verb("Reading the template $t_name"); open(T,fix_path($t_name)) || &tmake_error("Can't open template file \"$t_name\""); while ( <T> ) { if ( /\#\!/ ) { # tmake comment s/\s*\#\!.*//; next if /^$/; } if ( /\#\$(\{)?\s*(.*)\n/ ) { # code $cmd = $2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -