premake-core icon indicating copy to clipboard operation
premake-core copied to clipboard

g++/clang++ not found while linking when installed in a custom location

Open complexmath opened this issue 2 years ago • 11 comments

I'm building on a Linux system (WSL2) that doesn't have gcc or clang installed in /usr. Instead, it's installed in my local project directory. I've added the following to premake5.lua:

bindirs { "path/to/gcc/bin" }

The relevant portions of my generated makefile are:

LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)

$(OBJDIR)/main.o: source/main.cpp
	@echo $(notdir $<)
	$(SILENT) $(EXE_PATHS) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"

While building I get an error like:

/bin/sh: 1: g++: not found

I think the generated LINKCMD above should really look like:

LINKCMD = $(EXE_PATHS) $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)

complexmath avatar Sep 20 '22 00:09 complexmath

That is most likely Make not knowing where your C++ compiler is, not a bug in Premake. Is GCC/G++ on your path? Have you tried passing CXX as a parameter to make?

nickclark2016 avatar Sep 20 '22 00:09 nickclark2016

My understanding is that this is what the bindirs instruction is for in premake. Is this not the case? Like because of the $(EXE_PATHS) param in the generated build instruction, make is able to find the compiler to generate object files just fine. But because this is missing from the link command, it can't do the same for that step. I agree that I could fix this by doing something like:

PATH=/path/to/gcc/bin:$PATH make

But it doesn't seem like this should be necessary. Assuming I had GCC installed in the default location and a different version installed elsewhere that I was pointing to via bindirs for this build, I'd be using a different version of G++ for the link step than I used to generate object files.

complexmath avatar Sep 20 '22 20:09 complexmath

Can you share more of the generated makefile?

nickclark2016 avatar Sep 20 '22 20:09 nickclark2016

Makefile:

all: $(PROJECTS)

app: proj-test

proj-test:
ifneq (,$(proj_test_config))
	@echo "==== Building proj-test ($(proj_test_config)) ===="
	@${MAKE} --no-print-directory -C . -f proj-test.make config=$(proj_test_config)
endif

proj-test.make:

ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LDDEPS +=
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
EXECUTABLE_PATHS = "_build/tools/gcc/bin"
EXE_PATHS = export PATH=$(EXECUTABLE_PATHS):$$PATH;
...
# File sets
# #############################################

GENERATED :=
OBJECTS :=

GENERATED += $(OBJDIR)/main.o
OBJECTS += $(OBJDIR)/main.o

# Rules
# #############################################

all: $(TARGET)
	@:

$(TARGET): $(GENERATED) $(OBJECTS) $(LDDEPS) | $(TARGETDIR)
	$(PRELINKCMDS)
	@echo Linking proj-test
	$(SILENT) $(LINKCMD)
	$(POSTBUILDCMDS)

$(TARGETDIR):
	@echo Creating $(TARGETDIR)
ifeq (posix,$(SHELLTYPE))
	$(SILENT) mkdir -p $(TARGETDIR)
else
	$(SILENT) mkdir $(subst /,\\,$(TARGETDIR))
endif

$(OBJDIR):
	@echo Creating $(OBJDIR)
ifeq (posix,$(SHELLTYPE))
	$(SILENT) mkdir -p $(OBJDIR)
else
	$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
...
# File Rules
# #############################################

$(OBJDIR)/main.o: source/main.cpp
	@echo $(notdir $<)
	$(SILENT) $(EXE_PATHS) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"

-include $(OBJECTS:%.o=%.d)
ifneq (,$(PCH))
  -include $(PCH_PLACEHOLDER).d
endif

From looking at the premake code, I found this for example, which injects the bindirs for the build step: https://github.com/premake/premake-core/blob/master/modules/gmake/gmake_cpp.lua#L257

But the LINKCMD isn't given the same treatment, as you can see above. Maybe not a huge issue if this is C and you can link with ar, but potentially more of an issue for C++ when you typically link via the compiler.

complexmath avatar Sep 20 '22 20:09 complexmath

I believe that bindirs are used for using custom tools in custom build steps (passing paths to where you have you build tools), not to where CC, CXX, etc. I'd like @starkos or @samsinsane to confirm my guess though.

nickclark2016 avatar Sep 21 '22 01:09 nickclark2016

Then shouldn't the $(EXE_PATHS) bit be missing from the build rules involving $(CXX)? Ultimately, the issue here is the inconsistency in path handling between the compile and link steps.

complexmath avatar Sep 22 '22 19:09 complexmath

Good catch. I'll investigate further and get back to you.

nickclark2016 avatar Sep 22 '22 19:09 nickclark2016

BTW, https://premake.github.io/docs/bindirs/ has no real documentation.

Jarod42 avatar Sep 23 '22 11:09 Jarod42

BTW, https://premake.github.io/docs/bindirs/ has no real documentation.

Yup, that's a definite issue. I think it's lead to some of my confusion as well.

nickclark2016 avatar Sep 23 '22 12:09 nickclark2016

@nickclark2016 That is correct, bindirs was intended for the custom build rules system. The new gmake2 action built C++ support around the rules system, which has created this weird scenario of bindirs impacting regular project compilation.

@complexmath for GCC there is gccprefix which might work for your situation? It won't replicate PATH=<path>:$PATH but it might otherwise do what you're expecting? Alternatively, you could look into using makesettings to configure the paths as you expect? This will inject whatever Makefile settings you want just after the EXE_PATHS output but before the pre-build commands output.

samsinsane avatar Oct 03 '22 16:10 samsinsane

what if there's more than 1 version of the same compiler installed? does bindirs allow choosing one over the other?

Enhex avatar Dec 15 '22 11:12 Enhex