为什么我的 C 预处理器忽略这些使用空格的宏?
Why is my C preprocessor ignoring these macros using spaces?
我正在尝试构建 WRF 4.2,但 运行 由于预处理器未扩展宏而出现一些错误。
本质上,WRF 是通过配置然后编译源代码的 csh 脚本构建的。该配置过程的一部分采用固定格式 Fort运行(.F 文件),t运行将它们转换为自由格式 Fort运行 文件(.f90),然后将其编译为目标文件. 运行 的命令是根据用户选择的平台和编译器配置生成的,对我来说是达尔文架构,GNU (gfortran/gcc) 编译器。我正在尝试编译 "serial" 配置。这是我关心的输出部分:
sed -e "s/^\!.*'.*//" -e "s/^ *\!.*'.*//" module_mp_fast_sbm.F > module_mp_fast_sbm.G
cpp -P -nostdinc -xassembler-with-cpp -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/inc -DEM_CORE=1 -DNMM_CORE=0 -DNMM_MAX_DIM=2600 -DDA_CORE=0 -DWRFPLUS=0 -DIWORDSIZE=4 -DDWORDSIZE=8 -DRWORDSIZE=4 -DLWORDSIZE=4 -DNONSTANDARD_SYSTEM_SUBR -DMACOS -DWRF_USE_CLM -DDM_PARALLEL -DSTUBMPI -DNETCDF -DLANDREAD_STUB=1 -DUSE_ALLOCATABLES -Dwrfmodel -DGRIB1 -DINTIO -DKEEP_INT_AROUND -DLIMIT_ARGS -DBUILD_RRTMG_FAST=0 -DBUILD_RRTMK=0 -DBUILD_SBM_FAST=1 -DSHOW_ALL_VARS_USED=0 -DCONFIG_BUF_LEN=65536 -DMAX_DOMAINS_F=21 -DMAX_HISTORY=25 -DNMM_NEST=0 -I. -traditional-cpp module_mp_fast_sbm.G > module_mp_fast_sbm.bb
/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/tools/standard.exe module_mp_fast_sbm.bb | cpp -P -nostdinc -xassembler-with-cpp -traditional-cpp > module_mp_fast_sbm.f90
rm -f module_mp_fast_sbm.G module_mp_fast_sbm.bb
time gfortran -o module_mp_fast_sbm.o -c -O2 -ftree-vectorize -funroll-loops -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -I../dyn_em -I../dyn_nmm -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/esmf_time_f90 -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/main -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/io_netcdf -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/io_int -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/frame -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/share -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/phys -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/wrftladj -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/chem -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/inc -I/usr/local/Cellar/netcdf/4.7.4/include module_mp_fast_sbm.f90
module_mp_fast_sbm.f90:6065:4:
6065 | DM_BCAST_MACRO_R16 ( FAF1 )
| 1
Error: Unclassifiable statement at (1)
0.56 real 0.52 user 0.03 sys
这里发生的事情是,在最后一步编译的 Fort运行 文件仍然有一个未替换的宏。请记住,有许多这样的 Fort运行 文件,这是唯一一个有问题的文件。
我查看了宏在 module_mp_fast_sbm.F
中定义的位置,并看到了这些定义
#define DM_BCAST_MACRO_R4(A) CALL wrf_dm_bcast_bytes(A, size(A)*R4SIZE)
#define DM_BCAST_MACRO_R8(A) CALL wrf_dm_bcast_bytes(A, size(A)*R8SIZE)
#define DM_BCAST_MACRO_R16(A) CALL wrf_dm_bcast_bytes(A, size(A)*R16SIZE)
我还注意到同一宏的其他用法已被正确替换,但那些实例并未在宏名称、括号和参数之间使用 space。这让我想知道间距是否有所作为。所以我运行做了一个实验:
test.c:
#define DM_BCAST_MACRO_R4(A) CALL wrf_dm_bcast_bytes(A, size(A)*R4SIZE)
DM_BCAST_MACRO_R4(3);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
DM_BCAST_MACRO_R4( 3);
DM_BCAST_MACRO_R4 (3);
首先我使用了 WRF 脚本中使用的命令:
cat test.c | cpp -P -nostdinc -xassembler-with-cpp -traditional-cpp > output_traditional.txt
我得到了这个输出:
CALL wrf_dm_bcast_bytes(3, size(3)*R4SIZE);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
CALL wrf_dm_bcast_bytes( 3, size( 3)*R4SIZE);
DM_BCAST_MACRO_R4 (3);
我想可能是 WRF 使用的标志导致了这个问题,所以我尝试了这个命令:
cat test.c | cpp -P > output_noflags.txt
得到这个结果:
CALL wrf_dm_bcast_bytes(3, size(3)*R4SIZE);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
CALL wrf_dm_bcast_bytes( 3, size( 3)*R4SIZE);
DM_BCAST_MACRO_R4 (3);
cpp -v
的输出
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name - -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -fno-strict-return -masm-verbose -munwind-tables -target-sdk-version=10.15.4 -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 556.6 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -I /usr/include -I/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -Wno-objc-signed-char-bool-implicit-int-conversion -Wno-extra-semi-stmt -Wno-quoted-include-in-framework-header -fdebug-compilation-dir /Users/isaacrowe/Desktop -ferror-limit 19 -fmessage-length 270 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=macosx-10.15.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -x c -
clang -cc1 version 11.0.3 (clang-1103.0.32.62) default target x86_64-apple-darwin19.5.0
ignoring nonexistent directory "/usr/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/include
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
根据我的阅读here,宏定义的左括号前不能有space,但是宏的使用可以在括号前有space。那么为什么我的预处理器没有进行替换?
使用 -traditional-cpp
时 clang 的 cpp 的这种行为一直是 reported back in 2013, with no followup to date. It seems like it's probably a bug, since gcc's preprocessor doesn't do it (example),看起来 3.2 版之前的 clang 也没有这样做。但是 -traditional-cpp
的预期语义在我所知道的任何地方都没有精确定义,而且 clang 维护者没有对错误报告做出回应,所以很难确定。也有可能他们只是不关心 -traditional-cpp
并认为它已过时。
看起来 -traditional-cpp
是 运行 cpp
独立安装时的默认设置。我不知道如何关闭它,但 -std=c90
可以。请注意 clang -E
也避免了传统模式并且似乎表现正确。
您也可以使用 gcc 的预处理器来代替 "bug"。如您所见,在您的系统上 gcc
命令实际上是 clang,但您可以从 Homebrew 安装真正的 gcc。
我正在尝试构建 WRF 4.2,但 运行 由于预处理器未扩展宏而出现一些错误。
本质上,WRF 是通过配置然后编译源代码的 csh 脚本构建的。该配置过程的一部分采用固定格式 Fort运行(.F 文件),t运行将它们转换为自由格式 Fort运行 文件(.f90),然后将其编译为目标文件. 运行 的命令是根据用户选择的平台和编译器配置生成的,对我来说是达尔文架构,GNU (gfortran/gcc) 编译器。我正在尝试编译 "serial" 配置。这是我关心的输出部分:
sed -e "s/^\!.*'.*//" -e "s/^ *\!.*'.*//" module_mp_fast_sbm.F > module_mp_fast_sbm.G
cpp -P -nostdinc -xassembler-with-cpp -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/inc -DEM_CORE=1 -DNMM_CORE=0 -DNMM_MAX_DIM=2600 -DDA_CORE=0 -DWRFPLUS=0 -DIWORDSIZE=4 -DDWORDSIZE=8 -DRWORDSIZE=4 -DLWORDSIZE=4 -DNONSTANDARD_SYSTEM_SUBR -DMACOS -DWRF_USE_CLM -DDM_PARALLEL -DSTUBMPI -DNETCDF -DLANDREAD_STUB=1 -DUSE_ALLOCATABLES -Dwrfmodel -DGRIB1 -DINTIO -DKEEP_INT_AROUND -DLIMIT_ARGS -DBUILD_RRTMG_FAST=0 -DBUILD_RRTMK=0 -DBUILD_SBM_FAST=1 -DSHOW_ALL_VARS_USED=0 -DCONFIG_BUF_LEN=65536 -DMAX_DOMAINS_F=21 -DMAX_HISTORY=25 -DNMM_NEST=0 -I. -traditional-cpp module_mp_fast_sbm.G > module_mp_fast_sbm.bb
/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/tools/standard.exe module_mp_fast_sbm.bb | cpp -P -nostdinc -xassembler-with-cpp -traditional-cpp > module_mp_fast_sbm.f90
rm -f module_mp_fast_sbm.G module_mp_fast_sbm.bb
time gfortran -o module_mp_fast_sbm.o -c -O2 -ftree-vectorize -funroll-loops -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -I../dyn_em -I../dyn_nmm -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/esmf_time_f90 -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/main -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/io_netcdf -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/external/io_int -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/frame -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/share -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/phys -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/wrftladj -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/chem -I/Users/isaacrowe/Documents/GitHub/WRF_ARW/WRF/inc -I/usr/local/Cellar/netcdf/4.7.4/include module_mp_fast_sbm.f90
module_mp_fast_sbm.f90:6065:4:
6065 | DM_BCAST_MACRO_R16 ( FAF1 )
| 1
Error: Unclassifiable statement at (1)
0.56 real 0.52 user 0.03 sys
这里发生的事情是,在最后一步编译的 Fort运行 文件仍然有一个未替换的宏。请记住,有许多这样的 Fort运行 文件,这是唯一一个有问题的文件。
我查看了宏在 module_mp_fast_sbm.F
中定义的位置,并看到了这些定义
#define DM_BCAST_MACRO_R4(A) CALL wrf_dm_bcast_bytes(A, size(A)*R4SIZE)
#define DM_BCAST_MACRO_R8(A) CALL wrf_dm_bcast_bytes(A, size(A)*R8SIZE)
#define DM_BCAST_MACRO_R16(A) CALL wrf_dm_bcast_bytes(A, size(A)*R16SIZE)
我还注意到同一宏的其他用法已被正确替换,但那些实例并未在宏名称、括号和参数之间使用 space。这让我想知道间距是否有所作为。所以我运行做了一个实验:
test.c:
#define DM_BCAST_MACRO_R4(A) CALL wrf_dm_bcast_bytes(A, size(A)*R4SIZE)
DM_BCAST_MACRO_R4(3);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
DM_BCAST_MACRO_R4( 3);
DM_BCAST_MACRO_R4 (3);
首先我使用了 WRF 脚本中使用的命令:
cat test.c | cpp -P -nostdinc -xassembler-with-cpp -traditional-cpp > output_traditional.txt
我得到了这个输出:
CALL wrf_dm_bcast_bytes(3, size(3)*R4SIZE);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
CALL wrf_dm_bcast_bytes( 3, size( 3)*R4SIZE);
DM_BCAST_MACRO_R4 (3);
我想可能是 WRF 使用的标志导致了这个问题,所以我尝试了这个命令:
cat test.c | cpp -P > output_noflags.txt
得到这个结果:
CALL wrf_dm_bcast_bytes(3, size(3)*R4SIZE);
// The style used by WRF
DM_BCAST_MACRO_R4 ( 3 );
// Just curious
CALL wrf_dm_bcast_bytes( 3, size( 3)*R4SIZE);
DM_BCAST_MACRO_R4 (3);
cpp -v
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name - -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -fno-strict-return -masm-verbose -munwind-tables -target-sdk-version=10.15.4 -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 556.6 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -I /usr/include -I/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -Wno-objc-signed-char-bool-implicit-int-conversion -Wno-extra-semi-stmt -Wno-quoted-include-in-framework-header -fdebug-compilation-dir /Users/isaacrowe/Desktop -ferror-limit 19 -fmessage-length 270 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=macosx-10.15.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -x c -
clang -cc1 version 11.0.3 (clang-1103.0.32.62) default target x86_64-apple-darwin19.5.0
ignoring nonexistent directory "/usr/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/include
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
根据我的阅读here,宏定义的左括号前不能有space,但是宏的使用可以在括号前有space。那么为什么我的预处理器没有进行替换?
使用 -traditional-cpp
时 clang 的 cpp 的这种行为一直是 reported back in 2013, with no followup to date. It seems like it's probably a bug, since gcc's preprocessor doesn't do it (example),看起来 3.2 版之前的 clang 也没有这样做。但是 -traditional-cpp
的预期语义在我所知道的任何地方都没有精确定义,而且 clang 维护者没有对错误报告做出回应,所以很难确定。也有可能他们只是不关心 -traditional-cpp
并认为它已过时。
看起来 -traditional-cpp
是 运行 cpp
独立安装时的默认设置。我不知道如何关闭它,但 -std=c90
可以。请注意 clang -E
也避免了传统模式并且似乎表现正确。
您也可以使用 gcc 的预处理器来代替 "bug"。如您所见,在您的系统上 gcc
命令实际上是 clang,但您可以从 Homebrew 安装真正的 gcc。