使用一个主服务器和两个从服务器更正makefile

时间:2016-01-19 21:11:06

标签: c makefile

我正在尝试为多线程程序编写一个makefile,该程序具有执行两个从属进程的主进程。还有一个库(由主人和奴隶使用)。

我不确定我应该如何编译库。

但有时候,修改文件中的一个,makefile命令不会重新编译它(它表示与'all'无关)。

我尝试这样写(Ubuntu):

all:executable

executable: slave1 slave 2 executable.o
  gcc -o executable executable.o 

slave1: slave1.o
  gcc -o slave1 slave1.o

slave2: slave2.o
  gcc -o slave2 slave2.o

library.o : library.c
  gcc -c library.c

executable.o: executable.c
  gcc -c executable.c

slave1.o: slave1.c
   gcc -c slave1.c

slave2.o: slave2.c
   gcc -c slave2.c

我也尝试过:

all:executable

executable: slave1 slave2
gcc -g -o executable executable.c

slave1:
gcc -g -o slave1 slave1.c library.c-lm

slave2:
gcc -g -o slave2 slave2.c library.c -lm

程序结构如此定义:

executable.c,slave1.c,slave2.c,library.c include library.h

可执行文件运行slave1和slave 2

3 个答案:

答案 0 :(得分:2)

你的makefile完全错了。 makefile的一般结构如下:

target: prerequisite1 prerequisite2 ...
    commands to make target (most probably using prerequisites)

所以:

all:executable

要制作all目标,我们必须制作executable。右。

executable: slave1 slave 2 executable.o
  gcc -o executable executable.o 

从这些方面看,executable取决于slave1slave2executable.o。以下命令仅使用executable.o来创建executable,因此存在不必要的先决条件(以及拼写错误)。

下一步:

slave1: slave1.o
    gcc -o slave1 slave1.o

slave2: slave2.o
    gcc -o slave2 slave2.o

看起来没错,直到你不需要library.o来构建它们。

下一步:

library.o : library.c
    gcc -c library.c

此处为library.o,但未使用作为任何目标的先决条件。所以赢得根本就没有。

executable.o: executable.c
    gcc -c executable.c

slave1.o: slave1.c
    gcc -c slave1.c

slave2.o: slave2.c
    gcc -c slave2.c

那些看起来不错,但gcc命令缺少-o module.o部分。

因此,正如您所看到的,您的makefile几乎在所有可能的级别上都是错误的。

这是可以工作的makefile。它可能会更加紧凑(很多),但为了清晰起见,我会这样写:

all: executable slave1 slave2

executable: executable.c
    gcc -g -o executable executable.c

slave1: slave1.c library.c library.h
    gcc -g -o slave1 slave1.c library.c -lm

slave2: slave2.c library.c library.h
    gcc -g -o slave2 slave2.c library.c -lm

你可以看到它很简单。要制作all,我们必须构建executableslave1slave2executable取决于executable.c,每个slaveX二进制文件取决于slaveX.clibrary.clibrary.h来源。如果任何源文件更改make将重新编译目标。瞧。

答案 1 :(得分:1)

你告诉我们的是:

  • slave1.c依赖于library.h
  • slave2.c依赖于library.h
  • executable.c依赖于library.h
  • library.c取决于library.h

  • 每个源代码文件都需要编译为目标文件。

猜测:

  • 通过链接slave1.o和library.o
  • 生成slave1可执行文件
  • 通过链接slave2.o和library.o
  • 生成slave2可执行文件
  • 通过链接executable.o和library.o
  • 生成可执行文件可执行文件

因此,让我们说明这些规则,并让makefile默认构建所有可执行文件

#1. target becomes the default target.
#have it depend on all the executables    
all: slave1 slave2 executable

#state that slave1.c depends on library.h and so on.
slave1.c: library.h
slave2.c: library.h
executable.c: library.h
library.c: library.h

#State that the object file depends on the source file and
#produce the object file by compiling the source code file

slave1.o: slave1.c
     gcc -g -o slave1.o -c slave1.c

slave2.o: slave2.c
     gcc -g -o slave2.o -c slave2.c

executable.o: executable.c
     gcc -g -o executable.o -c executable.c 

library.o: library.c
     gcc -g -o library.o -c library.c 

#state that the executables depends on the object files, and 
#produce each executable by linking those object files

slave1: executable.o library.o
     gcc -o slave1 slave2.o library.o

slave2: library.o slave2.o 
     gcc -o executable slave2.o library.o 

executable: library.o executable.o 
     gcc -o executable executable.o library.o

所有缩进的命令(gcc命令)必须只是一个制表符。

  • 另请注意,有许多方法可以缩短和概括这样的Makefile。

这样(也可以进一步细化)

CC=gcc
CFLAGS=-g -Wall
LIBS=-lm

.PHONY: all
all: slave1 slave2 executable

slave1.c: library.h
slave2.c: library.h
executable.c: library.h
library.c: library.h

%.o: %.c
    $(CC) $(CFLAGS) -c -o $@ $< 

slave1: executable.o library.o
     $(CC) -o $@ $^ $(LIBS)

slave2: library.o slave2.o 
     $(CC) -o $@ $^ $(LIBS)

executable: library.o executable.o 
     $(CC) -o $@ $^ $(LIBS)

答案 2 :(得分:0)

您没有需要library.o的规则,因此make认为您不需要它来构建all。奇怪的是,我甚至没有看到使用你的库的链接器命令,这肯定不是你想要的。因此,为所有命令添加所有必需的先决条件,并相应地更新规则先决条件,您应该没问题。

旁注:实际上,make的所有问题都直接或间接地来自缺少的先决条件。如果您以任何方式将其置于黑暗中,make无法正常工作。因此,请始终尝试检查所有目标是否依赖于所有必需的输入。头文件就是一个例子。在使用该标头的文件的任何规则中作为先决条件丢失的任何标头都意味着您在某个地方获得了不完整的重建。这就是为什么标头依赖关系几乎总是自动生成的原因,因为人类无法正确获取这些依赖关系。