c++ - 在一个 Makefile 中编译 C++ 和 C

标签 c++ gcc makefile arm g++

我有一个项目是使用 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 文件的错误来自于我没有正确地将定义从 CFLAGS 转移到 CXX 标志的错误。一旦我添加了 -DBOARD=TEST 相关标志,我的头文件就能够识别我正在使用的板,这允许它通过“包含”链。

关于c++ - 在一个 Makefile 中编译 C++ 和 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50829974/

相关文章:

c++ - 这是实现自定义事件处理程序的正确方法吗?

c++ - 为什么 `S x({})` 仅在 GCC 7/C++1z 模式下调用默认构造函数?

c++ - MinGW gcc C 编译器工作,但 g++ 不工作

makefile - 如何编写Makefile以使用GNU Make自动检测并并行化构建?

linux - 如何在linux中使用我自己的动态库(Makefile)

makefile - OpenWRT 的 Elixir 包构建指南

未定义 C++ sqlite3 api (Visual Studio 2015)

c++ - 在 std::string 中查找第一个不是空格的字符

c++ - 计算最小N的置位位数

c - 错误-"/usr/bin/ld: cannot find -levent "的原因及解决方法?