Automatic rules rulez! (for things like .o files)

- This update also allowed to have a somewhat cleaner
	  support for building libraries. (because the code to generate
	  the rules for the .o files is common, uh)
	- Such automatic rules are hidden from the Makefiles’ “help”
	  message, as they previously were.
	- subdirs are expected to have been broken.

I should really write a real tool to do this job. In, say, C, maybe?
This commit is contained in:
Luka Vandervelden 2015-04-06 22:42:56 +02:00
parent dd63cd87e1
commit f30e64e604
5 changed files with 142 additions and 70 deletions

View File

@ -19,7 +19,7 @@ build.zsh:
build.zsh.install: build.zsh build.zsh.install: build.zsh
@echo ' [IN] $(BINDIR)/build.zsh' @echo ' [IN] $(BINDIR)/build.zsh'
$(Q)mkdir -p '$(DESTDIR)$(BINDIR)/build.zsh' $(Q)mkdir -p '$(DESTDIR)$(BINDIR)'
$(Q)install -m0755 build.zsh $(DESTDIR)$(BINDIR)/build.zsh $(Q)install -m0755 build.zsh $(DESTDIR)$(BINDIR)/build.zsh
build.zsh.clean: build.zsh.clean:
@ -74,6 +74,8 @@ $(PACKAGE)-$(VERSION).tar.gz: distdir
@echo ' [TAR] $(PACKAGE)-$(VERSION).tar.gz' @echo ' [TAR] $(PACKAGE)-$(VERSION).tar.gz'
$(Q)tar czf $(PACKAGE)-$(VERSION).tar.gz \ $(Q)tar czf $(PACKAGE)-$(VERSION).tar.gz \
$(PACKAGE)-$(VERSION)/build/binary.zsh \ $(PACKAGE)-$(VERSION)/build/binary.zsh \
$(PACKAGE)-$(VERSION)/build/library.zsh \
$(PACKAGE)-$(VERSION)/build/ofile.zsh \
$(PACKAGE)-$(VERSION)/build/script.zsh \ $(PACKAGE)-$(VERSION)/build/script.zsh \
$(PACKAGE)-$(VERSION)/project.zsh \ $(PACKAGE)-$(VERSION)/project.zsh \
$(PACKAGE)-$(VERSION)/Makefile $(PACKAGE)-$(VERSION)/Makefile
@ -83,6 +85,8 @@ $(PACKAGE)-$(VERSION).tar.xz: distdir
@echo ' [TAR] $(PACKAGE)-$(VERSION).tar.xz' @echo ' [TAR] $(PACKAGE)-$(VERSION).tar.xz'
$(Q)tar cJf $(PACKAGE)-$(VERSION).tar.xz \ $(Q)tar cJf $(PACKAGE)-$(VERSION).tar.xz \
$(PACKAGE)-$(VERSION)/build/binary.zsh \ $(PACKAGE)-$(VERSION)/build/binary.zsh \
$(PACKAGE)-$(VERSION)/build/library.zsh \
$(PACKAGE)-$(VERSION)/build/ofile.zsh \
$(PACKAGE)-$(VERSION)/build/script.zsh \ $(PACKAGE)-$(VERSION)/build/script.zsh \
$(PACKAGE)-$(VERSION)/project.zsh \ $(PACKAGE)-$(VERSION)/project.zsh \
$(PACKAGE)-$(VERSION)/Makefile $(PACKAGE)-$(VERSION)/Makefile
@ -92,6 +96,8 @@ $(PACKAGE)-$(VERSION).tar.bz2: distdir
@echo ' [TAR] $(PACKAGE)-$(VERSION).tar.bz2' @echo ' [TAR] $(PACKAGE)-$(VERSION).tar.bz2'
$(Q)tar cjf $(PACKAGE)-$(VERSION).tar.bz2 \ $(Q)tar cjf $(PACKAGE)-$(VERSION).tar.bz2 \
$(PACKAGE)-$(VERSION)/build/binary.zsh \ $(PACKAGE)-$(VERSION)/build/binary.zsh \
$(PACKAGE)-$(VERSION)/build/library.zsh \
$(PACKAGE)-$(VERSION)/build/ofile.zsh \
$(PACKAGE)-$(VERSION)/build/script.zsh \ $(PACKAGE)-$(VERSION)/build/script.zsh \
$(PACKAGE)-$(VERSION)/project.zsh \ $(PACKAGE)-$(VERSION)/project.zsh \
$(PACKAGE)-$(VERSION)/Makefile $(PACKAGE)-$(VERSION)/Makefile

