Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # COPYRIGHT 2018, TIOBE SOFTWARE B.V.
- # $Id: TICSBuildGradle.pm 36651 2019-02-13 17:23:07Z steneker $
- # $URL: svn+ssh://steneker@esp.tiobe.com/home/wilde/svnrepository/tics/branches/release/9.4.x/components/analyzer/TICSBuildGradle.pm $
- =head1 TICSBuildGradle
- Build integration for Gradle (https://gradle.org/)
- =cut
- package TICSBuildGradle;
- use TIOBEPragma;
- use Exception qw(:all);
- use List::MoreUtils qw(uniq);
- use List::Util qw(all);
- use TICSAccess;
- use TICSCompiler;
- use TICSConfig;
- use TICSEnv;
- use TICSFile;
- use TICSFiles;
- use TICSSystem;
- use TIOBEEnv;
- use TIOBEError;
- use TIOBEFiles;
- use TIOBEJson;
- use TIOBEOS;
- use TIOBEPerl;
- use TIOBEString;
- use TIOBESystem;
- use TICSServer;
- use TICSDatabase;
- my $TOOL = 'gradlew';
- sub IsBuildTypeEnumFiles () : Protected {
- return 0;
- }
- sub IsMakeFile ($) : Protected {
- my ($file) = @_;
- return grep { &TIOBEFiles::BaseName($file) eq $_} ('build.gradle', 'build.gradle.kts');
- }
- sub ExtractFilesFromMakefile ($) : Protected {
- my ($makefile) = @_;
- my $fileopts = {};
- try {
- $fileopts = &GetCompilerOptionsForMakefile($makefile);
- } except {
- my $err = &TIOBEError::Stringify(shift);
- &TICSSystem::Log(5073, $TOOL, $err)
- };
- return keys %$fileopts;
- }
- sub GetCompilerOptions ($$) : Protected {
- my ($inputfile, $target) = @_;
- my $makefile = &TICSFile::GetFileProperty($TICSFile::MAKEFILE, $inputfile);
- my $fileopts = &GetCompilerOptionsForMakefile($makefile);
- my @compileroptions = @{$fileopts->{$inputfile} // []};
- my ($pathoption) = grep($_->[0] eq '-compilerpath', @compileroptions);
- my $compilerpath = $pathoption->[1];
- &TICSCompiler::SetCompilerInfo($inputfile, 'None', 'kotlinc', $compilerpath, $target);
- return grep($_->[0] ne '-compilerpath', @compileroptions);
- return @{$fileopts->{$inputfile} // []};
- }
- {
- my %COMPOPTSCACHE = ();
- sub GetCompilerOptionsForMakefile ($) : Private {
- my ($makefile) = @_;
- $COMPOPTSCACHE{$makefile} //= &GetCompilerOptionsByRunningGradle($makefile);
- return $COMPOPTSCACHE{$makefile};
- }
- }
- {
- #Environment variable which tells Gradle were to output the compiler options
- my $GRADLE_OUTPUT_ENV_VAR = 'TICS_OUTPUT_FILE';
- sub GetGradleOutputEnvVarName () : Public {
- return $GRADLE_OUTPUT_ENV_VAR;
- }
- sub GetCompilerOptionsByRunningGradle ($) : Private {
- my ($makefile) = @_;
- my $workdir = &TIOBEFiles::DirName($makefile);
- my $toolexe = &FindToolExe($makefile);
- my $gradleplugin = &GetTICSGradlePlugin();
- my $out = '';
- my $buildfile = &GetBuildFile($makefile);
- &TICSEnv::SaveEnv();
- &TIOBEEnv::SetEnvVar($GRADLE_OUTPUT_ENV_VAR, $buildfile);
- my $project = &TICSDatabase::GetProject();
- my $gradleoptionalparams = &GetToolCfgProp($TOOL, 'ADDITIONALARGS', $project);
- my @gradleflags = ('-Dorg.gradle.parallel=false', '-Dorg.gradle.daemon=false',
- '-Dorg.gradle.configureondemand=false', @$gradleoptionalparams);
- my $status =
- &TIOBESystem::SysQXCmd(
- workdir=>$workdir,
- cmd=>[$toolexe, @gradleflags, '-I', $gradleplugin, ':tics'],
- output=>\$out,
- );
- &TICSEnv::ResetEnv();
- &TIOBEFiles::WriteFileContent("$buildfile.log", [$out]);
- if ($status || !-e $buildfile) {
- my $err = &GetFirstGradleError($out);
- &TICSSystem::Assert(!defined $err || $err eq '', 5073, $TOOL, $err);
- &TICSSystem::Die(5073, $TOOL, 'An unknown error occurred');
- }
- return &ParseBuildFile($buildfile, $makefile);
- }
- }
- sub FindToolExe ($) : Private {
- my ($makefile) = @_;
- my $makedir = &TIOBEFiles::DirName($makefile);
- my $toolexe = &TIOBEOS::IsWin32() ? "$TOOL.bat" : $TOOL;
- foreach my $dir (&TIOBEFiles::DirPrefixList($makedir)) {
- my $toolpath = &TIOBEFiles::SimpleCatFile($dir, $toolexe);
- return $toolpath if -e $toolpath;
- }
- &TICSSystem::Die(5000, "No installation of \'$TOOL\' found.");
- }
- {
- my $GRADLE_PLUGIN_FILE = 'TICSGradlePlugin.gradle';
- sub GetTICSGradlePlugin () : Private {
- my $gradleplugin = &TICSConfig::GetCfgFile($GRADLE_PLUGIN_FILE);
- return &TIOBEFiles::CanonicalPath($gradleplugin) if -f $gradleplugin;
- # PR19320: copy the bound file to the tmpdir and use it from there
- my $boundfile = &TIOBEPerl::ExtractBoundFile($GRADLE_PLUGIN_FILE, __PACKAGE__);
- $gradleplugin = &TICSConfig::GetTmpPath($GRADLE_PLUGIN_FILE);
- &TIOBEFiles::Copy($boundfile, $gradleplugin) if !-f $gradleplugin;
- return &TIOBEFiles::CanonicalPath($gradleplugin);
- }
- }
- my $MAX_FILENAME_LENGTH = 150;
- sub GetBuildFile ($) : Private {
- my ($makefile) = @_;
- $makefile =~ tr{\\/:}{-};
- my $buildfile = "$makefile.json";
- #Restrict length filename to prevent assertion failure when deleting TMPDIR
- my $striplength = length($buildfile) - $MAX_FILENAME_LENGTH;
- $buildfile = substr($buildfile, $striplength) if $striplength > 0;
- return &TICSConfig::GetTmpPath($buildfile);
- }
- #Error is the first line that starts with a > after the line 'What went wrong:'
- sub GetFirstGradleError ($) : Private {
- my ($gradleoutput) = @_;
- return if !$gradleoutput;
- my @lines =
- map(&TIOBEString::Trim($_), &TIOBEString::SplitLines($gradleoutput));
- my $error = '';
- my $seenerrormarker = 0;
- foreach my $line (@lines) {
- if ($line =~ m/What went wrong:/) {
- $seenerrormarker = 1;
- } elsif ($seenerrormarker && $line =~ m/^>\s*(.*)/) {
- $error = $1;
- last;
- }
- }
- return $error;
- }
- sub ParseBuildFile ($$) : Private {
- my ($buildfile, $makefile) = @_;
- my $configurationsperproject = &TIOBEJson::DecodeJsonFromFile($buildfile);
- my %compoptsperfile = ();
- foreach my $project (keys %{$configurationsperproject}) {
- my %projectconfigurations = %{$configurationsperproject->{$project}};
- foreach my $conf (keys %projectconfigurations) {
- my $configuration = $projectconfigurations{$conf};
- if (&IsDeadCode($configuration)) {
- #Configurations that have not been built are dead code
- &TICSSystem::Warn(1120, $conf, $project, $makefile);
- next;
- }
- my $compileropts = &GetCompilerOptionsForConfiguration($configuration);
- foreach my $srcfile (@{$configuration->{'sourceFiles'}}) {
- my $filename = &TICSFiles::CanonicalPath($srcfile);
- $compoptsperfile{$filename} //= $compileropts;
- }
- }
- }
- return \%compoptsperfile;
- }
- sub IsDeadCode ($) : Private {
- my ($configuration) = @_;
- my $classesdir = $configuration->{'classesDir'};
- return !-e &TIOBEFiles::CanonicalPath($classesdir) if defined $classesdir;
- my $classesdirs = $configuration->{'classesDirs'};
- return all { !-e &TIOBEFiles::CanonicalPath($_) } @$classesdirs;
- }
- sub GetCompilerOptionsForConfiguration (\%) : Private {
- my ($configuration) = @_;
- &AddClassesDirToClasspath($configuration);
- &AddSingularClassesDir($configuration);
- my %mapping = (
- 'bootstrapClasspath' => '-bootclasspath',
- 'classesDir' => '-d',
- 'sourceCompatibility' => '-source',
- 'targetCompatibility' => '-target',
- 'sourcePaths' => '-sourcepath',
- 'classpath' => '-classpath',
- 'compilerPath' => '-compilerpath',
- );
- my @compopts = ();
- foreach my $key (keys %mapping) {
- my $value = $configuration->{$key};
- next if !$value || ref $value eq 'ARRAY' && !@$value;
- $value = &JoinPaths($value) if ref $value eq 'ARRAY';
- my $name = $mapping{$key};
- push(@compopts, [$name, $value]);
- }
- #Add additional compiler arguments
- push(@compopts, map([$_], @{$configuration->{'compilerArgs'} // []}));
- return \@compopts;
- }
- #Adds classesDir to front of classpath
- sub AddClassesDirToClasspath (\%) : Private {
- my ($configuration) = @_;
- my $classesdirs = $configuration->{'classesDirs'} // [$configuration->{'classesDir'}];
- return if !$classesdirs;
- $configuration->{'classpath'} //= [];
- unshift(@{$configuration->{'classpath'}}, @$classesdirs);
- }
- #Adds classesDir property with a single value.
- sub AddSingularClassesDir(\%) : Private {
- my ($configuration) = @_;
- my $classesdirs = $configuration->{'classesDirs'};
- return if !$classesdirs;
- return if $configuration->{'classesDir'}; # already set
- $configuration->{'classesDir'} = @$classesdirs[0];
- }
- sub JoinPaths (\@) : Private {
- my ($paths) = @_;
- my $sep = &TIOBEOS::IsWin32() ? ';' : ':';
- return join($sep, uniq(@$paths));
- }
- sub GetBuildTargets ($) : Protected {
- my ($inputfile) = @_;
- return;
- }
- sub GetToolCfgProp ($$$) : Private {
- my ($tool, $prop, $project) = @_;
- return &TICSServer::GetProjectOrGlobalPropPath($project, 'TOOLS', $tool, $prop) // [];
- }
- 1;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement