summaryrefslogtreecommitdiff
path: root/modules/CMakeWorkspaceCreator.pm
blob: 4f173ca4cddf4e296f000a77bf164f756ef0af9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package CMakeWorkspaceCreator;

# ************************************************************
# Description   : A CMake Workspace creator
# Author        : Chad Elliott
# Create Date   : 10/10/2022
# ************************************************************

# ************************************************************
# Pragmas
# ************************************************************

use strict;
use File::Basename;

use CMakeProjectCreator;
use WorkspaceCreator;

use vars qw(@ISA);
@ISA = qw(WorkspaceCreator);

# ************************************************************
# Subroutine Section
# ************************************************************

sub pre_workspace {
  my($self, $fh) = @_;
  my $crlf = $self->crlf();

  $self->print_workspace_comment($fh,
           '# CMake Workspace', $crlf,
           '#', $crlf,
           '# This file was generated by MPC.', $crlf,
           '#', $crlf,
           '# MPC Command:', $crlf,
           '# ', $self->create_command_line_string($0, @ARGV), $crlf);
}

sub write_and_compare_file {
  my($self, $outdir, $oname, $func, @params) = @_;
  my $status = 1;
  my $errorString = '';
  my @project_dirs;

  ## Set the output directory if one wasn't provided
  $outdir = $self->get_outdir() if (!defined $outdir);

  ## Remove the existing workspace, if one exists.
  my $wsname = "$outdir/CMakeLists.txt";
  unlink($wsname);

  ## Rename the first (and hopefully the only) project in the directory to what
  ## CMake expects.
  my %dirs;
  foreach my $entry ($self->sort_dependencies($self->get_projects(), 0)) {
    my $dir = dirname($entry);
    if (!exists $dirs{$dir}) {
      ## Keep track of the project existing in this directory
      $dirs{$dir} = 1;

      ## Rename the project file to CMakeLists.txt and if it fails, we need to
      ## propagate that back to the caller.
      if (rename($entry, "$dir/CMakeLists.txt") == 0) {
        $status = 0;
        $errorString = "Unable to rename $entry";
        last;
      }

      push(@project_dirs, $dir);
    }
    else {
      $self->warning("Multiple projects in the same workspace are not " .
                     "supported: $dir");
    }
  }

  if ($status) {
    ## See if a project file exists in this directory.  Since the workspace and
    ## project files would have the same name, we need to read the contents of
    ## the file and then insert add_subdirectory() calls to it.
    my @lines;
    my $insert;
    my $version = '3.12.0';
    my $fh = new FileHandle();
    if (open($fh, $wsname)) {
      for(my $i = 0; <$fh>; $i++) {
        push(@lines, $_);
        if (/cmake_minimum_required\(VERSION ([^\)]+)\)/) {
          $insert = $i;
          $version = $1;
        }
      }
      close($fh);
    }

    if ($#lines == -1) {
      ## If a project doesn't exist, create the basis of a project so that we
      ## can add our add_subdirectory() calls below it.
      push(@lines, "cmake_minimum_required(VERSION $version)" . $self->crlf(),
                   "project(workspace)" . $self->crlf());
      $insert = $#lines;
    }

    ## Create the workspace here.
    if (open($fh, ">$wsname")) {
      ## Write out the pre-workspace information
      $self->pre_workspace($fh);

      for(my $i = 0; $i <= $#lines; $i++) {
        print $fh "$lines[$i]";
        if ($i == $insert) {
          my $crlf = $self->crlf();
          print $fh $crlf;
          foreach my $dir (@project_dirs) {
            if ($dir ne $outdir) {
              print $fh "add_subdirectory($dir)$crlf";
            }
          }
        }
      }
      close($fh);
    }
    else {
      $status = 0;
      $errorString = "Unable to open $wsname for output.";
    }
  }

  return $status, $errorString;
}

1;