From d4736ff20e0db3ec6a1d8d8c98af8027ebbb83c3 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Thu, 17 Nov 2022 10:41:03 -0600 Subject: Handle out-of-tree directories properly by creating a workspace for each project group directory and adding the bin dir parameter to add_subdirectory(). --- modules/CMakeWorkspaceCreator.pm | 54 ++++++++++++++++++++++++++++++++++++---- modules/WorkspaceCreator.pm | 10 ++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) (limited to 'modules') diff --git a/modules/CMakeWorkspaceCreator.pm b/modules/CMakeWorkspaceCreator.pm index ceca1cbe..a3cdafea 100644 --- a/modules/CMakeWorkspaceCreator.pm +++ b/modules/CMakeWorkspaceCreator.pm @@ -48,7 +48,12 @@ sub pre_workspace { '# This file was generated by MPC.', $crlf, '#', $crlf, '# MPC Command:', $crlf, - '# ', $self->create_command_line_string($0, @ARGV), $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 @@ -59,7 +64,7 @@ sub get_top_directory { ## First, convert the path to a relative path based on the current working ## directory. my $dir = $self->path_to_relative($self->getcwd(), $path); - if ($dir =~ /^\.\.\// || !$self->path_is_relative($dir)) { + 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. @@ -83,6 +88,28 @@ sub get_top_directory { 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_single_include_ws { + my($self, $prj) = @_; + my $fh = new FileHandle(); + my $dir = $self->mpc_dirname($prj); + 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)); + print $fh "${crlf}include(", basename($prj), ")$crlf"; + close($fh); + } +} + sub write_comps { my($self, $fh, $creator) = @_; my $status = 1; @@ -100,6 +127,12 @@ sub write_comps { ## Keep track of the project existing in this directory $dirs{$dir} = 1; + ## 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 generate one here. + if ($self->out_of_tree($dir)) { + $self->write_single_include_ws($entry); + } push(@project_dirs, $dir); } } @@ -108,16 +141,27 @@ sub write_comps { ## calls below it. my $crlf = $self->crlf(); my $ws = TemplateParser::actual_normalize(undef, $self->get_workspace_name()); - print $fh "cmake_minimum_required(VERSION $version)", $crlf, - "project($ws CXX)", $crlf; + $self->write_ws_top($fh, $ws); my $first = 1; + my %bin_used; foreach my $dir (@project_dirs) { if ($first) { $first = undef; print $fh $crlf; } - print $fh "add_subdirectory($dir)$crlf"; + my $bin_dir = ''; + if ($self->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; + } + print $fh "add_subdirectory($dir$bin_dir)$crlf"; } $first = 1; diff --git a/modules/WorkspaceCreator.pm b/modules/WorkspaceCreator.pm index b6be9879..b8b993f8 100644 --- a/modules/WorkspaceCreator.pm +++ b/modules/WorkspaceCreator.pm @@ -1343,8 +1343,14 @@ sub generate_hierarchy { my %projinfo = %{$originfo}; foreach my $prj (@projects) { - my($top, $rest) = $self->topname($prj); - + ## If the project path starts with ./ the code assumed that the top was + ## the current directory and would end up not creating the workspace as + ## it should have been. We will clean up the project directory and pass + ## that to topname() instead. + my $clean = $prj; + $clean =~ s/^\.[\/]+//; + + my($top, $rest) = $self->topname($clean); if (!defined $current) { $current = $top; push(@saved, $rest); -- cgit v1.2.1