【发布时间】:2018-11-22 14:34:35
【问题描述】:
我有一个使用 arm-none-eabi-gcc 工具链用 C 语言为 ARM 设备编写和开发的项目。它使用了一个只为 C 编译工作的自定义 makefile。我们试图在保留 C 源文件的同时过渡到主要 C++ 项目,但我在更新 makefile 时遇到问题。我知道这已被问过几次,但没有一个能够完全解决我们的问题。如何包含 C 源文件和头文件以使用 g++ 和 cpp 文件进行编译?
我非常感谢愿意并且能够查看我们的 makefile 以帮助解决编译问题的任何人。 makefile 很长,所以这里有一个略为删节的版本,应该包含所有重要的内容。
请记住,我只在此处包含了 makefile,而不是 platform_id.mk 或 $(PLATFORM_MCU).mk,但我对这些文件非常有信心。
BIN_NAME = $(PLATFORM)_firmware.bin
ifdef PLATFORM
include $(PROJECT_ROOT)build/platform_id.mk
include $(PROJECT_ROOT)hal/$(PLATFORM_MCU)/$(PLATFORM_MCU).mk
include $(PROJECT_ROOT)build/$(PLATFORM_MCU_CORE)/$(PLATFORM_MCU_CORE).mk
else
$(error "Platform not defined. Used the -e flag to define the platform in the environment
endif
$(info $(msg))
# C compiler flags
CFLAGS +=\
-std=c99\
-Og\
-g3\
-Wall\
-fdata-sections\
-ffunction-sections\
-MMD\
-DHAVE_MMAP=0\
-Dmalloc_getpagesize=8\
-DMORECORE_CLEARS=0\
-DDEFAULT_TRIM_THRESHOLD=8
# C++ compiler flags
CXXFLAGS +=\
-Wall\
-D__STDC_LIMIT_MACROS
# C Pre Processor flags
CPPFLAGS +=\
# Undefine WIN32 variable if building on Windows host
ifdef WIN32
CFLAGS += -UWIN32
msg = You're on a windows host.
else
msg = You're not on a windows host.
endif
ifdef TOOLCHAIN
AR = $(TOOLCHAIN)-ar
CC = $(TOOLCHAIN)-gcc
CXX = $(TOOLCHAIN)-g++
endif
# Binary make targets
TARGET = out/$(PLATFORM_MCU)/$(BIN_NAME)
# Binary Sources
VPATH += $(wildcard */src/)
# extract all *.c filenames, don't pull the filepath with it
C_SRCS += $(notdir $(wildcard */src/*.c))
# extract all *.cpp filesnames, don't pull the filepath with it
CXX_SRCS += $(notdir $(wildcard */src/*.cpp))
# extract all *.s filenames, don't pull the filepath with it
S_SRCS += $(notdir $(wildcard */src/*.s))
# Objects
OBJECTS_C += $(patsubst %.c,out/$(PLATFORM_MCU)/obj/%.o,$(C_SRCS))
OBJECTS_CXX += $(patsubst %.cpp,out/$(PLATFORM_MCU)/obj/%.o,$(CXX_SRCS))
# Dependencies
DEP_C := $(OBJECTS_C:.o=.d)
DEP_CXX := $(OBJECTS_CXX:.o=.d)
# Includes
NULL =
SPACE = $(NULL) $(NULL)
INCLUDE_SRC = $(subst $(SPACE),$(SPACE)-I,$(VPATH))
PATH_INC = $(wildcard */inc/)
INCLUDE_INC = $(subst $(SPACE),$(SPACE)-I,$(PATH_INC))
C_INC +=\
-I$(INCLUDE_INC) \
-I$(INCLUDE_SRC)
# Clean and precious
PRECIOUS += out/$(PLATFORM_MCU)/obj/%.o
CLEAN += out/$(PLATFORM_MCU)/
# all
all: $(TARGET)
# Create binary
$(TARGET): $(OBJECTS_C) $(OBJECTS_CXX) $(S_SRCS)
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) $(C_INC) -T$(LDFILE) $(LFLAGS) -o $@
$(TOOLCHAIN)-objcopy -O binary $@ $(basename $@).bin
# Compile from cpp files. Compilation works when this is removed (and toolchain and files are tweaked to represent that)
out/$(PLATFORM_MCU)/obj/%.o: %.cpp
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) $(C_INC) -o $@ -c $<
-include $(DEP_CXX)
# Create binary from c files
out/$(PLATFORM_MCU)/obj/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(C_INC) -o $@ -c $<
-include $(DEP_C)
.PRECIOUS: $(PRECIOUS)
.PHONY: all clean
clean:
rm -rf $(CLEAN)
在运行make -e PLATFORM=test 之后,错误很多,主要是说明 c 源代码中的各种函数未定义。现在 main.cpp 只不过是 int main() 并包含到一个包含大多数其他 C 头文件的头文件中。
以下是编译器错误之一的示例:
hal/atsamg55/sam/drivers/usart/usart.h:333:47: error: 'p_usart' was not declared in this scope
uint32_t usart_get_writeprotect_status(Usart *p_usart);
这里是 main.cpp
#include "headers.h"
int main(){
while(1)
{
}
return 0;
}
再次感谢您提供的任何帮助。
【问题讨论】:
-
你的 C++ 代码使用
extern "C"吗? -
@JVApen 我应该澄清一下。 C 文件包括
ifdef __cplusplus extern "C"。删除这些语句似乎并没有改变我收到的错误。是否需要在c++文件中添加相关语句? -
是编译错误还是链接错误?你能补充一些问题吗?
-
刚刚在原始帖子中添加了一个错误。好像是编译错误?我确实确认与 usart.h 关联的 .c 文件包含在目标文件列表中。谢谢!
-
确实是编译错误。在我看来,好像还有其他问题,编译器抱怨无法解决的变量。由于问题位于编译中,我建议将编译命令添加到 main.cpp 的问题和(减少)源