c - 适当的 Makefile 来替换 gcc 编译/链接运行?

标签 c gcc makefile gnu-make

我的目标是使用单个 Makefile 跨各种平台编译 C 应用程序。

我在做项目的时候一直在忙着重新学习C,所以还没有时间深入研究make;相反,我在一些 .bat/.sh 文件中有一个很长的 gcc 命令。不用说,每次我更改一个这样的文件时,我都必须对其他文件进行相同的更改。因此,make。需要处理的情况:

  • 针对多个操作系统和架构进行构建,即目前(至少)针对 Windows 和 Linux 的 32 和 64 位,因此我需要访问 Makefile 中的该信息,并且可执行文件应进入/build 下的不同文件夹:即 /win32/win64/lin32/lin64 (等等,将来)。
  • 所需的 DLL 应与构建的可执行文件一起复制。
  • 单独的编译和链接阶段(感谢@EtanReisner)

问题:有人可以告诉我如何使用下面的信息构建 Makefile 吗?并解释每个部分如何工作/为什么我的特定案例需要它?我了解构建 Makefile 的先决条件方法。提前致谢。

这是我的项目目录树:

+---bin
+---include
|   +---enet
|   +---GL
|   +---libxml
|   \---ncursesw
+---lib
+---src
+---fonts
\---shaders    

以及用于 Windows 32 位编译的 mingw gcc:

gcc -Iinclude ./src/main.c ./src/MainCtrl.c ./src/MainView.c ./src/PerspectiveView.c ./src/LogView.c ./src/LobbyView.c ./src/TerminalView.c ./src/World.c ./src/Chunk.c ./src/CellPattern.c ./src/CellPlan.c ./src/GridPoint.c ./src/Entity.c ./src/InfluenceRadial.c ./src/AoIList.c ./src/AoI.c ./src/ChunkRenderable.c ./src/PrimitiveRenderable.c ./src/Geometry.c ./src/glew/glew.c ./src/stb/stb_image_aug.c ../curt/list_generic.c ../curt/map_generic.c ../curt/intMap.c ../curt/floatMap.c ../hedgehog/hedgehog.c ./src/Inputs.c ./src/InputResponse.c ./src/Network.c ../Disjunction/c/disjunction.c ./src/my/math/Range.c ./src/my/math/Point.c -Llib -lglfw3-32 -lopengl32 -lgdi32 -lenet-32 -lws2_32 -lwinmm -llibxml2-32 -L. -ldll32/libncursesw6 -std=c11 -m32 -w -Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wstrict-prototypes -Wlogical-op -Wcast-align -Wconversion -Wpedantic -Wfloat-equal -fopenmp -O0 -o ./build/win32/wa

以及用于 Linux 64 位编译的 gcc:

gcc -Iinclude -I/usr/include/libxml2 ./src/main.c ./src/MainCtrl.c ./src/MainView.c ./src/PerspectiveView.c ./src/LogView.c ./src/LobbyView.c ./src/TerminalView.c ./src/World.c ./src/Chunk.c ./src/CellPattern.c ./src/CellPlan.c ./src/GridPoint.c ./src/Entity.c ./src/InfluenceRadial.c ./src/AoIList.c ./src/AoI.c ./src/ChunkRenderable.c ./src/PrimitiveRenderable.c ./src/Geometry.c ./src/glew/glew.c ./src/stb/stb_image_aug.c ../curt/list_generic.c ../curt/map_generic.c ../curt/intMap.c ../curt/floatMap.c ../hedgehog/hedgehog.c ./src/Inputs.c ./src/InputResponse.c ./src/Network.c ../disjunction/c/disjunction.c ./src/my/math/Range.c ./src/my/math/Point.c -Llib -L/usr/lib -l:libglfw.so.3 -lncurses -lGL -lxml2 -lenet -lm -std=c11 -m64 -w -Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wstrict-prototypes -Wlogical-op -Wcast-align -Wconversion -Wpedantic -Wfloat-equal -fopenmp -g -o ./wa-64.elf

(值得区分这些。)

最佳答案

反复试验导致了以下结果...工作正在进行中,但基础知识已经存在。特点:

  • 无需手动列出源文件/目标文件(所有相关源均应位于 src 中)
  • 使用 .c/.o 文件列表的共享逻辑来分离编译和链接阶段
  • 操作系统和架构自动检测 (WIP),可手动覆盖架构 ( 例如使 BITS=32)
  • 适用于 Win 和 *nixes 的 Clean
  • 编译时复制 .DLL(WIP 提供要复制的 DLL 列表)

