---底部的完整Makefile ---
我正在完成一个项目,所以我来到包装/编译部分。 我正在使用Make,我的项目的特殊性在于它包含两个项目,每个项目都有一个main()。
我想要第一个项目的二进制文件(名为'shell')和第二个项目的二进制文件(名为'ls')。我已经编辑了Makefile来分隔目标,源文件等。以下是重要的部分:
-- Projects --
TARGET_SHELL = shell
TARGET_LS = ls
-- Directories --
SOURCE = ./src
BIN = ./bin
DIRLIST = ${SOURCE} ${BIN}
-- Targets --
BINSHELL = ${TARGET_SHELL:%=${BIN}/%}
BINLS = ${TARGET_LS:%=${BIN}/%}
-- Files --
SRC_SHELL = ${wildcard ${SOURCE}/execution.c ${SOURCE}/shell.c}
SRC_LS = ${wildcard ${SOURCE}/commande_ls.c}
INT_SHELL = ${wildcard ${SOURCE}/execution.h}
INT_LS = ${wildcard ${SOURCE}/commande_ls.h}
OBJ_SHELL = ${SRC_SHELL:%.c=%.o}
OBJ_LS = ${SRC_LS:%.c=%.o}
-- Rules --
all : ${BINSHELL} ${BINLS}
-- Binaries --
${BIN}/${TARGET_SHELL} : ${${TARGET_SHELL}:%=${SOURCE}/%}
${BIN}/${TARGET_LS} : ${${TARGET_LS}:%=${SOURCE}/%}
${BIN}/% : $(OBJ_SHELL)
@echo
@echo Linking bytecode : $@
@echo ----------------
@echo
${CC} -o $@ $^ ${LDFLAGS}
@echo
@echo Done
@echo
'make'命令工作正常。最后,我有两个二进制文件,一个名为'shell',另一个名为'ls'。尼斯!
但事实上,这两个二进制文件完全相同,它们都执行'shell'项目。我希望二进制'shell'执行'shell'项目,以及名为'ls'的二进制文件来执行'ls'项目......
我知道我必须编辑Makefile的结尾,但我不知道:(
由于
#/// @file
#/// @brief Generic Makefile for the System 2 project.
#
#/// @detail If you just add some library files used by the project.c program, you have nothing to change to compile them if sources are in the ./src directory. To add a new binary, just add the name of the main file in the TARGETS variable.
#Nom du project
TARGET_SHELL = shell
TARGET_LS = ls
##############
# Constantes #
##############
# Repertoires
SOURCE = ./src
BIN = ./bin
DOCPATH = ${SOURCE}/dox
DOCTARGET = ./doc
DIRLIST = ${SOURCE} ${BIN}
#DEP = ${SOURCE}/depend
#DIRLIST = ${SOURCE} ${BIN} ${OPT} ${DEP}
# Cibles
BINSHELL = ${TARGET_SHELL:%=${BIN}/%}
BINLS = ${TARGET_LS:%=${BIN}/%}
# Commandes
CC = gcc
# Options
CFLAGS = -O0 -g -W -Wall -Wextra -Wconversion -Werror -mtune=native -march=native -std=c99 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700
LDFLAGS = -lm -W -Wall -pedantic -L. -lm
# Fichiers
DOX = ${wildcard ${DOCPATH}/*.dox} # Sources
SRC_SHELL = ${wildcard ${SOURCE}/divers.c ${SOURCE}/commandes_externes.c ${SOURCE}/commandes_internes.c ${SOURCE}/entities.c ${SOURCE}/execution.c ${SOURCE}/parse.c ${SOURCE}/shell.c} # Sources
SRC_LS = ${wildcard ${SOURCE}/commande_ls.c}
INT_SHELL = ${wildcard ${SOURCE}/divers.h ${SOURCE}/commandes_externes.h ${SOURCE}/commandes_internes.h ${SOURCE}/execution.h ${SOURCE}/parse.h} # Interfaces
INT_LS = ${wildcard ${SOURCE}/commande_ls.h}
OBJ_SHELL = ${SRC_SHELL:%.c=%.o} # Objets
OBJ_LS = ${SRC_LS:%.c=%.o}
##########
# Regles #
##########
# ALL
all : ${BINSHELL} ${BINLS}
# CLEAN
clean :
@echo
@echo Cleaning : object files
@echo --------
@echo
rm -f ${OBJ_SHELL}
rm -f ${OBJ_LS}
clean-doc :
@echo
@echo Cleaning : object files
@echo --------
@echo
rm -fr ${DOCTARGET}
clean-emacs :
@echo
@echo Cleaning : emacs back-ups
@echo --------
@echo
rm -f ${SOURCE}/*~
rm -f ${SOURCE}/\#*\#
rm -f *~
rm -f \#*\#
clean-bin :
@echo
@echo Cleaning : binaries
@echo --------
@echo
rm -f ${BINSHELL}
rm -f ${BINLS}
distclean : clean clean-emacs clean-bin
dirs :
@for dir in ${DIRLIST} ;\
do \
echo Creating directory : $${dir} ;\
echo ------------------ ;\
if test -d $${dir} ;\
then \
echo Directory already exists ;\
else mkdir -p $${dir} ;\
fi ;\
echo Done ;\
echo ;\
done
# Binaires
${BIN}/${TARGET_SHELL} : ${${TARGET_SHELL}:%=${SOURCE}/%}
${BIN}/${TARGET_LS} : ${${TARGET_LS}:%=${SOURCE}/%}
${BIN}/% : $(OBJ_SHELL)
@echo
@echo Linking bytecode : $@
@echo ----------------
@echo
${CC} -o $@ $^ ${LDFLAGS}
@echo
@echo Done
@echo
# Regles generiques
%.o : %.c %.h
@echo
@echo Compiling $@
@echo --------
@echo
$(CC) $(CFLAGS) -c $< -o $@
# Documentation
doc : ${SRC} ${INT} ${DOX}
doxygen; doxygen
#############################
# Inclusion et spécificités #
#############################
.PHONY : all clean clean-doc clean-emacs clean-bin distclean doc
答案 0 :(得分:0)
你有没有试过这样的事情:
SUBDIRS := common programs
all: subdir
ifdef SUBDIRS
.PHONY: subdir $(SUBDIRS)
subdir: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -s -C $@ <-- ${BIN...
endif
SUBDIRS - &gt; TARGET ...
答案 1 :(得分:0)
非常动态的makefile很有趣:
#
# Boilerplate.
#
define add_target
$(info add_target($1))
$(eval $(eval_args))
$(eval $(call eval_args,$1,\
OBJDIR := $(firstword $($1.OBJDIR) ./objs/$1),\
))
$(eval $(call eval_args,$1,\
objs := $(obj_from_source),
))
$(eval $1 := $($1.TARGET))
TARGETS += $($1)
PHONY_TARGETS += $1
CLEAN_TARGETS += clean_$1
.PHONY: clean_$1
clean_$1:; rm -rf $($1.OBJDIR) $($1)
.PHONY: $1
$1: $($1)
$($1): target:=$1
$($1): $($1.objs); $$(if $$(wildcard $$(@D)),,mkdir -p $$(@D) && )$$(add_target.link)
$($1.objs):; $$(if $$(wildcard $$(@D)),,mkdir -p $$(@D) && )$$(add_target.compile)
$(foreach $1.SOURCES,$($1.SOURCES),$(eval $(obj_from_source): $($1.SOURCES)))
$(info end)
endef
void :=
space := $(void) $(void)
obj_from_source = $(addprefix $($1.OBJDIR)/,$(addsuffix .o,$(basename $(notdir $($1.SOURCES)))))
eval_args = $(foreach i,2 3 4 5 6 7 8 9,$(call eval_arg,$1,$(strip $($i))))
eval_arg = $(if $2,$(info $(space)$(space)$1.$2)$(eval $1.$2))
# Link command line
add_target.link = $(CC) $($(target).LDLAGS) -o $@ $^
# Compile command line
add_target.compile = $(CC) -c -o $@ $($(target).CFLAGS) $<
# -- Directories --
SOURCE := ./src
BIN := ./bin
# Add 'shell' target to the project
$(eval $(call add_target,shell,\
TARGET := $(BIN)/shell,\
SOURCES += ${SOURCE}/execution.c,\
SOURCES += ${SOURCE}/shell.c,\
CFLAGS := -Wall -I./include,\
))
# Add 'ls' target to the project
$(eval $(call add_target,ls,\
TARGET := $(BIN)/ls,\
SOURCES := $(addprefix ${SOURCE}/,execution.c commande_ls.c),\
CFLAGS := -I./include,\
))
all: ${PHONY_TARGETS}
.PHONY: all
clean: | $(CLEAN_TARGETS)
.PHONY: clean
环境:
$ find
.
./include
./include/execution.h
./src
./src/commande_ls.c
./src/execution.c
./src/shell.c
源文件:
$ for f in `find -type f`; do echo $f; cat $f; echo; done
./include/execution.h
void workload();
./src/commande_ls.c
#include <stdio.h>
#include "execution.h"
int main() {
printf("Welcome to ls\n");
workload();
}
./src/execution.c
#include <stdio.h>
#include "execution.h"
void workload() {
printf("Hello from %s\n", __FILE__);
}
./src/shell.c
#include <stdio.h>
#include "execution.h"
int main() {
printf("Welcome to shell\n");
workload();
}
构建所有目标:
$ make -f ../Makefile.sample
add_target(shell)
shell.TARGET := ./bin/shell
shell.SOURCES += ./src/execution.c
shell.SOURCES += ./src/shell.c
shell.CFLAGS := -Wall -I./include
shell.OBJDIR := ./objs/shell
shell.objs := $(obj_from_source)
end
add_target(ls)
ls.TARGET := ./bin/ls
ls.SOURCES := ./src/execution.c ./src/commande_ls.c
ls.CFLAGS := -I./include
ls.OBJDIR := ./objs/ls
ls.objs := $(obj_from_source)
end
mkdir -p objs/shell && cc -c -o objs/shell/execution.o -Wall -I./include src/execution.c
cc -c -o objs/shell/shell.o -Wall -I./include src/shell.c
mkdir -p bin && cc -o bin/shell objs/shell/execution.o objs/shell/shell.o
mkdir -p objs/ls && cc -c -o objs/ls/execution.o -I./include src/execution.c
cc -c -o objs/ls/commande_ls.o -I./include src/commande_ls.c
cc -o bin/ls objs/ls/execution.o objs/ls/commande_ls.o
运行目标:
$ ./bin/ls.exe; ./bin/shell.exe
Welcome to ls
Hello from src/execution.c
Welcome to shell
Hello from src/execution.c
清理ls
并再次构建所有目标(只是为了好玩):
$ make -f ../Makefile.sample clean_ls
add_target(shell)
shell.TARGET := ./bin/shell
shell.SOURCES += ./src/execution.c
shell.SOURCES += ./src/shell.c
shell.CFLAGS := -Wall -I./include
shell.OBJDIR := ./objs/shell
shell.objs := $(obj_from_source)
end
add_target(ls)
ls.TARGET := ./bin/ls
ls.SOURCES := ./src/execution.c ./src/commande_ls.c
ls.CFLAGS := -I./include
ls.OBJDIR := ./objs/ls
ls.objs := $(obj_from_source)
end
rm -rf ./objs/ls ./bin/ls
$ make -f ../Makefile.sample
add_target(shell)
shell.TARGET := ./bin/shell
shell.SOURCES += ./src/execution.c
shell.SOURCES += ./src/shell.c
shell.CFLAGS := -Wall -I./include
shell.OBJDIR := ./objs/shell
shell.objs := $(obj_from_source)
end
add_target(ls)
ls.TARGET := ./bin/ls
ls.SOURCES := ./src/execution.c ./src/commande_ls.c
ls.CFLAGS := -I./include
ls.OBJDIR := ./objs/ls
ls.objs := $(obj_from_source)
end
mkdir -p objs/ls && cc -c -o objs/ls/execution.o -I./include src/execution.c
cc -c -o objs/ls/commande_ls.o -I./include src/commande_ls.c
cc -o bin/ls objs/ls/execution.o objs/ls/commande_ls.o
请注意$(add_target)
函数的方便性。它提供了为您的项目添加尽可能多的目标的方法,而无需愚蠢的代码重复。仍然配置目标构建选项非常灵活。
应该使用GNU Make 3.81及以上版本。享受!