windowsgccmakefilemingw-w64premake

Why is Premake5 producing incorrect file separator on Windows?


I am trying to use premake5 to build a simple C project using Visual Studio Code on Windows and I'm getting the below error:

$ make config=release_win64
"==== Building calc (release_win64) ===="
Creating obj/win64/Release
"main.c"
process_begin: CreateProcess(NULL, cc -MD -MP -DNDEBUG -Isrc/include -m64 -Werror -flto 
-O3 -o obj/win64/Release/main.o -MF obj/win64/Release/main.d -c src/main.c, ...) 
failed.
make (e=2): The system cannot find the file specified.
make[1]: *** [calc.make:153: obj/win64/Release/main.o] Error 2
make: *** [Makefile:36: calc] Error 2

I strongly suspect that it is not able to handle the file separator for windows correctly. Please help me understand what am I doing incorrectly with my premake5.lua script.

Here are the details:

Project Folder Structure

- Project Root
    - src
        - include
            - sum.h
        - main.c
        - sum.c
    - premake5.lua

premake5.lua

workspace "calc"
    configurations { "Debug", "Release" }
    platforms { "win64", "linux64" }

project "calc"
    kind "ConsoleApp"
    language "C"
    targetname "calc"
    targetdir "bin/%{cfg.buildcfg}"
    entrypoint ("main()")
    includedirs { "src/include" }
    files { "src/**.h", "src/**.c" }

    filter { "platforms:linux64" }
        system "linux"
        architecture "x86_64"

    filter { "platforms:win64" }
        system "windows"
        architecture "x86_64"
        toolset "gcc"

    filter { "configurations:Debug" }
        flags { "FatalWarnings" }
        defines { "DEBUG" }
        symbols "On"

    filter { "configurations:Release" }
        flags { "FatalWarnings", "LinkTimeOptimization" }
        defines { "NDEBUG" }
        optimize "speed"
    

main.c

#include "include/sum.h"
#include <stdio.h>

int main() {
    int a = 1;
    int b = 2;
    int result = sum(a, b);
    printf("%d + %d = %d", a, b, result);
    return 0;
}

Sum.h

#ifndef SUM_H
#define SUM_H

int sum(int a, int b);

#endif

sum.c

#include "include/sum.h"

int sum(int a, int b) {
    return a + b;
}

Build commands

$ premake5 gmake2
Building configurations...
Running action 'gmake2'...
Done (57ms).

$ make config=release_win64
"==== Building calc (release_win64) ===="
"main.c"
process_begin: CreateProcess(NULL, cc -MD -MP -DNDEBUG -Isrc/include -m64 -Werror -flto -O3 -o obj/win64/Release/main.o -MF obj/win64/Release/main.d -c src/main.c, ...) failed.
make (e=2): The system cannot find the file specified.
make[1]: *** [calc.make:153: obj/win64/Release/main.o] Error 2
make: *** [Makefile:36: calc] Error 2

Auto generated Makefile

# Alternative GNU Make workspace makefile autogenerated by Premake

ifndef config
  config=debug_win64
endif

ifndef verbose
  SILENT = @
endif

ifeq ($(config),debug_win64)
  calc_config = debug_win64

else ifeq ($(config),debug_linux64)
  calc_config = debug_linux64

else ifeq ($(config),release_win64)
  calc_config = release_win64

else ifeq ($(config),release_linux64)
  calc_config = release_linux64

else
  $(error "invalid configuration $(config)")
endif

PROJECTS := calc

.PHONY: all clean help $(PROJECTS) 

all: $(PROJECTS)

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

clean:
    @${MAKE} --no-print-directory -C . -f calc.make clean

help:
    @echo "Usage: make [config=name] [target]"
    @echo ""
    @echo "CONFIGURATIONS:"
    @echo "  debug_win64"
    @echo "  debug_linux64"
    @echo "  release_win64"
    @echo "  release_linux64"
    @echo ""
    @echo "TARGETS:"
    @echo "   all (default)"
    @echo "   clean"
    @echo "   calc"
    @echo ""
    @echo "For more information, see https://github.com/premake/premake-core/wiki"

Auto generated calc.make file

# Alternative GNU Make project makefile autogenerated by Premake

