gnustep / tools-make

The makefile package is a simple, powerful and extensible way to write makefiles for a GNUstep-based project.
https://www.gnustep.org/
GNU General Public License v3.0
29 stars 43 forks source link

Can't build a project with subprojects if GNUSTEP_BUILD_DIR is set to something different than the current directory #43

Open svgol opened 8 months ago

svgol commented 8 months ago

GNUSTEP_BUILD_DIR is set to . by default (common.make:176).

But if I point GNUSTEP_BUILD_DIR to a directory on tmpfs (e.g. /run/user/1000/build/gnustep on Linux/Ubuntu) I get the following error when trying to build libs-base:

make[4]: No rule to make target '/run/user/1000/build/gnustep/Source/ObjectiveC2//run/user/1000/build/gnustep/Source/ObjectiveC2/obj/ObjectiveC2.obj/blocks_runtime.m.o', needed by '/run/user/1000/build/gnustep/Source/obj/libgnustep-base.so.1.28.0'. Stop. make[3]: [/opt/gnustep/System/Library/Makefiles/Instance/library.make:286: internal-library-all_] Error 2 make[2]: [/opt/gnustep/System/Library/Makefiles/Master/rules.make:297: libgnustep-base.all.library.variables] Error 2 make[1]: [/opt/gnustep/System/Library/Makefiles/Master/library.make:37: internal-all] Error 2 make: *** [/opt/gnustep/System/Library/Makefiles/Master/serial-subdirectories.make:53: internal-all] Error 2

The close look at the error line gives a cue that the GNUSTEP_BUILD_DIR is somehow used twice somewhere

'/run/user/1000/build/gnustep/Source/ObjectiveC2//run/user/1000/build/gnustep/Source/ObjectiveC2/obj/ObjectiveC2.obj/blocks_runtime.m.o'

I was able to pin the cause down to the Instance/rules.make:211:

ifneq ($($(GNUSTEP_INSTANCE)_SUBPROJECTS),)
SUBPROJECT_OBJ_FILES = $(foreach d, $($(GNUSTEP_INSTANCE)_SUBPROJECTS), \
        $(foreach o, $(shell cat \
        $(GNUSTEP_BUILD_DIR)/$(d)/$(GNUSTEP_OBJ_DIR_NAME)/$(SUBPROJECT_PRODUCT)), \
        $(addprefix $(GNUSTEP_BUILD_DIR)/$(d)/, $(o))))
endif

Here is what happens: SUBPROJECT_PRODUCT is a file named subproject.txt where subproject's object file paths are written. Writing occurs in Instance/subproject.make:61:

$(GNUSTEP_OBJ_DIR)/$(SUBPROJECT_PRODUCT): $(OBJ_FILES_TO_LINK)
ifeq ($(OBJ_FILES_TO_LINK),)
    $(WARNING_EMPTY_LINKING)
endif
    @echo "$(OBJ_FILES_TO_LINK)" > $(GNUSTEP_OBJ_DIR)/$(SUBPROJECT_PRODUCT)

OBJ_FILES_TO_LINK is populated in Instance/rules.make:258 by content of variables like xxx_FILES, e.g. Instance/rules.make:215:

OBJC_OBJ_FILES = $(addprefix $(GNUSTEP_OBJ_INSTANCE_DIR)/,$(OBJC_OBJS))

GNUSTEP_OBJ_INSTANCE_DIR is defined in common.make:819:

ifneq ($(GNUSTEP_INSTANCE),)
  GNUSTEP_OBJ_INSTANCE_DIR_NAME = $(GNUSTEP_OBJ_DIR_NAME)/$(GNUSTEP_INSTANCE).obj
  GNUSTEP_OBJ_INSTANCE_DIR      = $(GNUSTEP_BUILD_DIR)/$(GNUSTEP_OBJ_INSTANCE_DIR_NAME)
else

Lets summarize: GNUSTEP_BUILD_DIR is used when subproject's object file paths are written into subproject.txt and the second time in the 'owning' project's SUBPROJECT_OBJ_FILES:

ifneq ($($(GNUSTEP_INSTANCE)_SUBPROJECTS),)
SUBPROJECT_OBJ_FILES = $(foreach d, $($(GNUSTEP_INSTANCE)_SUBPROJECTS), \
        $(foreach o, $(shell cat \
        $(GNUSTEP_BUILD_DIR)/$(d)/$(GNUSTEP_OBJ_DIR_NAME)/$(SUBPROJECT_PRODUCT)), \  # the first time
        $(addprefix $(GNUSTEP_BUILD_DIR)/$(d)/, $(o))))                              # the second time
endif

I am not a make expert so here am I lost. All my tinkering with that led to dirty hacks.

svgol commented 8 months ago

project_example.tar.gz

I upload a simple project example in case trying on libs-base is inappropriate.