#
# Copyright (C) 2026 Linux Studio Plugins Project <https://lsp-plug.in/>
#           (C) 2026 Vladimir Sadovnikov <sadko4u@gmail.com>
#
# This file is part of lsp-3rd-party
#
# lsp-3rd-party is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# lsp-3rd-party is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with lsp-3rd-party.  If not, see <https://www.gnu.org/licenses/>.
#
ifneq ($(VERBOSE),1)
.SILENT:
endif

BASEDIR                    := $(CURDIR)
ROOTDIR                    := $(CURDIR)
BUILD_FEATURES              = $(sort $(call subtraction,$(SUB_FEATURES),$(if $(FEATURES),$(FEATURES),$(DEFAULT_FEATURES)) $(ADD_FEATURES)))           

# Configure system settings
include $(BASEDIR)/project.mk
include $(BASEDIR)/make/functions.mk
include $(BASEDIR)/make/system.mk
include $(BASEDIR)/make/paths.mk
include $(BASEDIR)/make/tools.mk
include $(BASEDIR)/modules.mk
include $(BASEDIR)/dependencies.mk

ifeq ($(call fcheck,devel,$(BUILD_FEATURES),ON),ON)
  X_URL_SUFFIX                = _RW
else
  X_URL_SUFFIX                = _RO
endif

# Compute the full list of dependencies
MERGED_DEPENDENCIES        := \
  $(DEPENDENCIES) \
  $(TEST_DEPENDENCIES)
UNIQ_MERGED_DEPENDENCIES   := $(call uniq, $(MERGED_DEPENDENCIES))
DEPENDENCIES                = $(UNIQ_MERGED_DEPENDENCIES)