View File

@ -7,6 +7,7 @@
# it were cleaner, more readable and somewhat more documented. # it were cleaner, more readable and somewhat more documented.
# - Using subdirs creates trouble. Really. Dont do it unless its for # - Using subdirs creates trouble. Really. Dont do it unless its for
# completely separate, independent sub-projects. # completely separate, independent sub-projects.
# Also, theyre unmaintained and probably broken by now.
# #
# WARNINGS and LIMITATIONS: # WARNINGS and LIMITATIONS:
# - Using a relative path in DESTDIR= *will* fail. # - Using a relative path in DESTDIR= *will* fail.
@ -162,7 +163,7 @@ done
function main { function main {
typeset -a prefixes directories typeset -a prefixes directories
typeset -A ldflags cflags sources type depends install typeset -A ldflags cflags sources type depends install auto
prefixes=( prefixes=(
PREFIX '/usr/local' PREFIX '/usr/local'
@ -229,57 +230,60 @@ function main {
write "\n\t@:\n" write "\n\t@:\n"
fi fi
for target in ${targets[@]}; do local target_index=1
( while (($target_index <= ${#targets[@]})); do
typeset -a src local target="${targets[$target_index]}"
src=($(echo ${sources[$target]}))
local installdir="${install[$target]}"
if exists "${type[$target]}.build"; then typeset -a src
${type[$target]}.build src=($(echo ${sources[$target]}))
else local installdir="${install[$target]}"
if ! exists "${type[$target]}.test"; then
error "No predefined rule for the following type: ${type[$target]}" if exists "${type[$target]}.build"; then
error " (expect trouble, nothings gonna work!)" ${type[$target]}.build
fi else
if ! exists "${type[$target]}.test"; then
error "No predefined rule for the following type: ${type[$target]}"
error " (expect trouble, nothings gonna work!)"
fi fi
fi
if exists "${type[$target]}.install"; then if exists "${type[$target]}.install"; then
${type[$target]}.install ${type[$target]}.install
else
if [[ -z "${installdir}" ]]; then
error "No install[${type[${target}]}] and no default installation directory."
error "Your “install” rule will be broken!"
else else
if [[ -z "${installdir}" ]]; then write "${target}.install: \$(DESTDIR)${installdir}"
error "No install[${type[${target}]}] and no default installation directory." write "\t@echo '$(IN ${installdir}/${target})'"
error "Your “install” rule will be broken!" write "\t${Q}install -m755 $target \$(DESTDIR)${installdir}/$target"
else
write "${target}.install: \$(DESTDIR)${installdir}"
write "\t@echo '$(IN ${installdir}/${target})'"
write "\t${Q}install -m755 $target \$(DESTDIR)${installdir}/$target"
write
fi
fi
if exists "${type[$target]}.clean"; then
${type[$target]}.clean
else
write "${target}.clean:"
write "\t@echo '$(RM ${target})'"
write "\t${Q}rm -f ${target}"
write write
fi fi
fi
if exists "${type[$target]}.uninstall"; then if exists "${type[$target]}.clean"; then
${type[$target]}.uninstall ${type[$target]}.clean
else else
write "${target}.uninstall:" write "${target}.clean:"
write "\t@echo '$(RM "${installdir}/${target}")'" write "\t@echo '$(RM ${target})'"
write "\t${Q}rm -f '\$(DESTDIR)${installdir}/${target}'" write "\t${Q}rm -f ${target}"
write write
fi fi
if exists "${type[$target]}.test"; then if exists "${type[$target]}.uninstall"; then
${type[$target]}.test ${type[$target]}.uninstall
fi else
) write "${target}.uninstall:"
write "\t@echo '$(RM "${installdir}/${target}")'"
write "\t${Q}rm -f '\$(DESTDIR)${installdir}/${target}'"
write
fi
if exists "${type[$target]}.test"; then
${type[$target]}.test
fi
((target_index++))
done done
for dir in ${directories[@]}; do for dir in ${directories[@]}; do
@ -428,7 +432,9 @@ function main {
write " @echo ''" write " @echo ''"
write " @echo '${fg_bold[white]}Project targets: ${reset_color}'" write " @echo '${fg_bold[white]}Project targets: ${reset_color}'"
for T in ${targets[@]}; do for T in ${targets[@]}; do
printf " @echo ' - ${fg_bold[yellow]}%-14s${fg[white]}${type[$T]}${reset_color}'\n" "$T" >> $Makefile if [[ "${auto[$T]}" != true ]]; then
printf " @echo ' - ${fg_bold[yellow]}%-14s${fg[white]}${type[$T]}${reset_color}'\n" "$T" >> $Makefile
fi
done done
write " @echo ''" write " @echo ''"

View File

@ -12,22 +12,10 @@ function binary.build {
write write
for i in ${src[@]}; do for i in ${src[@]}; do
local dirname="$(dirname "$i")" targets+=("${i%.c}.o")
type[${i%.c}.o]=ofile
write -n "${i%.c}.o: ${i}" auto[${i%.c}.o]=true
cflags[${i%.c}.o]="${cflags[$target]}"
sed '/^#include "/!d;s/^#include "//;s/"$//' $i | while read h; do
h="$dirname/$h"
write -n " $h"
done
write
write "\t@echo '$(CC ${i%.c}.o)'"
write -n "\t$Q\$(CC) \$(CFLAGS) ${cflags[$target]} -c ${i} "
write -n " ${cflags[$target]}"
write " -o ${i%.c}.o"
write
done done
} }
@ -35,7 +23,7 @@ function binary.install {
local install="${install[$target]:-\$(BINDIR)}" local install="${install[$target]:-\$(BINDIR)}"
write "${target}.install: ${target}" write "${target}.install: ${target}"
write "\t@echo '$(IN "${install}/${target}")'" write "\t@echo '$(IN "${install}/${target}")'"
write "\t${Q}mkdir -p '\$(DESTDIR)${install}/${target}'" write "\t${Q}mkdir -p '\$(DESTDIR)${install}'"
write "\t${Q}install -m0755 ${target} \$(DESTDIR)${install}/${target}" write "\t${Q}install -m0755 ${target} \$(DESTDIR)${install}/${target}"
write write
} }
@ -53,12 +41,5 @@ function binary.clean {
write "\t@echo '$(RM ${target})'" write "\t@echo '$(RM ${target})'"
write "\t${Q}rm -f ${target}" write "\t${Q}rm -f ${target}"
write write
for i in ${src[@]}; do
write "${i%.c}.o.clean:"
write "\t@echo '$(RM ${i%.c}.o)'"
write "\t${Q}rm -f ${i%.c}.o"
write
done
} }

45
build/library.zsh Normal file
View File

@ -0,0 +1,45 @@
function library.build {
write -n "${target}:"
for i in ${src[@]}; do
write -n " ${i%.*}.o"
done
write " ${depends[$target]}"
write "\t@echo '$(LD ${target})'"
write -n "\t$Q\$(CC) -o ${target} -shared \$(LDFLAGS)"
write -n " ${src[@]//.c/.o}"
write " ${ldflags[$target]}"
write
for i in ${src[@]}; do
targets+=("${i%.c}.o")
type[${i%.c}.o]=ofile
auto[${i%.c}.o]=true
cflags[${i%.c}.o]="-fPIC ${cflags[$target]}"
done
}
function library.install {
local install="${install[$target]:-\$(LIBDIR)}"
write "${target}.install: ${target}"
write "\t@echo '$(IN "${install}/${target}")'"
write "\t${Q}mkdir -p '\$(DESTDIR)${install}'"
write "\t${Q}install -m0755 ${target} \$(DESTDIR)${install}/${target}"
write
}
function library.uninstall {
local install="${install[$target]:-\$(LIBDIR)}"
write "${target}.uninstall:"
write "\t@echo '$(RM ${install}/${target})'"
write "\t${Q}rm -f '\$(DESTDIR)${install}/${target}'"
write
}
function library.clean {
write "${target}.clean:"
write "\t@echo '$(RM ${target})'"
write "\t${Q}rm -f ${target}"
write
}

34
build/ofile.zsh Normal file
View File

@ -0,0 +1,34 @@
function ofile.build {
local dirname="$(dirname "$target")"
write -n "${target}: ${target%.o}.c"
sed '/^#include "/!d;s/^#include "//;s/"$//' "${target%.o}.c" | \
while read h; do
h="$dirname/$h"
write -n " $h"
done
write
write "\t@echo '$(CC ${target})'"
write -n "\t$Q\$(CC) \$(CFLAGS) ${cflags[$target]} -c ${target%.o}.c "
write -n " ${cflags[$target]}"
write " -o ${target}"
write
}
function ofile.install {
write "${target}.install:"
write
}
function ofile.uninstall {
write "${target}.uninstall:"
write
}
function ofile.clean {
binary.clean "$@"
}