我有一个(遗留的)bash 脚本,它解析源文件的目录列表并将它们回显到 makefile 中,以使用gcc -MM
创建实际的 makerules。脚本工作得很好,问题是在生成的 makefile 上运行make
会导致 makerules 中的路径格式不一致 - 虽然大多数 makerules 都有混合样式路径(没关系),但有些有 cygwin 样式路径(不行)。这并没有发生在一个非常古老的(~2002年版本)的cygwin上。
这是脚本:
#!/bin/bash
fn_source=SourceFileList
fn_depmake=depMakefile
fn_orgMake=Makefile
fn_depIncl=Depend.incl
fn_optIncl=OptimizationCflags.incl
#
# create a Makefile to determine the dependencies
echo -n create dep-makefile ...
#
# generate include for Optimization-File
#
echo > $fn_depIncl
echo include $fn_optIncl >> $fn_depIncl
echo >> $fn_depIncl
#
touch $fn_optIncl
#
echo > $fn_depmake
# CFLAGS options from Makefile
grep "^CFLAGS[ =]" $fn_orgMake | grep $BUILD_SPEC >> $fn_depmake
grep "^CFLAGS_AS[ =]" $fn_orgMake | grep $BUILD_SPEC >> $fn_depmake
grep "^CFLAGS_GCC[ =]" $fn_orgMake | grep $BUILD_SPEC >> $fn_depmake
echo -n generate depMakefile ...
echo >> $fn_depmake
# the default rule
echo all: >> $fn_depmake
FileList=`cat $fn_source`
incPath=""
rawIncPath=""
for fn in $FileList; do
incPath=$incPath" -I"${fn%/*}
rawIncPath=$rawIncPath" "${fn%/*}
done
# filter out redundant paths
echo $incPath |
sed -n -e 's/ /
/gp' |
sort -u > _tmp
incPath=`cat _tmp`
# filter out redundant paths
echo $rawIncPath |
sed -n -e 's/ /
/gp' |
sort -u > _tmp
rawIncPath=`cat _tmp`
#
# create file with include paths
#
echo LibIncludes=$incPath > LibIncludes
#
# put all source files with the same path in one gcc command
#
for path in $rawIncPath; do
sourceFiles=`grep $path/ $fn_source`
echo " "echo do $path >> $fn_depmake
echo " "gcc -MM '$(CFLAGS_GCC)' -I$path $sourceFiles >> _tmp >> $fn_depmake
done
# start the Makefile
echo start Makefile ...
rm _tmp; touch _tmp
make -s -f $fn_depmake
# add ./obj/xxxxx*.o to the make-rules
sed -e 's/(^[a-zA-Z])/./obj/1/' < _tmp > _tmp1
# add command to the make-rules
sed -e '/\/!a
$(CC) $($(*F)CFLAGS) -I$(<D) $(CFLAGS) -c $< -o $@' < _tmp1 >> $fn_depIncl
# workaround for gcc generating cygdrive paths for some paths only
sed -i 's#/cygdrive/d#d:#' $fn_depIncl
rm _tmp _tmp1
rm $fn_depmake
echo done.
如您所见,我目前正在使用一种解决方法,使用sed
将这些路径转换为混合样式的路径,但我想知道为什么会发生这种情况?
规则"出错"的示例:
some.o: d:/some/path/A/some.cpp
d:/some/path/A/some.h
/cygdrive/d/some/path/B/subpathA/anotherheader.h
/cygdrive/d/some/path/B/subpathA/yetanotherheader.h
D:/some/path/B/subpathB/header.h
关于这一点的主要问题是生成的makefile被馈送到Windows本机make.exe,它不知道/cygdrive/d/path
应该是什么。
我查看了每个步骤后的路径,它们都是混合样式,直到执行make -s -f $fn_depmake
。这意味着,偶尔转换为cygwin样式路径是通过生成的makefile中的gcc -MM
命令完成的。
它始终是转换为/cygdrive/d/pathA/somefile.cpp
样式路径的相同目录列表。路径没有什么异常,没有空格,名称上只有 a-z/A-Z,路径长度很短,最长路径是 76 个字符,包括文件名,基本路径是 34 个字符长。
如何强制 gcc 生成混合样式路径?
我可以在我的项目上看到同样的问题。我在Windows上使用Cygwin的gmake.exe
。
gcc -MM
的一次调用会同时输出Windows风格的路径(C:/project/file.h
)和Cygwin风格的路径(/cygdrive/c/project/file.h
)。
我还不知道如何解决这个问题,但我发现了触发对 Cygwin 风格路径更改的原因。当包含使用相对路径时,会发生这种情况。因此,当一个文件包含#include "../file.h"
时,gcc -MM
的输出将包含file.h
的绝对路径,使用 Cygwin 样式的路径。