Makefile有两个目标和两种语言

时间:2015-06-18 11:26:11

标签: c++ c gcc makefile

我使用C和C ++,感谢this answer我能够编译并运行我的项目。现在我正在写一个makefile来腾出时间。但事情变得越来越复杂了:

项目结构

  
      
  • 项目      
        
          
    • 生成文件
    •     
      
  •   
  • 客户端      
        
    •   
    • SRC      
          
      • C
      •   
      • CC
      •   
      • 的java
      •   
    •   
  •   
  • 服务器      
        
    • ...
    •   
  •   
# Directories

# CLIENT
CLIENT_BIN_DIR      = /client/bin/
CLIENT_SRC_C_DIR    = /client/src/c/
CLIENT_SRC_CC_DIR   = /client/src/cc/
CLIENT_SRC_JAVA_DIR = /client/src/java/
# SECC
SERVER_BIN_DIR      = /server/bin/
SERVER_SRC_C_DIR    = /server/src/c/
SERVER_SRC_CC_DIR   = /server/src/cc/
SERVER_SRC_JAVA_DIR = /server/src/java/

# Files

# CLIENT
CLIENT_BIN          = ${CLIENT_BIN_DIR}client_app
CLIENT_SRC_C        = ${wildcard ${CLIENT_SRC_C_DIR}*.c}
CLIENT_SRC_CC       = ${wildcard ${CLIENT_SRC_CC_DIR}*.cc}
CLIENT_SRC_JAVA     = ${wildcard ${CLIENT_SRC_JAVA_DIR}*.java}

# SERVER
SERVER_BIN          = ${SERVER_BIN_DIR}server_app
SERVER_SRC_C        = ${wildcard ${SERVER_SRC_C_DIR}*.c}
SERVER_SRC_CC       = ${wildcard ${SERVER_SRC_CC_DIR}*.cc}
SERVER_SRC_JAVA     = ${wildcard ${SERVER_SRC_JAVA_DIR}*.java}

# Flags
CFLAGS              = -g -W -Wall
IFLAGS              = -I${INC_DIR}

# Compilers
C                   = gcc
CC                  = g++

# Rules
all: ${CLIENT_BIN} ${SERVER_BIN}
${CLIENT_BIN}:
${SERVER_BIN}:
// NEED HELP HERE

既然我有所有的源文件,我应该写下每个文件的以下步骤:

  1. gcc -c -o file.o file.c
  2. g++ -c -o file.o file.cc -I/PATH_TO_C_HEADER
  3. g++ -o APP_NAME C_O_FILES CC_O_FILES

3 个答案:

答案 0 :(得分:1)

make built-in rules用于将C和C ++文件编译为目标文件,您可以使用它们而不是使用他们期望的内置标志来编写自己的文件。类似地,make有一个从目标文件构建二进制文件的规则(只要二进制文件与其中一个源文件完全匹配)。

  

编译C程序

n.o is made automatically from n.c with a recipe of the form ‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
     

编译C ++程序

n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
     

链接单个目标文件

     

n是通过C编译器运行链接器(通常称为ld)从n.o自动生成的。使用的精确配方是'$(CC)$(LDFLAGS)n.o $(LOADLIBES)$(LDLIBS)'。

     

对于只有一个源文件的简单程序,此规则是正确的。如果有多个目标文件(可能来自各种其他源文件),其中一个名称与可执行文件的名称相匹配,它也会做正确的事情。因此,

x: y.o z.o
     

当x.c,y.c和z.c全部存在时将执行:

cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o
     

在更复杂的情况下,例如当没有名称来自可执行文件名的目标文件时,您必须编写一个明确的链接配方。

     

自动制作成'.o'对象文件的各种文件将通过编译器自动链接('$(CC)','$(FC)'或'$(PC)'; C编译器' $(CC)'用于组装'.s'文件)而不使用'-c'选项。这可以通过使用'.o'对象文件作为中间体来完成,但是在一步中进行编译和链接会更快,所以这就是它的完成方式。

因此,只需设置正确的标志(在这些规则中使用)并将正确的.o文件先决条件添加到二进制目标中,您应该完成。

答案 1 :(得分:0)

# client binary depends on c and c++ .o's
$(CLIENT_BIN): $(CLIENT_SRC_C:.c=.o) $(CLIENT_SRC_CC:.cc=.o)

# server binary depends on c and c++ .o's
$(SERVER_BIN): $(SERVER_SRC_C:.c=.o) $(SERVER_SRC_CC:.cc=.o)

# example header dependency (file.cc depends on file.h and file1.h)
$(CLIENT_SRC_CC_DIR)file.o: $(CLIENT_SRC_CC_DIR)file.h $(CLIENT_SRC_CC_DIR)file1.h

GNU Make有编译C和C ++源文件的隐式规则并生成最终的二进制文件,所以不需要重写它们。

此外,您可能需要RTFM

答案 2 :(得分:0)

如果你必须使用make,这可以帮助你入门(仅适用于C文件):

# CLIENT
CLIENT_BIN_DIR      = client/bin/
CLIENT_SRC_C_DIR    = client/src/c/

# CLIENT
CLIENT_BIN          = $(CLIENT_BIN_DIR)client_app
CLIENT_SRC_C        = $(wildcard $(CLIENT_SRC_C_DIR)*.c)
CLIENT_SRC_C_O      = $(CLIENT_SRC_C:.c=.o)
CLIENT_SRC_C_D      = $(CLIENT_SRC_C:.c=.d)

# Flags
CFLAGS              = -g -W -Wall
IFLAGS              = -I$(INC_DIR)

# Compilers
C                   = gcc

#Create header dependency files (included headers are dependencies too)
%.d: %.c
    $(C) $(CFLAGS) -MM -MF $@ -MT $*.o $<

#include will remake the dependency files if they need to be
-include $(CLIENT_SRC_C_D)

#O files will be created via the implicit rule
$(CLIENT_BIN): $(CLIENT_SRC_C_O)
    $(C) $(CFLAGS) $(LDFLAGS) $^ -o $(@)

all: $(CLIENT_BIN)

https://www.gnu.org/software/make/manual/make.html非常有帮助。

否则,如果可以,我建议使用tup,这比制作更容易,更灵活,更快速,更先进。