【问题标题】:Handling file names with space with GNU Make使用 GNU Make 处理带空格的文件名
【发布时间】:2016-06-07 15:42:58
【问题描述】:

我正在使用 GNU Make (v3.80),我必须处理带有空格的文件名。 (对于文件名,我无能为力本身。)我的makefile 包括"normal" rulesstatic pattern rules。我如何处理这些文件 更改太多我的makefile

我已阅读并研究过以前的相关问题(herehereherethere),但没有一个处理静态模式规则。

【问题讨论】:

    标签: makefile pattern-matching whitespace gnu-make space


    【解决方案1】:

    一种解决方案将"question mark" trick by Mecklenburg 与shell 命令(find 和sed)相结合,并且 使用自动变量$< 而是使用$*

    假设您要将在data 目录中找到的任何文件复制到目标目录中,以下是规则(包括静态模式规则)。以下是完整的makefile,以下是有趣的部分:

    EXEDIR     = bin/vbcc-classic/AmiModRadio/
    DATADIR    = $(EXEDIR)data/
    DATA       = $(addprefix $(DATADIR),    $(shell find data/   -mindepth 1 -maxdepth 1 -printf "%f\n"         | sed 's/ /?/g'))
    

    在上面,最后一个变量声明DATA 包含data/ 中可用的文件名集,文件名中的任何空格都替换为?。每个文件名都以目标目录DATADIR为前缀,并以空格分隔。

    space :=
    space +=
    replaceQuestionBySpace = $(subst ?,$(space),$1)
    replaceSpaceByQuestion = $(subst $(space),?,$1)
    

    在上面,在梅克伦堡之后,定义了两个函数来用问号替换空格,反之亦然。

    $(DATA) : $(DATADIR)% : $(wildcard data/%)
        cp -f -R "$(call replaceQuestionBySpace,data/$*)" "$(call replaceQuestionBySpace,$@)"
    

    以上是重要的静态模式规则:规则$(wildcard data/%) 的先决条件确保Make 不会在每次调用时复制data 中的文件,但前提是它们已从$(DATADIR) 更改或消失。

    $(wildcard data/%) 有效,因为%$(DATA) : $(DATADIR)% 构建的词干所取代,并且因为$(DATA) 包含一组不带空格(但问号)并以$(DATADIR) 为前缀的文件名。

    在配方中,问号被替换为空格以恢复原始文件名。不能使用$<,因为它会匹配$(wildcard data/%),这将导致一个空字符串。但是,因为目标包含$(DATADIR)和文件名,所以可以使用$*(文件名),代价是在前面添加data/


    例如完整的makefile

    #
    #    AmiModRadio
    #    All of Aminet modules at your fingertips
    #
    #
    #
    #    Copyright 2015, 2016 Tygre <tygre@chingu.asia>
    #
    #    This file is part of AmiModRadio.
    #
    #    AmiModRadio is free software: you can redistribute it and/or modify
    #    it under the terms of the GNU General Public License as published by
    #    the Free Software Foundation, either version 3 of the License, or
    #    (at your option) any later version.
    #
    #    AmiModRadio is distributed in the hope fthat it will be useful,
    #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    #    GNU General Public License for more details.
    #
    #    You should have received a copy of the GNU General Public License
    #    along with AmiModRadio. If not, see <http://www.gnu.org/licenses/>.
    #
    #
    #
    #    Entirely developed on an Amiga!
    #    (Except for source code versioning...)
    #    tygre@chingu.asia
    #
    
    # Main paths
    EXEDIR     = bin/vbcc-classic/debug/
    OBJECTSDIR = o/vbcc-classic/debug/
    
    # Main paths for release ONLY
    ifeq "$(strip $(filter dist, $(MAKECMDGOALS)))" "dist"
    EXEDIR     = bin/vbcc-classic/AmiModRadio/
    OBJECTSDIR = o/vbcc-classic/release/
    endif
    
    # Secondary paths
    EXE        = $(EXEDIR)AmiModRadio
    DATADIR    = $(EXEDIR)data/
    ICONSDIR   = $(EXEDIR)icons/
    IMAGESDIR  = $(EXEDIR)images/
    MODULESDIR = $(EXEDIR)modules/
    
    # (Re)Source files
    SOURCES    = $(wildcard *.c)
    OBJECTS    = $(addprefix $(OBJECTSDIR), $(SOURCES:.c=.o))
    DATA       = $(addprefix $(DATADIR),    $(shell find data/   -mindepth 1 -maxdepth 1 -printf "%f\n"         | sed 's/ /?/g'))
    ICONS      = $(addprefix $(ICONSDIR),   $(shell find icons/  -mindepth 1 -maxdepth 1 -printf "%f\n"         | sed 's/ /?/g'))
    IMAGES     = $(addprefix $(IMAGESDIR),  $(shell find images/ -mindepth 1 -maxdepth 1 -printf "%f\n" -type d | sed 's/ /?/g'))
    
    # compiler and linker
    CC         = vbcc:bin/vc
    LD         = vbcc:bin/vc
    
    
    
    # Because Make does not support spaces properly...
    space :=
    space +=
    replaceQuestionBySpace = $(subst ?,$(space),$1)
    replaceSpaceByQuestion = $(subst $(space),?,$1)
    
    
    
    # ----------------------------------------
    
    # target 'all' (default target, for debug)
    all :  CFLAGS += -DFORTIFY
    all :  $(EXEDIR)\
           $(OBJECTSDIR)\
           $(EXE)\
           data\
           images
    
    # target 'dist' for release
    dist : mostlyclean\
           $(EXEDIR)\
           $(OBJECTSDIR)\
           $(EXE)\
           data\
           icons\
           images\
           modules\
           $(EXEDIR:/=).lha
    
    # target 'mostlyclean'
    mostlyclean :
        -rm $(EXE)
        -rm $(OBJECTSDIR)*
    
    # target 'clean'
    clean : mostlyclean
        -rm $(DATADIR)*
        -rm $(ICONSDIR)*
        -rm $(IMAGESDIR)*
        -rm $(MODULESDIR)*
    
    # ----------------------------------------
    
    
    
    # Directories
    $(EXEDIR) :
        mkdir "$@"
    
    $(OBJECTSDIR) :
        mkdir "$@"
    
    
    
    # Objects and executable
    $(OBJECTS) : $(OBJECTSDIR)%.o : %.c
        $(CC) $(shell vbccprefs) $(CFLAGS) -c $< -o $@
    
    $(EXE) : $(OBJECTS)
        $(LD) $(shell vbccprefs) -o $(EXE) $(OBJECTS)
    
    
    
    # Data
    data : $(DATADIR)\
           $(DATA)\
    
    $(DATADIR) :
        mkdir "$@"
    
    $(DATA) : $(DATADIR)% : $(wildcard data/%)
        cp -f -R "$(call replaceQuestionBySpace,data/$*)" "$(call replaceQuestionBySpace,$@)"
    
    
    
    # Icons
    icons : $(ICONSDIR)\
            $(ICONS)\
            $(EXE).info\
            $(EXEDIR:/=).info
    
    $(ICONSDIR) :
        mkdir "$@"
    
    $(ICONS) : $(ICONSDIR)% : $(wildcard icons/%)
        cp -f -R "$(call replaceQuestionBySpace,icons/$*)" "$(call replaceQuestionBySpace,$@)"
    
    $(EXE).info :
        cp -f -R "$(ICONSDIR)AmiModRadio2.tool.info" "$@"
    
    $(EXEDIR:/=).info :
        cp -f -R "$(ICONSDIR)AmiModRadio3.drawer.info" "$@"
    
    
    
    # Images
    images : $(IMAGESDIR)\
             $(IMAGES)\
    
    $(IMAGESDIR) :
        mkdir "$@"
    
    $(IMAGES) : $(IMAGESDIR)% : $(wildcard images/%)
        cp -f -R "$(call replaceQuestionBySpace,images/$*)" "$(call replaceQuestionBySpace,$@)"
    
    
    
    # Modules
    modules : $(MODULESDIR)
    
    $(MODULESDIR) :
        mkdir "$@"
    
    
    
    # LHA archive of 'dist'
    $(EXEDIR:/=).lha : PARENTDIR = $(dir $(patsubst %/,%,$(EXEDIR)))
    $(EXEDIR:/=).lha : EXENAME   = $(notdir $(patsubst %/,%,$(EXEDIR)))
    $(EXEDIR:/=).lha :
        rm -f          RAM:$(EXENAME).lha
        /C/LHA -r -e a RAM:$(EXENAME).lha $(PARENTDIR) $(EXENAME).info $(EXENAME)/*
    

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多