ifndef config
  config=debug_win64
endif

ifndef verbose
  SILENT = @
endif

.PHONY: clean prebuild

SHELLTYPE := posix
ifeq (.exe,$(findstring .exe,$(ComSpec)))
    SHELLTYPE := msdos
endif

# Configurations
# #############################################

RESCOMP = windres
INCLUDES += -Isrc/include
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES)
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS +=
LDDEPS +=
LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef

ifeq ($(config),debug_win64)
TARGETDIR = bin/Debug
TARGET = $(TARGETDIR)/calc.exe
OBJDIR = obj/win64/Debug
DEFINES += -DDEBUG
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -g
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64

else ifeq ($(config),debug_linux64)
TARGETDIR = bin/Debug
TARGET = $(TARGETDIR)/calc
OBJDIR = obj/linux64/Debug
DEFINES += -DDEBUG
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -g
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64

else ifeq ($(config),release_win64)
TARGETDIR = bin/Release
TARGET = $(TARGETDIR)/calc.exe
OBJDIR = obj/win64/Release
DEFINES += -DNDEBUG
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -flto -O3
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -flto -O3
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64 -flto -s

else ifeq ($(config),release_linux64)
TARGETDIR = bin/Release
TARGET = $(TARGETDIR)/calc
OBJDIR = obj/linux64/Release
DEFINES += -DNDEBUG
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -flto -O3
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -Werror -flto -O3
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64 -flto -s

endif

# Per File Configurations
# #############################################


# File sets
# #############################################

GENERATED :=
OBJECTS :=

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

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

all: $(TARGET)
    @:

$(TARGET): $(GENERATED) $(OBJECTS) $(LDDEPS) | $(TARGETDIR)
    $(PRELINKCMDS)
    @echo Linking calc
    $(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

clean:
    @echo Cleaning calc
ifeq (posix,$(SHELLTYPE))
    $(SILENT) rm -f  $(TARGET)
    $(SILENT) rm -rf $(GENERATED)
    $(SILENT) rm -rf $(OBJDIR)
else
    $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET))
    $(SILENT) if exist $(subst /,\\,$(GENERATED)) del /s /q $(subst /,\\,$(GENERATED))
    $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR))
endif

prebuild: | $(OBJDIR)
    $(PREBUILDCMDS)

ifneq (,$(PCH))
$(OBJECTS): $(GCH) | $(PCH_PLACEHOLDER)
$(GCH): $(PCH) | prebuild
    @echo $(notdir $<)
    $(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<"
$(PCH_PLACEHOLDER): $(GCH) | $(OBJDIR)
ifeq (posix,$(SHELLTYPE))
    $(SILENT) touch "$@"
else
    $(SILENT) echo $null >> "$@"
endif
else
$(OBJECTS): | prebuild
endif


# File Rules
# #############################################

$(OBJDIR)/main.o: src/main.c
    @echo "$(notdir $<)"
    $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/sum.o: src/sum.c
    @echo "$(notdir $<)"
    $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"

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

Make version

$ make --version
GNU Make 4.4.1
Built for Windows32
Copyright (C) 1988-2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GCC Version

$ gcc --version
gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Operating System

Edition Windows 11
Version 23H2
OS build    22631.4169
Experience  Windows Feature Experience Pack 1000.22700.1034.0

Device Specifications

Processor   Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz   2.59 GHz
Installed RAM   8.00 GB (7.80 GB usable)
System type 64-bit operating system, x64-based processor

PATH

$ echo %PATH%
<OTHERS>;C:\mingw64\bin;C:\Program Files\premake-5.0.0-beta2-windows

Solution

  • Your suspicion regarding path separators is not correct. The error you get is:

    CreateProcess(NULL, cc -MD ...

    This means that make was not able to invoke the cc command. You show that the command gcc exists, but that's not the command make is trying to run.

    I don't know what "premake5" is but one problem is that the generated makefile is hiding the commands that are being invoked rather than printing them so your makefile is hard to debug. It looks like you can run make verbose=1 or similar to see all the commands being run.

    If you don't have a cc compiler on your system, you should set the CC variable to the name of your compiler. For example, make CC=gcc