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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
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);
# ************************************************************
# Data Section
# ************************************************************
my $version = '3.12.0';
# ************************************************************
# Subroutine Section
# ************************************************************
sub workspace_per_project {
#my $self = shift;
return 1;
}
sub workspace_file_name {
return 'CMakeLists.txt';
}
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, $crlf);
}
sub out_of_tree {
my($self, $dir) = @_;
return ($dir =~ /^\.\.\// || !$self->path_is_relative($dir));
}
## Get the top level directory in the path. If the path does not contain
## a directory, the path will be returned unmodified.
sub get_top_directory {
my($self, $path) = @_;
## First, convert the path to a relative path based on the current working
## directory.
my $dir = $self->path_to_relative($self->getcwd(), $path);
if ($self->out_of_tree($dir)) {
## If the directory is above the current directory or not relative to
## the current working directory, we need to give the directory portion
## back and call it a day.
return $self->mpc_dirname($dir);
}
else {
my $done = 0;
do {
## Go up one directory. If we were already at the top directory,
## we're finished.
my $next = $self->mpc_dirname($dir);
if ($next eq '.') {
$done = 1;
}
else {
$dir = $next;
}
} while(!$done);
}
return $dir;
}
sub write_ws_top {
my($self, $fh, $ws) = @_;
my $crlf = $self->crlf();
print $fh "cmake_minimum_required(VERSION $version)", $crlf,
"project($ws CXX)", $crlf;
}
sub write_include_ws {
my($self, $prjs) = @_;
my $fh = new FileHandle();
my $dir = $self->mpc_dirname($$prjs[0]);
my $file = $dir . '/' . $self->workspace_file_name();
if (open($fh, ">$file")) {
my $crlf = $self->crlf();
$self->pre_workspace($fh);
$self->write_ws_top($fh, basename($dir));
foreach my $prj (@$prjs) {
print $fh "${crlf}include(", basename($prj), ")";
}
print $fh $crlf;
close($fh);
}
}
sub write_comps {
my($self, $fh, $creator) = @_;
my $status = 1;
my $errorString = '';
my @project_dirs;
my @projects = $self->sort_dependencies($self->get_projects(), 0);
## Build a list of top level directories. We only want to go down one
## directory. The workspace in that directory will handle going to
## other subdirectories.
my %dirs;
my %out_of_tree;
foreach my $entry (@projects) {
my $dir = $self->get_top_directory($entry);
if ($dir ne $entry) {
if (!exists $dirs{$dir}) {
## Keep track of the project existing in this directory
$dirs{$dir} = 1;
push(@project_dirs, $dir);
}
## If this directory is out-of-tree, it will not contain a top-level
## workspace (due to the way that workspace-per-directory works). We
## need to keep track of it here.
if ($self->out_of_tree($dir)) {
if (exists $out_of_tree{$dir}) {
push(@{$out_of_tree{$dir}}, $entry);
}
else {
$out_of_tree{$dir} = [$entry];
}
}
}
}
## Create the basis of a project so that we can add our add_subdirectory()
## calls below it.
my $crlf = $self->crlf();
my $ws = TemplateParser::actual_normalize(undef, $self->get_workspace_name());
$self->write_ws_top($fh, $ws);
my $first = 1;
my %bin_used;
foreach my $dir (@project_dirs) {
if ($first) {
$first = undef;
print $fh $crlf;
}
my $bin_dir = '';
if (exists $out_of_tree{$dir}) {
## Because this directory is out-of-tree, CMake requires a binary
## directory to be passed to add_subdirectory().
my $bin = basename($dir);
while(exists $bin_used{$bin}) {
$bin .= '_';
}
$bin_dir = " $bin";
$bin_used{$bin} = 1;
$self->write_include_ws($out_of_tree{$dir});
}
print $fh "add_subdirectory($dir$bin_dir)$crlf";
}
$first = 1;
foreach my $entry (@projects) {
my $dir = $self->mpc_dirname($entry);
if ($dir eq '.') {
if ($first) {
$first = undef;
print $fh $crlf;
}
print $fh "include($entry)$crlf";
}
}
return $status, $errorString;
}
1;
|