Merge pull request #228 from DOCGroup/jwillemsen-patch-1
[MPC.git] / modules / CMakeWorkspaceCreator.pm
blobf5d9e63a1960d282c105559215c98294b11cbdbc
1 package CMakeWorkspaceCreator;
3 # ************************************************************
4 # Description : A CMake Workspace creator
5 # Author : Chad Elliott
6 # Create Date : 10/10/2022
7 # ************************************************************
9 # ************************************************************
10 # Pragmas
11 # ************************************************************
13 use strict;
14 use File::Basename;
16 use CMakeProjectCreator;
17 use WorkspaceCreator;
19 use vars qw(@ISA);
20 @ISA = qw(WorkspaceCreator);
22 # ************************************************************
23 # Data Section
24 # ************************************************************
26 my $version = '3.12.0';
28 # ************************************************************
29 # Subroutine Section
30 # ************************************************************
32 sub workspace_per_project {
33 #my $self = shift;
34 return 1;
37 sub workspace_file_name {
38 return 'CMakeLists.txt';
41 sub pre_workspace {
42 my($self, $fh) = @_;
43 my $crlf = $self->crlf();
45 $self->print_workspace_comment($fh,
46 '# CMake Workspace', $crlf,
47 '#', $crlf,
48 '# This file was generated by MPC.', $crlf,
49 '#', $crlf,
50 '# MPC Command:', $crlf,
51 '# ', $self->create_command_line_string($0, @ARGV), $crlf, $crlf);
54 sub out_of_tree {
55 my($self, $dir) = @_;
56 return ($dir =~ /^\.\.\// || !$self->path_is_relative($dir));
59 ## Get the top level directory in the path. If the path does not contain
60 ## a directory, the path will be returned unmodified.
61 sub get_top_directory {
62 my($self, $path) = @_;
64 ## First, convert the path to a relative path based on the current working
65 ## directory.
66 my $dir = $self->path_to_relative($self->getcwd(), $path);
67 if ($self->out_of_tree($dir)) {
68 ## If the directory is above the current directory or not relative to
69 ## the current working directory, we need to give the directory portion
70 ## back and call it a day.
71 return $self->mpc_dirname($dir);
73 else {
74 my $done = 0;
75 do {
76 ## Go up one directory. If we were already at the top directory,
77 ## we're finished.
78 my $next = $self->mpc_dirname($dir);
79 if ($next eq '.') {
80 $done = 1;
82 else {
83 $dir = $next;
85 } while(!$done);
88 return $dir;
91 sub write_ws_top {
92 my($self, $fh, $ws) = @_;
93 my $crlf = $self->crlf();
94 print $fh "cmake_minimum_required(VERSION $version)", $crlf,
95 "project($ws CXX)", $crlf;
98 sub write_include_ws {
99 my($self, $prjs) = @_;
100 my $fh = new FileHandle();
101 my $dir = $self->mpc_dirname($$prjs[0]);
102 my $file = $dir . '/' . $self->workspace_file_name();
104 if (open($fh, ">$file")) {
105 my $crlf = $self->crlf();
106 $self->pre_workspace($fh);
107 $self->write_ws_top($fh, basename($dir));
108 foreach my $prj (@$prjs) {
109 print $fh "${crlf}include(", basename($prj), ")";
111 print $fh $crlf;
112 close($fh);
116 sub write_comps {
117 my($self, $fh, $creator) = @_;
118 my $status = 1;
119 my $errorString = '';
120 my @project_dirs;
121 my @projects = $self->sort_dependencies($self->get_projects(), 0);
123 ## Build a list of top level directories. We only want to go down one
124 ## directory. The workspace in that directory will handle going to
125 ## other subdirectories.
126 my %dirs;
127 my %out_of_tree;
128 foreach my $entry (@projects) {
129 my $dir = $self->get_top_directory($entry);
130 if ($dir ne $entry) {
131 if (!exists $dirs{$dir}) {
132 ## Keep track of the project existing in this directory
133 $dirs{$dir} = 1;
135 push(@project_dirs, $dir);
138 ## If this directory is out-of-tree, it will not contain a top-level
139 ## workspace (due to the way that workspace-per-directory works). We
140 ## need to keep track of it here.
141 if ($self->out_of_tree($dir)) {
142 if (exists $out_of_tree{$dir}) {
143 push(@{$out_of_tree{$dir}}, $entry);
145 else {
146 $out_of_tree{$dir} = [$entry];
152 ## Create the basis of a project so that we can add our add_subdirectory()
153 ## calls below it.
154 my $crlf = $self->crlf();
155 my $ws = TemplateParser::actual_normalize(undef, $self->get_workspace_name());
156 $self->write_ws_top($fh, $ws);
158 my $first = 1;
159 my %bin_used;
160 foreach my $dir (@project_dirs) {
161 if ($first) {
162 $first = undef;
163 print $fh $crlf;
165 my $bin_dir = '';
166 if (exists $out_of_tree{$dir}) {
167 ## Because this directory is out-of-tree, CMake requires a binary
168 ## directory to be passed to add_subdirectory().
169 my $bin = basename($dir);
170 while(exists $bin_used{$bin}) {
171 $bin .= '_';
173 $bin_dir = " $bin";
174 $bin_used{$bin} = 1;
175 $self->write_include_ws($out_of_tree{$dir});
177 print $fh "add_subdirectory($dir$bin_dir)$crlf";
180 $first = 1;
181 foreach my $entry (@projects) {
182 my $dir = $self->mpc_dirname($entry);
183 if ($dir eq '.') {
184 if ($first) {
185 $first = undef;
186 print $fh $crlf;
188 print $fh "include($entry)$crlf";
192 return $status, $errorString;