1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-15 10:03:22 +03:00
juvix/runtime/Makefile.generic
2023-05-24 12:50:02 +02:00

314 lines
11 KiB
Makefile

# CMakefile: generic automatic Makefile for C and C++
#
# See https://github.com/lukaszcz/cmakefile for the latest version.
#
# Copyright (C) 2008-2022 by Lukasz Czajka.
#
# Distributed under the MIT license. See the bottom of this file.
#
MAKEFILE := $(lastword $(MAKEFILE_LIST))
WORD := [[:graph:]]*[[:space:]][[:space:]]*
CAT_PROJECT := (if [ -f PROJECT ]; then cat PROJECT | sed "s/^\#.*//"; else echo ""; fi)
mstrip = $(patsubst [[:space:]]*%[[:space:]]*,%,$(1))
lsdirs = $(foreach dir,$(2),$(foreach file,$(wildcard $(dir)/*.$(1)),$(file)))
getopt = $(call mstrip,$(shell $(CAT_PROJECT) | sed -n "s/^[[:space:]]*$(1)[[:space:]]*=[[:space:]]*\(.*\)/\1/p"))
getpopt = $(call mstrip,$(foreach cfg,$(1),$(shell $(CAT_PROJECT) | sed -n "s/^[[:space:]]*\($(WORD)\)*$(cfg)[[:space:]][[:space:]]*\($(WORD)\)*$(2)[[:space:]]*=[[:space:]]*\(.*\)/\3/p")))
# build configuration
CONFIG := $(call getopt,CONFIG)
override CONFIG := $(sort $(strip $(subst +, ,$(CONFIG)) $(CONFIG)))
ifeq ($(CONFIG),)
getcopt = $(call getopt,$(1))
getropt = $(call getopt,$(1))
else
getcopt = $(call mstrip,$(call getopt,$(1)) $(call getpopt,$(CONFIG),$(1)))
getropt = $(if $(call getpopt,$(CONFIG),$(1)),$(call getpopt,$(CONFIG),$(1)),$(call getopt,$(1)))
endif
# getcopt gets a concatenable option; getropt a replaceable option
CC := $(call getropt,CC)
ifeq ($(CC),)
CC := gcc
endif
CXX := $(call getropt,CXX)
ifeq ($(CXX),)
CXX := g++
endif
YACC := $(call getropt,YACC)
ifeq ($(YACC),)
YACC := bison
endif
LEX := $(call getropt,LEX)
ifeq ($(LEX),)
LEX := flex
endif
CFLAGS := $(call getcopt,CFLAGS) $(CFLAGS)
CXXFLAGS := $(call getcopt,CXXFLAGS) $(CXXFLAGS)
CDEPFLAGS := $(call getcopt,CDEPFLAGS) $(CDEPFLAGS)
ifeq ($(strip $(CDEPFLAGS)),)
CDEPFLAGS := $(CFLAGS)
endif
CXXDEPFLAGS := $(call getcopt,CXXDEPFLAGS) $(CXXDEPFLAGS)
ifeq ($(strip $(CXXDEPFLAGS)),)
CXXDEPFLAGS := $(CXXFLAGS)
endif
LDFLAGS := $(call getcopt,LDFLAGS) $(LDFLAGS)
CCLDFLAGS := $(call getcopt,CCLDFLAGS) $(LDFLAGS) $(CCLDFLAGS)
CXXLDFLAGS := $(call getcopt,CXXLDFLAGS) $(LDFLAGS) $(CXXLDFLAGS)
YFLAGS := $(call getcopt,YFLAGS) $(YFLAGS)
ifeq ($(strip $(YFLAGS)),)
YFLAGS := -d
endif
LEXFLAGS := $(call getcopt,LEXFLAGS) $(LEXFLAGS)
LIBFLAGS := $(call getcopt,LIBFLAGS) $(LIBFLAGS)
ifeq ($(strip $(LIBFLAGS)),)
LIBFLAGS := -static -o
endif
# source directory
SRCDIR := $(call getropt,SRCDIR)
ifeq ($(SRCDIR),)
SRCDIR := $(shell if [ -d src ]; then echo "src/"; else echo ""; fi)
else
override SRCDIR := $(SRCDIR)/
endif
ifeq ($(SRCDIR),./)
BUILDDIR :=
endif
ifeq ($(SRCDIR),.//)
BUILDDIR :=
endif
ifneq ($(SRCDIR),)
INCLUDES := $(call mstrip,-I$(SRCDIR) $(INCLUDES))
endif
# build directory
BUILDDIR := $(call getropt,BUILDDIR)
ifeq ($(BUILDDIR),)
BUILDDIR := _build/
else
override BUILDDIR := $(BUILDDIR)/
endif
ifeq ($(BUILDDIR),./)
BUILDDIR :=
endif
ifeq ($(BUILDDIR),.//)
BUILDDIR :=
endif
ifneq ($(BUILDDIR),)
INCLUDES := $(call mstrip,-I$(BUILDDIR)$(SRCDIR) $(INCLUDES))
ifeq ($(SRCDIR),)
INCLUDES := $(call mstrip,-I. $(INCLUDES))
endif
endif
# update flags
ifneq ($(INCLUDES),)
CFLAGS := $(INCLUDES) $(CFLAGS)
CXXFLAGS := $(INCLUDES) $(CXXFLAGS)
CDEPFLAGS := $(INCLUDES) $(CDEPFLAGS)
CXXDEPFLAGS := $(INCLUDES) $(CXXDEPFLAGS)
endif
# library to create
LIB := $(call getropt,LIB)
ifneq ($(LIB),)
LIB := $(BUILDDIR)lib$(LIB).a
endif
# programs to create
PROGRAMS := $(patsubst %,$(BUILDDIR)$(SRCDIR)%,$(call getcopt,PROGRAMS))
# subdirectories of the source directory
SUBDIRS := $(call getcopt,SUBDIRS)
override SUBDIRS := $(patsubst %,$(SRCDIR)%,$(SUBDIRS))
# recursive subdirectories of the source directory
RSUBDIRS := $(call getcopt,RSUBDIRS)
override RSUBDIRS := $(patsubst %,$(SRCDIR)%,$(RSUBDIRS))
override SUBDIRS := $(strip $(SUBDIRS) $(foreach dir,$(RSUBDIRS),$(shell find $(dir) -type d)))
# files to ignore
IGNORE := $(patsubst %,$(SRCDIR)%,$(call getcopt,IGNORE))
# source files
YSOURCES := $(filter-out $(IGNORE),$(wildcard $(SRCDIR)*.y) $(call lsdirs,y,$(SUBDIRS)))
LEXSOURCES := $(filter-out $(IGNORE),$(wildcard $(SRCDIR)*.lex) $(call lsdirs,lex,$(SUBDIRS)))
CYSOURCES := $(patsubst %.y,$(BUILDDIR)%.c,$(YSOURCES))
HYSOURCES := $(patsubst %.y,$(BUILDDIR)%.h,$(YSOURCES))
CLEXSOURCES := $(patsubst %.lex,$(BUILDDIR)%.c,$(LEXSOURCES))
CSOURCES := $(filter-out $(IGNORE) $(CYSOURCES) $(CLEXSOURCES),$(strip $(sort $(wildcard $(SRCDIR)*.c) $(call lsdirs,c,$(SUBDIRS)))))
ALLCSOURCES := $(filter-out $(IGNORE),$(strip $(CSOURCES) $(CYSOURCES) $(CLEXSOURCES)))
CPPSOURCES := $(filter-out $(IGNORE),$(strip $(wildcard $(SRCDIR)*.cpp) $(call lsdirs,cpp,$(SUBDIRS))))
CXXSOURCES := $(filter-out $(IGNORE),$(strip $(wildcard $(SRCDIR)*.cxx) $(call lsdirs,cxx,$(SUBDIRS))))
CCSOURCES := $(filter-out $(IGNORE),$(strip $(wildcard $(SRCDIR)*.cc) $(call lsdirs,cc,$(SUBDIRS))))
ALLCPPSOURCES := $(strip $(CPPSOURCES) $(CXXSOURCES) $(CCSOURCES))
# all object files (sort to remove duplicates, which may exist from
# previous builds in a different directory)
COBJECTS := $(sort $(patsubst %.c,$(BUILDDIR)%.o,$(CSOURCES)) $(patsubst %.c,%.o,$(CYSOURCES) $(CLEXSOURCES)))
CPPOBJECTS := $(patsubst %.cpp,$(BUILDDIR)%.o,$(CPPSOURCES))
CXXOBJECTS := $(patsubst %.cxx,$(BUILDDIR)%.o,$(CXXSOURCES))
CCOBJECTS := $(patsubst %.cc,$(BUILDDIR)%.o,$(CCSOURCES))
ALLCPPOBJECTS := $(strip $(CPPOBJECTS) $(CXXOBJECTS) $(CCOBJECTS))
ALLOBJECTS := $(strip $(COBJECTS) $(ALLCPPOBJECTS))
# object files which contain the "main" function
ifneq ($(strip $(CSOURCES)),)
CMAINOBJECTS := $(patsubst %.c,$(BUILDDIR)%.o,$(shell egrep -l '\bint[[:space:]]+main\b' $(CSOURCES)))
else
CMAINOBJECTS :=
endif
ifneq ($(strip $(CPPSOURCES)),)
CPPMAINOBJECTS := $(patsubst %.cpp,$(BUILDDIR)%.o,$(shell egrep -l '\bint[[:space:]]+main\b' $(CPPSOURCES)))
else
CPPMAINOBJECTS :=
endif
ifneq ($(strip $(CXXSOURCES)),)
CXXMAINOBJECTS := $(patsubst %.cxx,$(BUILDDIR)%.o,$(shell egrep -l 'int[[:space:]]+main\b' $(CXXSOURCES)))
else
CXXMAINOBJECTS :=
endif
ifneq ($(strip $(CCSOURCES)),)
CCMAINOBJECTS := $(patsubst %.cxx,$(BUILDDIR)%.o,$(shell egrep -l 'int[[:space:]]+main\b' $(CCSOURCES)))
else
CCMAINOBJECTS :=
endif
ifneq ($(PROGRAMS),)
MAINOBJECTS := $(patsubst %,%.o,$(PROGRAMS))
CPROGRAMS := $(filter $(PROGRAMS),$(patsubst %.o,%,$(COBJECTS)))
CPPPROGRAMS := $(filter $(PROGRAMS),$(patsubst %.o,%,$(ALLCPPOBJECTS)))
else ifneq ($(LIB),)
MAINOBJECTS :=
CPROGRAMS :=
CPPPROGRAMS :=
else
MAINOBJECTS := $(CMAINOBJECTS) $(CPPMAINOBJECTS) $(CXXMAINOBJECTS) $(CCMAINOBJECTS)
CPROGRAMS := $(patsubst %.o,%,$(CMAINOBJECTS))
CPPPROGRAMS := $(patsubst %.o,%,$(CPPMAINOBJECTS)) $(patsubst %.o,%,$(CXXMAINOBJECTS)) $(patsubst %.o,%,$(CCMAINOBJECTS))
PROGRAMS := $(patsubst %.o,%,$(MAINOBJECTS))
endif
# dependencies for each source file
CDEPENDS := $(patsubst %.c,$(BUILDDIR)%.d,$(CSOURCES))
CYLDEPENDS := $(patsubst %.c,%.d,$(CYSOURCES)) $(patsubst %.c,%.d,$(CLEXSOURCES))
CPPDEPENDS := $(patsubst %.cpp,$(BUILDDIR)%.d,$(CPPSOURCES))
CXXDEPENDS := $(patsubst %.cxx,$(BUILDDIR)%.d,$(CXXSOURCES))
CCDEPENDS := $(patsubst %.cc,$(BUILDDIR)%.d,$(CCSOURCES))
DEPENDS := $(sort $(CDEPENDS) $(CYLDEPENDS) $(CPPDEPENDS) $(CXXDEPENDS) $(CCDEPENDS))
# object files which don't include the "main" function
OBJECTS := $(filter-out $(MAINOBJECTS),$(ALLOBJECTS))
# linkers
CCLD := $(call getropt,CCLD)
ifeq ($(CCLD),)
ifeq ($(ALLCPPSOURCES),)
CCLD := $(CC)
else
CCLD := $(CXX)
endif
endif
CXXLD := $(call getropt,CXXLD)
ifeq ($(CXXLD),)
CXXLD := $(CXX)
endif
LIBTOOL := $(call getropt,LIBTOOL)
ifeq ($(LIBTOOL),)
LIBTOOL := libtool
endif
ifneq ($(BUILDDIR),)
$(shell mkdir -p $(BUILDDIR))
$(shell mkdir -p $(BUILDDIR)$(SRCDIR))
$(foreach dir,$(patsubst %,$(BUILDDIR)%,$(SUBDIRS)),$(shell mkdir -p $(dir)))
endif
.PHONY: all depend clean
all: $(DEPENDS) $(OBJECTS) $(PROGRAMS) $(LIB)
depend: $(DEPENDS)
$(HYSOURCES) : $(BUILDDIR)%.h : %.y
$(YACC) $(YFLAGS) -o $(patsubst %.h,%.c,$@) $<
$(CYSOURCES) : $(BUILDDIR)%.c : %.y
$(YACC) $(YFLAGS) -o $@ $<
$(CLEXSOURCES) : $(BUILDDIR)%.c : %.lex
$(LEX) $(LEXFLAGS) -o $@ $<
$(CDEPENDS) : $(BUILDDIR)%.d : %.c
$(CC) $(CDEPFLAGS) -MM -MT $(patsubst %.c,$(BUILDDIR)%.o,$<) $< > $@
printf "\t$(CC) -c $(CFLAGS) -o $(patsubst %.c,$(BUILDDIR)%.o,$<) $<\n" >> $@
$(CYLDEPENDS) : $(BUILDDIR)%.d : $(BUILDDIR)%.c
$(CC) $(CDEPFLAGS) -MM -MT $(patsubst %.c,%.o,$<) $< > $@
printf "\t$(CC) -c $(CFLAGS) -o $(patsubst %.c,%.o,$<) $<\n" >> $@
$(CPPDEPENDS) : $(BUILDDIR)%.d : %.cpp
$(CXX) $(CXXDEPFLAGS) -MM -MT $(patsubst %.cpp,$(BUILDDIR)%.o,$<) $< > $@
printf "\t$(CXX) -c $(CXXFLAGS) -o $(patsubst %.cpp,$(BUILDDIR)%.o,$<) $<\n" >> $@
$(CXXDEPENDS) : $(BUILDDIR)%.d : %.cxx
$(CXX) $(CXXDEPFLAGS) -MM -MT $(patsubst %.cxx,$(BUILDDIR)%.o,$<) $< > $@
printf "\t$(CXX) -c $(CXXFLAGS) -o $(patsubst %.cxx,$(BUILDDIR)%.o,$<) $<\n" >> $@
$(CCDEPENDS) : $(BUILDDIR)%.d : %.cc
$(CXX) $(CXXDEPFLAGS) -MM -MT $(patsubst %.cc,$(BUILDDIR)%.o,$<) $< > $@
printf "\t$(CXX) -c $(CXXFLAGS) -o $(patsubst %.cc,$(BUILDDIR)%.o,$<) $<\n" >> $@
$(CPROGRAMS) : % : $(ALLOBJECTS)
$(CCLD) -o $@ $@.o $(OBJECTS) $(CCLDFLAGS)
$(CPPPROGRAMS) : % : $(ALLOBJECTS)
$(CXXLD) -o $@ $@.o $(OBJECTS) $(CXXLDFLAGS)
$(LIB) : % : $(OBJECTS)
$(LIBTOOL) $(LIBFLAGS) $@ $(OBJECTS)
-include $(DEPENDS)
clean:
-rm -f $(PROGRAMS) $(ALLOBJECTS) $(DEPENDS) $(LIB) $(CYSOURCES) $(HYSOURCES) $(CLEXSOURCES)
ifneq ($(wildcard $(BUILDDIR).prjconfig),)
-rm $(BUILDDIR).prjconfig
endif
ifneq ($(BUILDDIR),)
-rm -rf $(BUILDDIR)
endif
ifneq ($(wildcard PROJECT),)
$(MAKEFILE): $(DEPENDS) $(BUILDDIR).prjconfig
$(BUILDDIR).prjconfig: PROJECT
-rm -f $(PROGRAMS) $(ALLOBJECTS) $(DEPENDS) $(LIB) $(CYSOURCES) $(HYSOURCES) $(CLEXSOURCES)
touch $(BUILDDIR).prjconfig
else
$(MAKEFILE): $(DEPENDS)
endif
ifneq ($(wildcard Makefile-include),)
include Makefile-include
endif
# Copyright (c) 2008-2022 by Lukasz Czajka.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.