@goto invoke_perl #!/usr/bin/perl # Copyright (C) 2015 The Qt Company Ltd. # Contact: http://www.qt.io/licensing/ # # You may use this file under the terms of the 3-clause BSD license. # See the file LICENSE from this package for details. # # Use modules -------------------------------------------------------- use strict; use File::Basename; my $script_path = dirname($0); $script_path =~ s=^/(.)/=\1:\\=; $script_path =~ s=/=\\=g; # Simplify program name, if it is a path. my $orig_argv0 = $0; #save the old $0 $0 =~ s/.*(\\|\/)//; my @targetProjects; my @allPossibleTargetProjects; my $compiler = "msvc"; # Default compiler my $verbose = 0; my $openMonitor = 0; my $configuration = ""; my $lastTarget = ""; my $projectFile = ""; my $isSolution = 0; my $passOnArguments = ""; my $lastKnownArgument = 0; my $onlyShow = 0; my $buildforks = 15; sub usage { printf "Usage:\n"; printf "$0 [project file <.pro, .sln/.vcproj, or .dsw/.dsp>] [projects in the .sln file] \n"; printf " [-j] [[-c] configuration] [--monitor] [--help | -help]\n\n"; printf " By default, without any parameters, $0 will build the project or whole\n"; printf " solution in debug configuration. If no .sln or .vcproj file is found\n"; printf " in the current directory, the first .pro is generated, and its resulting\n"; printf " project file is used.\n\n"; printf " If a directory contains more than one project/solution file, you'll have\n"; printf " to specify the target. If a project/solution contains more than one\n";; printf " configuration containing \"debug\", you'll have to specify the correct one.\n"; printf " (If the last 'project' on the commandline is either \"debug\" or \"release\"\n"; printf " it is assumed that you meant a configuration, so for these you don't need to\n"; printf " specify the '-c' option. For all others, you'll need the '-c' option)\n\n"; printf " Specifying a project within a solution file lets you build just a project\n"; printf " and its dependencies.\n\n"; printf " -j Sets the number of jobs for this build using the /MAXCPUS=\n"; printf " option for MSVC builds, and the -j option for MinGW builds\n"; printf " --n Show everthing that will be done, but don't actually do them\n"; printf " --monitor Opens the build monitor, if not already open. (same as\n"; printf " specifying /buildmonitor)\n"; printf " --help, -help This help\n\n"; printf " Specifying any other option will simply pass the option on to the\n"; printf " buildconsole command, including any other arguments following an the last\n"; printf " known $0 option.\n\n"; printf " Ex:\n"; printf " $0 release\n"; printf " Builds the project / solution in release\n"; printf " $0 debug release\n"; printf " Builds the \"debug\" project in a solution in release\n"; printf " $0 release debug\n"; printf " Builds the \"release\" project in a solution in debug\n"; printf " $0 some_project.vcproj release\n"; printf " Builds the \"some_project\" project in release\n"; printf " $0 some_project.vcproj -c profiled\n"; printf " Builds the \"some_project\" project in profiled configuration\n"; printf " $0 some_big_project.sln test_app -c profiled\n"; printf " Builds the \"test_app\" project (and its dependencies) in the\n"; printf " \"some_big_project\" solution in profiled configuration\n"; exit( 0 ); } ###################################################################### # Syntax: findFiles(dir, match, descend) # Params: dir, string, directory to search for name # match, string, regular expression to match in dir # descend, integer, 0 = non-recursive search # 1 = recurse search into subdirectories # # Purpose: Finds files matching a regular expression. # Returns: List of matching files. # # Examples: # findFiles("/usr","\.cpp$",1) - finds .cpp files in /usr and below # findFiles("/tmp","^#",0) - finds #* files in /tmp ###################################################################### sub findFiles { my ($dir,$match,$descend) = @_; my ($file,$p,@files); local(*D); $dir =~ s=\\=/=g; ($dir eq "") && ($dir = "."); if ( opendir(D,$dir) ) { if ( $dir eq "." ) { $dir = ""; } else { ($dir =~ /\/$/) || ($dir .= "/"); } foreach $file ( readdir(D) ) { next if ( $file =~ /^\.\.?$/ ); $p = $file; ($file =~ /$match/) && (push @files, $p); if ( $descend && -d $p && ! -l $p ) { push @files, &findFiles($p,$match,$descend); } } closedir(D); } return @files; } sub findProjectFile { printf "Searching for sln/dsw files......"; my @filesFound = findFiles(".", "^.*\.(sln|dsw)\$", 0); if (scalar(@filesFound) == 0) { printf "[none]\n"; printf "Searching for vcproj/dsp files..."; @filesFound = findFiles(".", "^.*\.(vcproj|dsp)\$", 0); } if (scalar(@filesFound) == 0) { printf "[none]\n"; printf "Searching for Makefiles files...."; @filesFound = findFiles(".", "^Makefile\$", 0); foreach my $file (@filesFound) { my @configs = findPossibleConfigurations($file, "", @targetProjects); # If the Makefile is for msvc, clear it, as we # want to use MSVC projects for that compiler @filesFound = () if ($compiler eq "msvc"); } } if (scalar(@filesFound) == 0) { printf "[none]\n"; printf "Searching for .pro files........."; @filesFound = findFiles(".", "^.*\.pro\$", 0); } if (scalar(@filesFound) == 0) { printf "[error]\n"; printf "Found no possible project file! You can't build in this directory!\n"; exit(1); } my $found = join(", ", @filesFound); printf "[$found]\n"; if (scalar(@filesFound) > 1) { printf "Too many possible project files! You have to specify the correct file!\n"; exit(2); } return pop @filesFound; } sub findPossibleConfigurations { my ($file, $conf, @prjs) = @_; my @possibleConf; # Load contents of $file into $filecontents open(I, "< " . $file) || die "Could not open $file for reading"; my @filecontents = ; close I; # MSVC.NET Solution file ------- if ($file =~ /\.sln$/) { my @confs = grep(/[ \t]*ConfigName\.\d+[ \t]+=.*$conf.*/i, @filecontents); foreach (@confs) { my $txt = $_; $txt =~ s,^[^=]*=\s*(.*)\s*$,\1,; $txt =~ tr/\r//d; push @possibleConf, $txt; } # 2005 version ------- my @confs = grep(/[ \t]*$conf\|\w+[ \t]+=.*$conf\|.*/i, @filecontents); foreach (@confs) { my $txt = $_; $txt =~ s,^[^=]*=\s*(.*)\s*$,\1,; $txt =~ tr/\r//d; push @possibleConf, $txt; } # MSVC.NET Project file -------- } elsif ($file =~ /\.vcproj$/) { # Resplit the file in XML elements instead my $flatContents = join(" ", @filecontents); $flatContents =~ s/[\r\n]//g; $flatContents =~ s/\s\s+/ /g; $flatContents =~ s/> />\n/g; @filecontents = split(/\n/, $flatContents); my @confs = grep(/^ 1 && scalar grep("^$configuration\$", @fullConfigurationNames) > 1) { my $allConfs = join(", ", @fullConfigurationNames); printf "* Too many possible configurations ($allConfs), so you have to specify one\n"; exit(3); } $configuration = pop @fullConfigurationNames; } my $projects = join(" ", @targetProjects); printf "---\n"; printf "Using IncrediBuild for $compiler building:\n"; printf " Project: $projectFile\n"; if ($projects eq "" || $projects eq join(" ", @allPossibleTargetProjects)) { printf " Targets: (%s)\n", ($compiler eq "msvc") ? "all" : "first"; } else { printf " Targets: $projects\n"; } printf " As: $configuration\n"; printf " Arguments: $passOnArguments\n"; # Check if Makefile # Detect which compiler ($compiler) # Use xgconsole my $build_cmd; if ($compiler eq "msvc") { # MSVC buildconsole command -------------------------------------------------------------------- my $prjComma = join(",", @targetProjects); $build_cmd = "buildconsole "; $build_cmd .= "$projectFile "; $build_cmd .= "-PRJ=\"$prjComma\" " if ($projects ne ""); $build_cmd .= "-CFG=\"$configuration\" "; $build_cmd .= "-MAXCPUS=$buildforks "; $build_cmd .= "-OPENMONITOR " if ($openMonitor); $build_cmd .= "-USEENV $passOnArguments"; } else { # Makefile xgconsole command ------------------------------------------------------------------- my $xgeprofile = $script_path; $xgeprofile .= ($compiler eq "mingw") ? "\\mingw-xge-profile.xge" : "\\icc-xge-profile.xge"; $build_cmd = "xgconsole "; $build_cmd .= "-OPENMONITOR " if ($openMonitor); $build_cmd .= "-PROFILE=\"$xgeprofile\" "; $build_cmd .= "-COMMAND=\""; $build_cmd .= ($compiler eq "mingw") ? "mingw32-make" : "make"; $build_cmd .= " -j$buildforks"; $build_cmd .= " $projects" if ($projects ne ""); $build_cmd .= "\" $passOnArguments"; } printf " Build CMD: $build_cmd\n"; printf "---\n"; if (!$onlyShow) { system($build_cmd); exit $? >> 8; } __END__ :invoke_perl @perl -x %~f0 %*