1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
#SPDX-License-Identifier: Apache-2.0
#Copyright 2018-2025 Gliim LLC.
#Licensed under Apache License v2. See LICENSE file.
#On the web http://golf-lang.com/ - this file is part of Golf framework.
#variable names for Golf start with GG_ (GG_C_ being compiling-related) and _ (internal)
#
# Golf make file
#
#
# Setting of build variables
#
SHELL:=/bin/bash
export GG_EXPLAIN
_SYSTEMID:=$(shell $$GG_LIBRARY_PATH/sys showid)
# c/linker flags
_CC=gcc
#ASAN (internal)
ifeq ($(strip $(GG_C_ASAN)),1)
_ASAN=-fsanitize=address -fsanitize-recover=address
else
_ASAN=
endif
ifeq ($(strip $(GG_C_IGNORE_WARN)),1)
GG_IGNORE_WARN=-ignore-warn
else
GG_IGNORE_WARN=
endif
ifeq ($(strip $(GG_C_DEBUG)),1)
_OPTIM_COMP=-g3 -DDEBUG -rdynamic
_OPTIM_LINK=-rdynamic
CFLAGS_WARN_ERROR=-Werror
else
_OPTIM_COMP=-g3 -O3
_OPTIM_LINK=
CFLAGS_WARN_ERROR=
endif
_APPMAKE=-DGG_APPMAKE=1
GG_SERVICE_TARGET=$(GG_BLD)/$(GG_C_NAME).srvc
GG_TARGET=$(GG_BLD)/$(GG_C_NAME)
ifeq ($(strip $(_SYSTEMID)),opensuse)
GG_SERVICE_INCLUDE=-I /usr/include/fastcgi
else
GG_SERVICE_INCLUDE=
endif
#If --single-file is used, then each request handler must be in its own file and own directory as per request path
#Without it, then each .golf file can have any number of request handlers, but they must start with file name, so still organized
ifeq ($(strip $(GG_C_SINGLE_FILE)),1)
GG_SINGLE_FILE=-single-file
else
GG_SINGLE_FILE=
endif
#If --public is used, then all request handlers are publicly accessible unless private
#Without --public, they are all private unless public
ifeq ($(strip $(GG_C_PUBLIC)),1)
GG_PUBLIC_FLAG=-public
else
GG_PUBLIC_FLAG=
endif
#If c-lines is used, then show all diagnostics
GG_DIAG_OUT=
ifeq ($(strip $(GG_C_SKIPLINES)),1)
GG_X_FLAG=-x
else
GG_X_FLAG=
endif
ifeq ($(strip $(GG_C_POSIXREGEX)),1)
GG_POSIXREGEX_FLAG=-DGG_C_POSIXREGEX
else
GG_POSIXREGEX_FLAG=
endif
#even though GG_DIAG_OUT is set to "", at run time it will have value from make_source macro. This is because of how makefile assignments work with = (and not :=)
#ignoring char-subscripts (such as str[str[0]] is fine because golf checks for boundaries
#GG_C_CFLAGS *must* be the last in order to override anything else by user action!
_CFLAGS=-fpic -fmax-errors=$(GG_C_MAXERRORS) $(GG_DIAG_OUT) $(CFLAGS_WARN_ERROR) -Wall -Wno-error=char-subscripts -Wuninitialized -Wmissing-declarations -Wformat -Werror=format-security -Wno-format-zero-length -funsigned-char -fno-semantic-interposition $(GG_MARIADB_USED) $(GG_CURL_USED) $(GG_TREE_USED) $(GG_ARRAY_USED) $(GG_XML_USED) $(GG_PCRE2_USED) $(GG_SERVICE_USED) $(GG_CRYPTO_USED) $(GG_XML_USED) $(GG_MODULES_INCLUDE) $(GG_SERVICE_INCLUDE) $(GG_POSIXREGEX_FLAG) -DGG_ROOT="\"$(GG_ROOT)\"" -I $(CURDIR) -I $(GG_INCLUDE_PATH) -I $(GG_BLD) $(_APPMAKE) $(_OPTIM_COMP) -Wdate-time -fno-stack-protector -fno-stack-clash-protection $(_ASAN) $(GG_C_CFLAGS)
#
# Rules for building
#
all: $(GG_SERVICE_TARGET) $(GG_TARGET)
#clean files. *.golfo is produced by GOLF, the result is generated/object files
clean:
if [ -d "$(GG_BLD)" ]; then find $(GG_BLD)/ -name "*" -type f \( -name "*.o" -or -name "*.c" -or -name "*.h" \) -exec rm -f {} \; ; fi
#include $(GG_BLD)/source.golf
#obtain GG_SOURCE_FILES, GG_SOURCE_C_FILES and GG_HEADER_FILES from generated source.golf
ifneq (clean,$(filter clean,$(MAKECMDGOALS)))
include $(GG_BLD)/source.golf
endif
GG_HEADER_FILES:=$(GG_HEADER_FILES)
#string subst: short for $(patsubst %.golf,%.o,$(GG_SOURCE_FILES)) which finds whitespace-separated word in $(GG_SOURCE_FILES) that match %.golf and replaces them with %.o
#the same for C files in GG_SOURCE_C_FILES
_OBJ_FILES=$(GG_SOURCE_FILES:%.golf=$(GG_BLD)/%.o) $(GG_SOURCE_C_FILES:%.c=$(GG_BLD)/%.oc)
#strip symbols but keep _dbg for when needed (gdb->core or addr2line)
#we have || true (i.e. surpress error in bash, but not error message)
#so as not to stop the build process, as this isn't critical. It really
#happens only if you build against live running server, something that's
#usually only done in testing, and stripping symbols is not a priority.
define strip_sym
if [ "$(GG_C_DEBUG)" != "1" ]; then objcopy --only-keep-debug $@ $@_dbg || true ; objcopy --strip-unneeded $@ || true ; objcopy --add-gnu-debuglink=$@_dbg $@ || true ; fi
endef
#when making source, start with compiling; then if error, check if plain diagnostic (meaning no coloring and using C generated code);
#if not, recompile with error processed by vdiag script to produce highlights (in which
#case we don't use caret, we produce one ourselves instead of gcc)
#use ECODE (as exit code) to make sure non-zero exit code doesn't stop the build rule. Also use basename of the source file in .comperr... in order not to mix up output from different source files when makefile runs in parallel (export GG_ROOT for vdiag)
define make_source
TFILE="$@"; SFILE="$<"; rm -f $(GG_BLD)/.setparam/$${SFILE##*/}.sp; ECODE=0; $(GG_LIBRARY_PATH)/v1 $(GG_X_FLAG) $(GG_PUBLIC_FLAG) $(GG_IGNORE_WARN) $(GG_SINGLE_FILE) -plain-diag "1" -max-errors $(GG_C_MAXERRORS) -name "$(GG_C_NAME)" $< -out $(GG_BLD)/__$${TFILE##*/}.c || ECODE=$$? ; if [ "$$ECODE" != "0" ]; then exit 1; fi ; >$(GG_BLD)/gg_sparam_$${SFILE##*/}.h; if [ -f "$(GG_BLD)/.setparam/$${SFILE##*/}.sp" ]; then for i in $$(cat $(GG_BLD)/.setparam/$${SFILE##*/}.sp|sort -k 1|uniq); do echo "extern gg_num _gg_aprm_$$i;">>$(GG_BLD)/gg_sparam_$${SFILE##*/}.h; done; echo "extern void **_gg_sprm_run; extern gg_num _gg_sprm_run_tot;">>$(GG_BLD)/gg_sparam_$${SFILE##*/}.h ; fi ; GG_DIAG_OUT="" ; ECODE=0 ; rm -f $(GG_BLD)/.comperr.$${TFILE##*/} ; $(_CC) -c $(GG_BLD)/__$${TFILE##*/}.c $(_CFLAGS) -o $@ -I`pwd` 2>$(GG_BLD)/.comperr.$${TFILE##*/} 1>&2 || ECODE="$$?" ; if [ "$$ECODE" != "0" ]; then if [ "$$GG_C_PLAINDIAG" == "1" ]; then cat $(GG_BLD)/.comperr.$${TFILE##*/}; exit -1; else GG_DIAG_OUT="-fno-diagnostics-show-caret"; $(GG_LIBRARY_PATH)/v1 $(GG_X_FLAG) $(GG_PUBLIC_FLAG) $(GG_IGNORE_WARN) $(GG_SINGLE_FILE) -plain-diag "$(GG_C_PLAINDIAG)" -max-errors $(GG_C_MAXERRORS) -name "$(GG_C_NAME)" $< -out $(GG_BLD)/__$${TFILE##*/}.c; ECODE=0 ; $(_CC) -c $(GG_BLD)/__$${TFILE##*/}.c $(_CFLAGS) -o $@ -I`pwd` 2>$(GG_BLD)/.comperr.$${TFILE##*/} 1>&2 || ECODE="$$?" ; export GG_ROOT ; $(GG_LIBRARY_PATH)/vdiag "$(GG_C_NAME)" $(GG_C_PLAINDIAG) < $(GG_BLD)/.comperr.$${TFILE##*/} ; fi ; fi
endef
#the rest if compilation of source files and producing object files and libraries needed for apache,
#do not change these
$(GG_BLD)/gg_dispatch_request.o: $(GG_BLD)/.flatsrc/gg_dispatch_request.c $(GG_INCLUDE_PATH)/golf.h $(GG_HEADER_FILES) $(GG_BLD)/golfapp.h $(GG_BLD)/blds $(_OBJ_FILES)
$(_CC) -c $(GG_BLD)/.flatsrc/gg_dispatch_request.c $(_CFLAGS) -o $@ -I`pwd`
$(GG_BLD)/%.o: $(GG_BLD)/.flatsrc/%.golf $(GG_INCLUDE_PATH)/golf.h $(GG_HEADER_FILES) $(GG_BLD)/golfapp.h $(GG_BLD)/blds
$(call make_source)
$(GG_BLD)/%.oc: %.c $(GG_INCLUDE_PATH)/golf.h $(GG_HEADER_FILES) $(GG_BLD)/golfapp.h $(GG_BLD)/blds
TFILE="$@"; GG_BN=$${TFILE##*/} ; $(_CC) -c $${GG_BN%.*}.c $(_CFLAGS) -o $@ -I`pwd`
#does not need to depend on golfsrvcapp.c because it makes it. There's a dependency on params (blds) and list of files to be made (_OBJ_FILES)
#because now we have hash list there that accounts for all request name. If we didn't have this, adding new .golf file would not be picked up until
#the next next time something changes on the gg command line! /dev/null is used to suppress error message if there are no parameters in project.
$(GG_BLD)/golfsrvcapp.o: $(GG_BLD)/blds $(GG_BLD)/.reqlist $(_OBJ_FILES)
rm -f $(GG_BLD)/gg_sparam.h.new; GG_SPAR_LIST=$$(find $(GG_BLD)/.setparam -type f -name "*" -print0 |xargs -0 cat 2>/dev/null|sort -k 1|uniq); tot_sprm=0; for i in $$GG_SPAR_LIST; do ((tot_sprm=tot_sprm+1)); done; echo "$$tot_sprm" > $(GG_BLD)/.gg_sparam; for i in $$GG_SPAR_LIST; do echo "$$i" >> $(GG_BLD)/.gg_sparam; done; echo "gg_ipar _gg_sprm_par[$$tot_sprm] = {">>$(GG_BLD)/gg_sparam.h.new; j=0; for i in $$GG_SPAR_LIST; do if [ "$$j" != "0" ]; then echo ",">>$(GG_BLD)/gg_sparam.h.new; fi; echo "{.name=\"$$i\", .type=GG_DEFNONE}">>$(GG_BLD)/gg_sparam.h.new; ((j=j+1)); done; echo "};">>$(GG_BLD)/gg_sparam.h.new; j=0; for i in $$GG_SPAR_LIST; do echo "gg_num _gg_aprm_$$i=$$j;">>$(GG_BLD)/gg_sparam.h.new; ((j=j+1)); done; echo "void *_gg_sprm_run[$$j];">>$(GG_BLD)/gg_sparam.h.new; echo "gg_num _gg_sprm_run_tot=$$j;">>$(GG_BLD)/gg_sparam.h.new; _ISDIFF=$$(diff $(GG_BLD)/gg_sparam.h.new $(GG_BLD)/gg_sparam.h 2>/dev/null) || true ; if [[ "$$_ISDIFF" != "" || ! -f $(GG_BLD)/gg_sparam.h ]]; then mv $(GG_BLD)/gg_sparam.h.new $(GG_BLD)/gg_sparam.h ; else rm -rf $(GG_BLD)/gg_sparam.h.new; fi
$(GG_LIBRARY_PATH)/v1 $(GG_X_FLAG) $(GG_PUBLIC_FLAG) $(GG_IGNORE_WARN) $(GG_SINGLE_FILE) -plain-diag "$(GG_C_PLAINDIAG)" -max-errors $(GG_C_MAXERRORS) -main -name "$(GG_C_NAME)" -max-upload "$(GG_C_MAXUPLOAD)" -app-path "$(GG_C_RESTPATH)" -trace "$(GG_C_TRACE)" -out $(GG_BLD)/golfsrvcapp.c
$(_CC) -c $(GG_BLD)/golfsrvcapp.c $(_CFLAGS) -DCMOD -o $@ -I`pwd`
#GG_C_LFLAGS *must* be the last in order to override anything else by user action!
_LFLAGS=-Wl,--no-undefined -Wl,--rpath=$(GG_LIBRARY_PATH) -Wl,--enable-new-dtags -L$(GG_LIBRARY_PATH) $(_OPTIM_LINK) -Wl,-z,relro $(_ASAN) $(GG_C_LFLAGS)
#libs are always specified *after* the object where they're needed. Link flags (including -L) go first.
#$@ is a file generated to hold all input files, and passed to gcc as "in file" via @. Since $@ is already in GG_BLD, can't prefix with $GG_BLD
#as it would be inaccurate (double path). gcc requires file with each item on a single line, hence foreach. This avoids 2-4000 files limit for
#a Golf application, and makes it effectively unlimited.
$(GG_BLD)/$(GG_C_NAME).srvc: $(GG_BLD)/golfsrvcapp.o $(GG_BLD)/gg_dispatch_request.o $(_OBJ_FILES)
$(file >$@.inarg) $(foreach F,$^,$(file >>$@.inarg,$F))
$(_CC) -o $@ @$@.inarg $(_LFLAGS) $(GG_EVENT_STUBS) -lsrvcgolf -lfcgi $(GG_MOD_LIBS) $(GG_MODULES) $(GG_STUBS)
$(call strip_sym)
rm -f $@.inarg
$(GG_BLD)/$(GG_C_NAME): $(GG_BLD)/golfsrvcapp.o $(GG_BLD)/gg_dispatch_request.o $(_OBJ_FILES)
$(file >$@.inarg) $(foreach F,$^,$(file >>$@.inarg,$F))
$(_CC) -o $@ @$@.inarg $(_LFLAGS) $(GG_EVENT_STUBS) -lgolf $(GG_MOD_LIBS) $(GG_MODULES) $(GG_STUBS)
$(call strip_sym)
rm -f $@.inarg
|