# Determine versions
ifeq ($(findstring -devel,$(ARTIFACT_VERSION)),-devel)
  $(foreach dep, $(DEPENDENCIES), \
    $(eval $(dep)_BRANCH=devel) \
  )
  # Strip '-devel' from version
  tmp_version :=$(shell echo "$(ARTIFACT_VERSION)" | sed s/-devel//g)
  ARTIFACT_VERSION=$(tmp_version)
else
  $(foreach dep,$(DEPENDENCIES),\
    $(eval $(dep)_BRANCH="$($(dep)_VERSION)") \
  )
endif

define pkgconfig =
  $(eval name=$(1))
  
  $(if $($(name)_NAME), \
    $(if $($(name)_CFLAGS),,       $(eval $(name)_CFLAGS       := $(shell $(PKG_CONFIG)      --cflags "$($(name)_NAME)"))) \
    $(if $($(name)_LDFLAGS),,      $(eval $(name)_LDFLAGS      := $(shell $(PKG_CONFIG)      --libs "$($(name)_NAME)"))) \
    \
    $(if $(HOST_$(name)_CFLAGS),,  $(eval HOST_$(name)_CFLAGS  := $(shell $(HOST_PKG_CONFIG) --cflags "$($(name)_NAME)"))) \
    $(if $(HOST_$(name)_LDFLAGS),, $(eval HOST_$(name)_LDFLAGS := $(shell $(HOST_PKG_CONFIG) --libs "$($(name)_NAME)"))) \
  )
  
  $(if $($(name)_OBJ),,          $(eval $(name)_OBJ      :=))
  $(if $(HOST_$(name)_OBJ),,     $(eval HOST_$(name)_OBJ :=))
endef

define libconfig =
  $(eval name=$(1))
  
  $(if $($(name)_NAME), \
    $(if $($(name)_LDFLAGS),,      $(eval $(name)_LDFLAGS      := -l$($(name)_NAME))) \
    \
    $(if $(HOST_$(name)_LDFLAGS),, $(eval HOST_$(name)_LDFLAGS := -l$($(name)_NAME))) \
  )
  
  $(if $($(name)_OBJ),,          $(eval $(name)_OBJ      :=))
  $(if $(HOST_$(name)_OBJ),,     $(eval HOST_$(name)_OBJ :=))
endef

define optconfig =
  $(eval name=$(1))
  
  $(if $($(name)_NAME), \
    $(if $(HOST_$(name)_LDFLAGS),, $(eval HOST_$(name)_LDFLAGS := $($(name)_LDFLAGS))) \
  )
  
  $(if $($(name)_OBJ),,          $(eval $(name)_OBJ      :=))
  $(if $(HOST_$(name)_OBJ),,     $(eval HOST_$(name)_OBJ :=))
endef

define _modconfig =
  $(eval name=$(1))
  $(eval publisher=$(2))
  
  $(if $($(name)_DESC),,         $(eval $(name)_DESC         := $($(name)_DESC)))
  $(if $($(name)_URL),,          $(eval $(name)_URL          := $($(name)_URL$(X_URL_SUFFIX))))
  
  $(if $($(name)_PATH),,         $(eval $(name)_PATH         := $(MODULES)/$($(name)_NAME)))
  $(if $($(name)_INC),,          $(eval $(name)_INC          := $($(name)_PATH)/include))
  $(if $($(name)_SRC),,          $(eval $(name)_SRC          := $($(name)_PATH)/src))
  $(if $($(name)_TEST),,         $(eval $(name)_TEST         := $($(name)_PATH)/test))
  $(if $($(name)_TESTING),,      $(eval $(name)_TESTING      := 0))
  $(if $($(name)_BIN),,          $(eval $(name)_BIN          := $(TARGET_BUILDDIR)/$($(name)_NAME)))
  $(if $($(name)_CFLAGS),,       $(eval $(name)_CFLAGS       := "$(if $($(name)_INC_OPT),$($(name)_INC_OPT) ,-I )\"$($(name)_INC)\"" -D$(name)_BUILTIN$(if $(publisher), -D$(name)_PUBLISHER)))
  $(if $($(name)_LDFLAGS),,      $(eval $(name)_LDFLAGS      :=))
  $(if $($(name)_OBJ),,          $(eval $(name)_OBJ          := "$($(name)_BIN)/$($(name)_NAME).o"))
  $(if $($(name)_OBJ_TEST),,     $(eval $(name)_OBJ_TEST     := "$($(name)_BIN)/$($(name)_NAME)-test.o"))
  $(if $($(name)_MFLAGS),,       $(eval $(name)_MFLAGS       := $(if $(publisher),,"-D$(name)_BUILTIN -fvisibility=hidden")))
  
  $(if $(HOST_$(name)_NAME),,    $(eval HOST_$(name)_NAME    := $($(name)_NAME)))
  $(if $(HOST_$(name)_DESC),,    $(eval HOST_$(name)_DESC    := $($(name)_DESC)))
  $(if $(HOST_$(name)_URL),,     $(eval HOST_$(name)_URL     := $($(name)_URL$(X_URL_SUFFIX))))
  
  $(if $(HOST_$(name)_PATH),,    $(eval HOST_$(name)_PATH    := $(MODULES)/$($(name)_NAME)))
  $(if $(HOST_$(name)_INC),,     $(eval HOST_$(name)_INC     := $(HOST_$(name)_PATH)/include))
  $(if $(HOST_$(name)_SRC),,     $(eval HOST_$(name)_SRC     := $(HOST_$(name)_PATH)/src))
  $(if $(HOST_$(name)_TEST),,    $(eval HOST_$(name)_TEST    := $(HOST_$(name)_PATH)/test))
  $(if $(HOST_$(name)_TESTING),, $(eval HOST_$(name)_TESTING := 0))
  $(if $(HOST_$(name)_BIN),,     $(eval HOST_$(name)_BIN     := $(HOST_BUILDDIR)/$($(name)_NAME)))
  $(if $(HOST_$(name)_CFLAGS),,  $(eval HOST_$(name)_CFLAGS  := "$(if $($(name)_INC_OPT),$($(name)_INC_OPT) ,-I )\"$($(name)_INC)\"" -D$(name)_BUILTIN$(if $(publisher), -D$(name)_PUBLISHER)))
  $(if $(HOST_$(name)_LDFLAGS),, $(eval HOST_$(name)_LDFLAGS :=))
  $(if $(HOST_$(name)_OBJ),,     $(eval HOST_$(name)_OBJ     := "$(HOST_$(name)_BIN)/$($(name)_NAME).o"))
  $(if $(HOST_$(name)_OBJ_TEST),,$(eval HOST_$(name)_OBJ_TEST:= "$(HOST_$(name)_BIN)/$($(name)_NAME)-test.o"))
  $(if $(HOST_$(name)_MFLAGS),,  $(eval HOST_$(name)_MFLAGS  := $(if $(publisher),,"-D$(name)_BUILTIN -fvisibility=hidden")))
endef

define srcconfig =
  $(eval name=$(1))
  $(eval publisher=$(findstring $(ARTIFACT_NAME),$($(name)_NAME)))
  $(eval $(call _modconfig,$(name),$(publisher)))
endef 

define binconfig =
  $(eval name=$(1))
  $(eval publisher=1)
  $(eval $(call _modconfig,$(name),$(publisher)))
endef

define hdrconfig =
  $(eval name=$(1))
  $(eval publisher=$(findstring $(ARTIFACT_NAME),$($(name)_NAME)))
  
  $(if $($(name)_DESC),,         $(eval $(name)_DESC         := $($(name)_DESC)))
  $(if $($(name)_URL),,          $(eval $(name)_URL          := $($(name)_URL$(X_URL_SUFFIX))))
  
  $(if $($(name)_PATH),,         $(eval $(name)_PATH         := $(MODULES)/$($(name)_NAME)))
  $(if $($(name)_INC),,          $(eval $(name)_INC          := $($(name)_PATH)/include))
  $(if $($(name)_TESTING),,      $(eval $(name)_TESTING      := 0))
  $(if $($(name)_CFLAGS),,       $(eval $(name)_CFLAGS       := "$(if $($(name)_INC_OPT),$($(name)_INC_OPT) ,-I )\"$($(name)_INC)\""$(if $(publisher), "-D$(name)_PUBLISHER")))
  $(if $($(name)_MFLAGS),,       $(eval $(name)_MFLAGS       := "-D$(name)_BUILTIN -fvisibility=hidden"))

  $(if $(HOST_$(name)_NAME),,    $(eval HOST_$(name)_NAME    := $($(name)_NAME)))
  $(if $(HOST_$(name)_DESC),,    $(eval HOST_$(name)_DESC    := $($(name)_DESC)))
  $(if $(HOST_$(name)_URL),,     $(eval HOST_$(name)_URL     := $($(name)_URL$(X_URL_SUFFIX))))
  
  $(if $(HOST_$(name)_PATH),,    $(eval HOST_$(name)_PATH    := $(MODULES)/$($(name)_NAME)))
  $(if $(HOST_$(name)_INC),,     $(eval HOST_$(name)_INC     := $(HOST_$(name)_PATH)/include))
  $(if $(HOST_$(name)_TESTING),, $(eval HOST_$(name)_TESTING := 0))
  $(if $(HOST_$(name)_CFLAGS),,  $(eval HOST_$(name)_CFLAGS  := "$(if $($(name)_INC_OPT),$($(name)_INC_OPT) ,-I )\"$(HOST_$(name)_INC)\""$(if $(publisher), "-D$(name)_PUBLISHER")))
  $(if $(HOST_$(name)_MFLAGS),,  $(eval HOST_$(name)_MFLAGS  := "-D$(name)_BUILTIN -fvisibility=hidden"))
endef

define vardef =
  $(eval name = $(1))
  # Override variables if they are not defined
  $(if $(findstring pkg,$($(name)_TYPE)), $(eval $(call pkgconfig, $(name))))
  $(if $(findstring src,$($(name)_TYPE)), $(eval $(call srcconfig, $(name))))
  $(if $(findstring hdr,$($(name)_TYPE)), $(eval $(call hdrconfig, $(name))))
  $(if $(findstring lib,$($(name)_TYPE)), $(eval $(call libconfig, $(name))))
  $(if $(findstring bin,$($(name)_TYPE)), $(eval $(call binconfig, $(name))))
  $(if $(findstring opt,$($(name)_TYPE)), $(eval $(call optconfig, $(name))))
endef

# Define predefined variables
ifndef ARTIFACT_TYPE
  ARTIFACT_TYPE              := src
endif

ifndef $(ARTIFACT_ID)_NAME
  $(ARTIFACT_ID)_NAME        := $(ARTIFACT_NAME)
endif
ifndef $(ARTIFACT_ID)_TYPE
  $(ARTIFACT_ID)_TYPE        := $(ARTIFACT_TYPE)
endif
ifndef $(ARTIFACT_ID)_DESC
  $(ARTIFACT_ID)_DESC        := $(ARTIFACT_DESC)
endif
ifndef $(ARTIFACT_ID)_VERSION 
  $(ARTIFACT_ID)_VERSION     := $(ARTIFACT_VERSION)
endif
ifndef $(ARTIFACT_ID)_PATH
  $(ARTIFACT_ID)_PATH        := $(BASEDIR)
endif
ifndef HOST_$(ARTIFACT_ID)_PATH
  HOST_$(ARTIFACT_ID)_PATH   := $(BASEDIR)
endif

ROOT_ARTIFACT_ID           := $(ARTIFACT_ID)
$(ARTIFACT_ID)_TESTING      = $(call fcheck,test,$(BUILD_FEATURES),1,0)

OVERALL_DEPS := $(call uniq,$(DEPENDENCIES) $(ARTIFACT_ID))
override __tmp := $(foreach dep,$(OVERALL_DEPS),$(call vardef, $(dep)))

CONFIG_VARS = \
  $(PATH_VARS) \
  $(COMMON_VARS) \
  $(TOOL_VARS) \
  $(foreach name, $(OVERALL_DEPS), \
    $(name)_NAME \
    $(name)_DESC \
    $(name)_VERSION \
    $(name)_TYPE \
    $(name)_URL \
    $(name)_BRANCH \
    \
    $(name)_PATH \
    $(name)_INC \
    $(name)_SRC \
    $(name)_TEST \
    $(name)_TESTING \
    $(name)_BIN \
    $(name)_CFLAGS \
    $(name)_MFLAGS \
    $(name)_LDFLAGS \
    $(name)_OBJ \
    $(name)_OBJ_TEST \
    \
    HOST_$(name)_NAME \
    HOST_$(name)_DESC \
    HOST_$(name)_PATH \
    HOST_$(name)_INC \
    HOST_$(name)_SRC \
    HOST_$(name)_TEST \
    HOST_$(name)_TESTING \
    HOST_$(name)_BIN \
    HOST_$(name)_CFLAGS \
    HOST_$(name)_MFLAGS \
    HOST_$(name)_LDFLAGS \
    HOST_$(name)_OBJ \
    HOST_$(name)_OBJ_TEST \
  )

.DEFAULT_GOAL      := config
.PHONY: config prepare help
.PHONY: $(CONFIG_VARS)

prepare:
	echo "Configuring build..."
	echo "# Project settings" > "$(CONFIG)"

$(CONFIG_VARS): prepare
	echo "$(@)=$($(@))" >> "$(CONFIG)"

config: $(CONFIG_VARS)
	echo "Platform:          $(PLATFORM)"
	echo "Host architecture: $(HOST_ARCHITECTURE_FAMILY)/$(HOST_ARCHITECTURE) ($(HOST_ARCHITECTURE_CFLAGS))"
	echo "Architecture:      $(ARCHITECTURE_FAMILY)/$(ARCHITECTURE) ($(ARCHITECTURE_CFLAGS))"
	echo "Features:          $(BUILD_FEATURES)"
	echo "Configured OK"

help: | pathvars toolvars sysvars
	echo ""
	echo "List of variables for each dependency:"
	echo "  <ARTIFACT>_BIN            location to put all binaries when building artifact"
	echo "  <ARTIFACT>_BRANCH         git branch used to checkout source code"
	echo "  <ARTIFACT>_CFLAGS         C/C++ flags to access headers of the artifact"
	echo "  <ARTIFACT>_DESC           Full description of the artifact"
	echo "  <ARTIFACT>_INC            path to include files of the artifact"
	echo "  <ARTIFACT>_LDFLAGS        linker flags to link with artifact"
	echo "  <ARTIFACT>_MFLAGS         artifact-specific compilation flags"
	echo "  <ARTIFACT>_NAME           the artifact name used in pathnames"
	echo "  <ARTIFACT>_OBJ            path to output object file for artifact"
	echo "  <ARTIFACT>_PATH           location of the source code of the artifact"
	echo "  <ARTIFACT>_SRC            path to source code files of the artifact"
	echo "  <ARTIFACT>_TEST           location of test files of the artifact"
	echo "  <ARTIFACT>_TYPE           artifact usage type"
	echo "                            - bin  - binaries build from source code"
	echo "                            - hdr  - use headers only from git"
	echo "                            - lib  - use system headers and -l<libname> flags"
	echo "                            - opt  - use optional configuration"
	echo "                            - pkg  - use pkgconfig for configuration"
	echo "                            - src  - use sources and headers from git"
	echo "  <ARTIFACT>_URL            location of the artifact git repoisitory"
	echo "  <ARTIFACT>_VERSION        version of the artifact used for building"
	echo ""
	echo "Artifacts used for build:"
	echo "  $(DEPENDENCIES)"
	echo ""
