GNU makefile将“覆盖一个源列表”覆盖到“另一源列表”的上方

时间:2018-08-06 20:13:00

标签: makefile gnu-make

我有两个源目录...

一个目录具有自动生成的代码。 另一个目录的代码采用自动生成的代码,并向代码添加自定义...

我想自动合并这两个源目录,以便每个文件的源路径的basename替换自动生成的源目录中的`basename。示例:

SRC_AUTO := $(wildcard path1/path2/src_auto/*.cpp)
SRC_WORK := $(wildcard path3/path4/src_work/*.cpp)

# How to achieve this with GNU Make without going out to $shell or perl...
SRC_MERGED := overlay_basename($SRC_WORK, $SRC_AUTO)

示例:

SRC_AUTO := \
    ./path1/path2/src_auto/pathz/file1.cpp \
    ./path1/path2/src_auto/pathx/pathy/file2.cpp \
    ./path1/path2/src_auto/file3.cpp

SRC_WORK := \
    ./path3/path4/src_work/file1.cpp \
    ./path3/path4/src_work/file3.cpp

#This is what I need to generate automatically
SRC_MERGED := \
   path1/path2/src_auto/pathx/pathy/file2.cpp \
   path3/path4/src_work/file1.cpp \
   path3/path4/src_work/file3.cpp

除了有更多文件外... SRC_WORK覆盖从文件路径的基本名称键入的SRC_AUTO。

这是我基本上想从GNU用perl伪代码生成的内容:

@SRC_AUTO = ( ...list of automatically generated files.. );
@SRC_WORK = ( ...list of customized files copied from auto directory );

%unique = ();
foreach $file (@SRC_WORK) {
    $base = basename($file);
    $unique{$base} = $file;
}

foreach $file (@SRC_AUTO) {
    $base = basename($file);
    if (!defined($unique{$base}) {
         $unique{$base} = $file;            
    }
}
@merged_list = ();
foreach $key (keys %unique) {
    $file = $unique{$key};
    push(@merged_list, $file);
}
@sorted_merged_list = sort(@merged_list);

return @sorted_merged_list;

更新,经过一些改进,我现在有了以下perl脚本:(现在,如果您仅能使用单个内置函数从gnu make中自动执行此操作,而不会遇到调用脚本的脚本不稳定的脚本环境。 ):

#!/usr/bin/perl

# Automatically Generated Source Code
$dir_auto   = "../src_auto";

# Overlayed Source Code
$dir_work   = "../src_work";

#Merge File Output
$merge_list = "source.txt";

use File::Find;

sub OverlaySource($$) 
{
    my $dir_auto = shift;
    my $dir_work = shift;

    my %unique = ();

    my @cpp_work;
    find( sub {
        my $file = $_;
        if ($file =~ /\.cpp$/) {
            $path = $dir_work . "/" . $file;
            $unique{$file} = $path;
        }
    }, $dir_work);

    my @cpp_auto;
    find( sub {
        my $file = $_;
        return if (defined($unique{$file}));
        if ($file =~ /\.cpp$/) {
            $path = $dir_auto . "/" . $file;
            $unique{$file} = $path;         
        }
    }, $dir_auto);

    my @tmp = ();
    foreach $key (keys %unique) {
        $file = $unique{$key};
        push(@tmp, $file);
    }

    my @cpp_files = sort @tmp;
    return @cpp_files;
}


$dir_auto = "../src_auto";
$dir_work = "../src_work";

my @cpp_files = OverlaySource($dir_auto, $dir_work);

print "Creating File: $merge_list\n";
open(F, ">${merge_list}"); 
foreach $file (@cpp_files) {
    print F "$file\n";
}
close(F);

1 个答案:

答案 0 :(得分:2)

这应该做您想要的:

SRC_MERGED := $(filter-out $(addprefix %/,$(notdir $(SRC_WORK))),$(SRC_AUTO)) $(SRC_WORK)

说明:

  1. $(notdir $(SRC_WORK))返回$(SRC_WORK)中所有单词的基本名称:file1.cpp file3.cpp
  2. $(addprefix %/,$(notdir $(SRC_WORK)))%/前缀添加到1的结果中;这是制作模式的列表(%是通配符):%/file1.cpp %/file3.cpp
  3. $(filter-out $(addprefix %/,$(notdir $(SRC_WORK))),$(SRC_AUTO))返回$(SRC_AUTO)中所有与$(addprefix %/,$(notdir $(SRC_WORK)))中的任何模式都不匹配的单词:./path1/path2/src_auto/pathx/pathy/file2.cpp
  4. $(filter-out $(addprefix %/,$(notdir $(SRC_WORK))),$(SRC_AUTO)) $(SRC_WORK)仅将$(SRC_WORK)连接到3的结果:

    ./path1/path2/src_auto/pathx/pathy/file2.cpp ./path3/path4/src_work/file1.cpp ./path3/path4/src_work/file3.cpp