1 package CMakeWorkspaceCreator
;
3 # ************************************************************
4 # Description : A CMake Workspace creator
5 # Author : Chad Elliott
6 # Create Date : 10/10/2022
7 # ************************************************************
9 # ************************************************************
11 # ************************************************************
16 use CMakeProjectCreator
;
20 @ISA = qw(WorkspaceCreator);
22 # ************************************************************
24 # ************************************************************
26 my $version = '3.12.0';
28 # ************************************************************
30 # ************************************************************
32 sub workspace_per_project
{
37 sub workspace_file_name
{
38 return 'CMakeLists.txt';
43 my $crlf = $self->crlf();
45 $self->print_workspace_comment($fh,
46 '# CMake Workspace', $crlf,
48 '# This file was generated by MPC.', $crlf,
50 '# MPC Command:', $crlf,
51 '# ', $self->create_command_line_string($0, @ARGV), $crlf, $crlf);
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
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);
76 ## Go up one directory. If we were already at the top directory,
78 my $next = $self->mpc_dirname($dir);
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), ")";
117 my($self, $fh, $creator) = @_;
119 my $errorString = '';
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.
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
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);
146 $out_of_tree{$dir} = [$entry];
152 ## Create the basis of a project so that we can add our add_subdirectory()
154 my $crlf = $self->crlf();
155 my $ws = TemplateParser
::actual_normalize
(undef, $self->get_workspace_name());
156 $self->write_ws_top($fh, $ws);
160 foreach my $dir (@project_dirs) {
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}) {
175 $self->write_include_ws($out_of_tree{$dir});
177 print $fh "add_subdirectory($dir$bin_dir)$crlf";
181 foreach my $entry (@projects) {
182 my $dir = $self->mpc_dirname($entry);
188 print $fh "include($entry)$crlf";
192 return $status, $errorString;