感谢Yanick Rochon , SamuelTrevor Robinson寻求他们的答案,以及那些写下 GNU Makefile examples 的人.

CC = gcc

#Directories
HDRDIR   = include
SRCDIR   = ./src
OBJDIR   = ./obj
BINDIR   = ./bin
LIBDIR   = lib

#File lists
HDRS := $(wildcard $(HDRDIR)/*.h)
SRCS := $(wildcard $(SRCDIR)/*.c)
OBJS := $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o)

#Autodetect OS / architecture
OS =
BITS = 32

#ifeq ($(shell echo "check_quotes"),"check_quotes")
ifeq ($(OS),Windows_NT)
    OS   := win
    EXT  := .exe
    rm   := del /q
    cp   := copy /y
    ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
        CFLAGS += -D AMD64
    endif
    ifeq ($(PROCESSOR_ARCHITECTURE),x86)
        CFLAGS += -D IA32
    endif
else
    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Linux)
        OS  := lin
        EXT := .elf
        rm  := rm -f
        cp  := cp
        CCFLAGS += -D LINUX
        BITS = $(shell getconf LONG_BIT)
    endif
    ifeq ($(UNAME_S),Darwin)
        OS := osx
        EXT :=
        rm  := rm -f
        cp  := cp
        CCFLAGS += -D OSX
        BITS = $(shell getconf LONG_BIT)
    endif
    UNAME_P := $(shell uname -p)
    ifeq ($(UNAME_P),x86_64)
        CCFLAGS += -D AMD64
    endif
    ifneq ($(filter %86,$(UNAME_P)),)
        CCFLAGS += -D IA32
    endif
    ifneq ($(filter arm%,$(UNAME_P)),)
        CCFLAGS += -D ARM
    endif
endif

#Define flags for compile & link
CFLAGS = -I$(HDRDIR) -std=c11 -m64 -fopenmp -Wall -Werror -Wmissing-prototypes -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wlogical-op -Wcast-align -Wconversion -Wpedantic -Wfloat-equal -w -O0 -DGLEW_STATIC
LFLAGS = -L$(LIBDIR)

#Do we want verbose linker messages?
LVERBOSE := false 
LLIBS =
ifeq ($(OS),win)
    LLIBS += -lglfw3-$(BITS) -lglew32s -lglew32 -lopengl32 -lgdi32 -lwinmm
endif
ifeq ($(OS),lin)
    LLIBS += -lglew32s -lglew32 -lGL -lm
endif
ifeq ($(LVERBOSE),true)
    LFLAGS += -Wl,--verbose
endif

TARGET = program$(EXT)

#Rules
$(BINDIR)/$(TARGET): $(OBJS)
    @$(CC) -o ./$@ $(OBJS) $(LFLAGS) $(LLIBS) 
    @echo Linking complete.
    @$(cp) $(LIBDIR)\glfw3.dll $(BINDIR)
    @echo DLLs accompanying executable.

$(OBJS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    @$(CC) $(CFLAGS) -c $< -o ./$@
    @echo Compiled $<.

.PHONEY: clean
clean:
ifeq ($(OS),win)
    @$(rm) $(subst /,\\,$(OBJS))
    @$(rm) $(subst /,\\,$(BINDIR)/*.*)
else
    @$(rm) $(OBJS)
    @$(rm) $(BINDIR)/*
endif
    @echo Cleanup complete.
#$(subst /,\\, $(SOMETHING)) replaces all (make-native) forward slashes with backslashes, for Windows.

关于c - 适当的 Makefile 来替换 gcc 编译/链接运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31186431/

相关文章:

c++ - 与位域相邻的变量会损坏吗?

编译剪贴板的内容

c++ - 与 gdb 一起使用的 Makefile

c - 如何检查文件是否完全到达/复制?

c - 使用链表存储txt的句子

c - 使用 C 预处理获取字符串的整数值

c++ - GCC C++ 编译器是否考虑了 __restrict - 语句?

c - 使用Makefile编译时出现错误 "no such file or directory"

Makefile - 如何调用其他具有依赖项的 makefile

c - 可执行文件的大小?