I've seen a project,它使用asm
关键字作为变量名,并且代码在Makefile
上使用提供的Linux
可以正常编译:
int
main(int ac, char *av[])
{
struct TMap *tm;
FILE *inf, *hf;
char *f, *sep;
int c, asm; // <---
asm = Defasm;
// ...
}
这是整个Makefile
:
BIN = qbe
V = @
OBJDIR = obj
SRC = main.c util.c parse.c cfg.c mem.c ssa.c alias.c load.c copy.c \
fold.c live.c spill.c rega.c gas.c
AMD64SRC = amd64/targ.c amd64/sysv.c amd64/isel.c amd64/emit.c
ARM64SRC = arm64/targ.c arm64/abi.c arm64/isel.c arm64/emit.c
SRCALL = $(SRC) $(AMD64SRC) $(ARM64SRC)
AMD64OBJ = $(AMD64SRC:%.c=$(OBJDIR)/%.o)
ARM64OBJ = $(ARM64SRC:%.c=$(OBJDIR)/%.o)
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(AMD64OBJ) $(ARM64OBJ)
CFLAGS += -Wall -Wextra -std=c99 -g -pedantic
$(OBJDIR)/$(BIN): $(OBJ) $(OBJDIR)/timestamp
@test -z "$(V)" || echo "ld $@"
$(V)$(CC) $(LDFLAGS) $(OBJ) -o $@
$(OBJDIR)/%.o: %.c $(OBJDIR)/timestamp
@test -z "$(V)" || echo "cc $<"
$(V)$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/timestamp:
@mkdir -p $(OBJDIR)
@mkdir -p $(OBJDIR)/amd64
@mkdir -p $(OBJDIR)/arm64
@touch $@
$(OBJ): all.h ops.h
$(AMD64OBJ): amd64/all.h
$(ARM64OBJ): arm64/all.h
obj/main.o: config.h
config.h:
@case `uname` in \
*Darwin*) \
echo "#define Defasm Gasmacho"; \
echo "#define Deftgt T_amd64_sysv"; \
;; \
*) \
echo "#define Defasm Gaself"; \
case `uname -m` in \
*aarch64*) \
echo "$define Deftgt T_arm64"; \
;; \
*) \
echo "#define Deftgt T_amd64_sysv";\
;; \
esac \
;; \
esac > $@
install: $(OBJDIR)/$(BIN)
mkdir -p "$(DESTDIR)/$(PREFIX)/bin/"
cp $< "$(DESTDIR)/$(PREFIX)/bin/"
uninstall:
rm -f "$(DESTDIR)/$(PREFIX)/bin/$(BIN)"
clean:
rm -fr $(OBJDIR)
clean-gen: clean
rm -f config.h
check: $(OBJDIR)/$(BIN)
tools/test.sh all
check-arm64: $(OBJDIR)/$(BIN)
TARGET=arm64 tools/test.sh all
src:
@echo $(SRCALL)
80:
@for F in $(SRCALL); \
do \
awk "{ \
gsub(/\\t/, \" \"); \
if (length(\$$0) > $@) \
printf(\"$$F:%d: %s\\n\", NR, \$$0); \
}" < $$F; \
done
.PHONY: clean clean-gen check check-arm64 src 80 install uninstall
我想知道如何实现编译器将asm
用作变量名(忽略这样做的错误样式这一事实)。我尝试将Makefile
移植到CMakeLists.txt
,但是由于asm
的无效用法,编译器引发了错误。如何在不更改代码的情况下解决此问题?我已经像C99
一样强行使用Makefile
标准,并使用了相同的C
编译器标志,但这无济于事:
cmake_minimum_required(VERSION 3.10.2)
project(qbe C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-Wall -Wextra -std=c99 -g -pedantic")
include_directories(amd64)
add_executable(qbe
amd64/all.h
amd64/emit.c
amd64/isel.c
amd64/sysv.c
amd64/targ.c
alias.c
all.h
cfg.c
copy.c
fold.c
gas.c
live.c
load.c
main.c
mem.c
ops.h
parse.c
rega.c
spill.c
ssa.c
util.c)
由于CMake
的支持,我想使用IDE
。
答案 0 :(得分:4)
asm
不是标准C的关键字,也不是保留的标识符,尽管是the standard recognizes it as a common extension。该标准进一步指出
包含任何可能导致严格符合的扩展名 程序变为无效会导致实现不合格。 此类扩展的示例包括新关键字,额外的库函数 在标准标头或预定义的宏中声明的名称 不是以下划线开头。
这在Annex J中,它是非规范性的,但是它仅总结了可以从规范性文本中得出的结论。因此,符合标准的实现不会因为使用asm
作为标识符而拒绝代码。
例如,我发现在使用GCC支持的任何严格一致性模式(asm
,-std=c89
或{{1})时,GCC都接受使用-std=c99
作为标识符}),但默认情况下会出现错误或通过专门启用的GNU扩展(例如,-std=c11
)将其拒绝。如果您使用的是其他编译器,则如果可能的话,您将需要查阅其文档以获取如何符合该领域标准的要求。
对于为什么您的CMake尝试失败的原因,-std=gnu11
属性没有按照您认为的那样做。它告诉CMake在可能的情况下选择提供C版本指定版本功能的编译器选项,但不要求对该标准严格遵守。文档专门假设它会导致在某些情况下使用CMAKE_C_STANDARD
选项,并且该选项或类似的包含选项会产生与您想要的相反的效果。
答案 1 :(得分:3)
asm
不是标准的C关键字。合格的C编译器可能不会拒绝编译使用asm
作为标识符的程序。
使用-std=c99
明确选择标准也会删除asm
关键字。但是,您可以继续使用__asm__
,因为实现中始终将所有以两个下划线开头的名称保留为 any 使用。
但是,它仍然是非常糟糕的样式,因为 C99 ,C11和C17修订版 do 都将其称为common extension 。