MS-Windows MakeFIles - c

I am trying to write makefile for ms-windows application. The idea is very simple. I have to generate the output .o, .exe files into the build directory. I have written makefile which will compile source directory, but is not able to generate the build directory and compilation process is perfectly working.
Please have a look for the makefile. It looks like i am not able to generate the build directory using mkdir command.
CC= gcc
CFLAG= -g -Wall
TARGET_EXEC ?= test.exe
RELEASE= Release
RELEASE_BIN= bin
RELEASE_CNFG= config
RELEASE_LOG= log
RELEASE_DATA=data
BUILD_DIR ?= build
SRC_DIRS ?= src
#OS dependent cleaning command
ifdef OS
RM = rd /s /q
else
ifeq ($(shell uname), Linux)
RM = rm -f
endif
endif
SRCS := $(wildcard $(SRC_DIRS)/*.c)
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:.o=.d)
INC_DIRS := $(wildcard $(SRC_DIRS) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
#find the directory for the include file
#this is best otpion to search curl directory
USR_INC := /usr/include
FILES :=
INCLUDES = -Iinclude
LIBS= -lm
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
$(CC) $(OBJS) -o $# $(LIBS) $(LLFLAGS)
# c source
$(BUILD_DIR)/%.c.o: %.c
#echo Compiling $<
# here I am trying to generate the file into the build/src/xxxc.o
# $(MKDIR_P) $#
$(CC) $(CFLAG) -c $< -o $# $(INCLUDES)
.PHONY: install
install:
# echo "Installing..........."
# echo "Creating $(RELEASE) Directory..."
# $(MKDIR_P) $(RELEASE)
# echo "Creating $(RELEASE)/$(RELEASE_BIN) Directory.."
# $(MKDIR_P) $(RELEASE)/$(RELEASE_BIN)
# echo "Creating $(RELEASE)/$(RELEASE_CNFG) Directory..."
# $(MKDIR_P) $(RELEASE)/$(RELEASE_CNFG)
# echo "Creating $(RELEASE)/$(RELEASE_LOG) Directory..."
# $(MKDIR_P) $(RELEASE)/$(RELEASE_LOG)
# echo "Creating $(RELEASE)/$(RELEASE_DATA) Directory..."
# $(MKDIR_P) $(RELEASE)/$(RELEASE_DATA)
# echo "Makking Release folder ready.."
#cp $(BUILD_DIR)/$(TARGET_EXEC) $(RELEASE)/$(RELEASE_BIN)
# echo "copy certificate file to Release"
#cp -r cert $(RELEASE)
# echo "copy .ini file to Release"
#cp -r config/*.ini $(RELEASE)/$(RELEASE_CNFG)
.PHONY: clean
clean:
$(RM) $(BUILD_DIR) $(RELEASE)
-include $(DEPS)
MKDIR_P ?= mkdir

I do understand what your are trying. But please be aware that some differences in platforms and dependencies will force you to create something that is similar to a "configure" and "make" step.
So you will start to generate a custom Makefile in a tool to be invented by you sooner or later :).
It is mentioned in the comments: This has already been done and cmake is now "industrial standard"
It works on Windows, Linux, OSX and so on with great toolchain support. Have a look at it!
Example:
cmake_minimum_required(VERSION 3.4)
project(HelloWorldCMake)
set(MY_SOURCES
hello_world.c
)
add_executable(HelloWorldCMake
${MY_SOURCES}
)
And hello_world.c
#include <stdio.h>
int main()
{
printf("Hello world (cmake)");
}
If you want to link additional libraries, please research
the CMake command: target_link_libraries
https://cmake.org/cmake/help/latest/command/target_link_libraries.html

Related

Breakpoints are not being hit - CLion Full Remote Debug - MakeFile - GDB

It doesn't matter what type of remote debug connection I tried.. Full Remote Host, Remote Debug, Remote GDB Server etc.
Actually remote device starts working when I clicked the debug button. I can run it from my CLion but it never hits to my breakpoints..
I'm not professional on remote debugging, actually it is my second work but this time it is on already working ( readymade ) project on my Raspberry pi Lorawan device ( Debian ) .
Device connected to my home network and there is a package forwarder app in it. App listens 1680 port.
Normally it is working on remote device with no problem. I downloaded the app to my computer and built the project successfully in CLion. After I tried lots of things, almost every combination of remote debugging and settings. I understood I'm missing some point and I need help. If you can help me you will save my life
Makefile :
### get external defined data
include ../target.cfg
### Application-specific constants
APP_NAME := lora_pkt_fwd
### Environment constants
LGW_PATH ?= ../libloragw
LIB_PATH ?= ../libtools
ARCH ?=
CROSS_COMPILE ?=
OBJDIR = obj
INCLUDES = $(wildcard inc/*.h)
### External constant definitions
# must get library build option to know if mpsse must be linked or not
include $(LGW_PATH)/library.cfg
RELEASE_VERSION := `cat ../VERSION`
### Constant symbols
CC := -g $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. -I../libtools/inc
VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\""
### Constants for Lora concentrator HAL library
# List the library sub-modules that are used by the application
LGW_INC =
ifneq ($(wildcard $(LGW_PATH)/inc/config.h),)
# only for HAL version 1.3 and beyond
LGW_INC += $(LGW_PATH)/inc/config.h
endif
LGW_INC += $(LGW_PATH)/inc/loragw_hal.h
### Linking options
LIBS := -lloragw -ltinymt32 -lparson -lbase64 -lrt -lpthread -lm -lcursor
### General build targets
all: $(APP_NAME)
clean:
rm -f $(OBJDIR)/*.o
rm -f $(APP_NAME)
ifneq ($(strip $(TARGET_IP)),)
ifneq ($(strip $(TARGET_DIR)),)
ifneq ($(strip $(TARGET_USR)),)
install:
#echo "---- Copying packet_forwarder files to $(TARGET_IP):$(TARGET_DIR)"
#ssh $(TARGET_USR)#$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
#scp lora_pkt_fwd $(TARGET_USR)#$(TARGET_IP):$(TARGET_DIR)
install_conf:
#echo "---- Copying packet_forwarder conf files to $(TARGET_IP):$(TARGET_DIR)"
#ssh $(TARGET_USR)#$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
#scp global_conf.json.sx1250.* $(TARGET_USR)#$(TARGET_IP):$(TARGET_DIR)
#scp global_conf.json.sx1257.* $(TARGET_USR)#$(TARGET_IP):$(TARGET_DIR)
else
#echo "ERROR: TARGET_USR is not configured in target.cfg"
endif
else
#echo "ERROR: TARGET_DIR is not configured in target.cfg"
endif
else
#echo "ERROR: TARGET_IP is not configured in target.cfg"
endif
### Sub-modules compilation
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR)
$(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $#
### Main program compilation and assembly
$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) $(INCLUDES) | $(OBJDIR)
$(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $#
$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/jitqueue.o
$(CC) -L$(LGW_PATH) -L$(LIB_PATH) $< $(OBJDIR)/jitqueue.o -o $# $(LIBS)
### EOF
I'm sharing my last try screenshots with you : Full Remot Host.
If I add -g to CXXFLAGS in https://github.com/remonbonbon/makefile-example, I can debug the app target just fine.
link -> https://intellij-support.jetbrains.com/hc/en-us/community/posts/360009699119-Debugging-not-working-when-using-the-Makefile-feature-in-2020-2-EAP-

filter-out is not filtering file? Makefile for C

so ive got a make file here and my project currently has a master.c and slave.c which both have main functions. therefore i just want to filter the slave.c file out of the building process. so I used fliter-out when defining the source files. but when run make the project keeps turning up with the "multiple definitions of main" error. why is this when filter-out should be hiding the slave.c file?
########################################################################
####################### Makefile Template ##############################
########################################################################
#Compiler settings - Can be customized.
CC = gcc
CXXFLAGS = -std=c11 -Wall
LDFLAGS =
# Makefile settings - Can be customized.
APPNAME = master
SUBAPPNAME = slave
EXT = .c
SRCDIR = .
OBJDIR = .
############## Do not change anything from here downwards! #############
SRC := $(filter-out slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
OBJ := $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)/%.o)
DEP := $(OBJ:$(OBJDIR)/%.o=%.d)
#UNIX-based OS variables & settings
RM = rm
DELOBJ = $(OBJ)
# Windows OS variables & settings
DEL = del
EXE = .exe
WDELOBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)\\%.o)
########################################################################
####################### Targets beginning here #########################
########################################################################
all: $(APPNAME)
# Builds the app
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
# Creates the dependecy rules
%.d: $(SRCDIR)/%$(EXT)
#$(CPP) $(CFLAGS) $< -MM -MT $(#:%.d=$(OBJDIR)/%.o) >$#
# Includes all .h files
-include $(DEP)
# Building rule for .o files and its .c/.cpp in combination with all .h
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(CXXFLAGS) -o $# -c $<
################### Cleaning rules for Unix-based OS ###################
# Cleans complete project
.PHONY: clean
clean:
$(RM) $(DELOBJ) $(DEP) $(APPNAME)
# Cleans only all files with the extension .d
.PHONY: cleandep
cleandep:
$(RM) $(DEP)
# Clean only all files with the extension .o
.PHONY: cleanobj
cleanobj:
$(RM) $(DELOBJ)
# Cleans both files with .d and .o extensions
.PHONY: cleanod
cleanod:
$(RM) $(DELOBJ) $(DEP)
The call
SRC := $(filter-out slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
is just a string operation, that is, make is unaware of the underlying file tree and tries to throw out the string slave.c from the liste yoursrcdir/slave.c yoursrcdir/master.c which obviously fails. Although you may disagree at first, this is a good thing because the semantic of filter operations on filetrees is by no means universal or easy to document or transport. Therefore make just looks at the presented strings and decides on the character-for-character comparison which to take and which to drop.
That said, the rewrite to
SRC := $(filter-out $(SRCDIR)/slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
will do the trick in your case.
For wider reaching functionality look up the two functions abspath and realpath to get file names in a canonical format, which prevent filter et.al. from stumbling on differences in OS nomenclature.

Makefile automatically call `yacc`

Hi I have a makefile like this:
# Variables =====================================================================================
PHONY =
proj =
ALL_FILES := $(filter $(proj).%,$(shell ls | grep "^$(proj)\.[a-z]*$$"))
LEX_FILE := $(filter %.l, $(ALL_FILES))
BISON_FILE := $(filter %.y, $(ALL_FILES))
C_FILE := $(filter %.c, $(ALL_FILES))
H_FILE := $(filter %.h, $(ALL_FILES))
BISON_OUT_H := $(subst .y,.tab.h,$(BISON_FILE))
BISON_OUT_C := $(subst .y,.tab.c,$(BISON_FILE))
BISON_OUT := $(BISON_OUT_C) $(BISON_OUT_H)
LEX_OUT := $(subst .l,.yy.c,$(LEX_FILE))
LEX_TRG := $(LEX_FILE)
LEX_DEP := $(LEX_FILE) $(BISON_OUT_H)
GCC_TRG := $(BISON_OUT_C) $(LEX_OUT) $(C_FILE)
GCC_DEP := $(GCC_TRG) $(H_FILE) $(BISON_OUT_H)
CFLAGS = -g
test:
#echo $(proj)
#echo $(ALL_FILES)
#echo $(LEX_FILE)
#echo $(BISON_FILE)
#echo $(C_FILE)
#echo $(BISON_OUT_C)
#echo $(LEX_OUT)
#echo $(GCC_TRG)
#echo $(GCC_DEP)
# Flex ==========================================================================================
$(LEX_OUT):$(LEX_DEP)
ifneq (,$(LEX_TRG))
flex --outfile=$# $(LEX_TRG)
endif
# Bison =========================================================================================
$(BISON_OUT):$(BISON_FILE)
ifneq (,$(BISON_FILE))
bison -d $<
endif
# Run ===========================================================================================
$(proj).out:$(GCC_DEP)
ifneq (,$(GCC_TRG))
gcc $(CFLAGS) $(GCC_TRG) -o $#
endif
run:$(proj).out
./$<
run_lex:$(proj).out
#echo "Please type in file names: "; \
read file; \
./$< $$file
PHONY += run run_wc run_lex
# Clean =========================================================================================
clean:
-rm *.out *.lex *.yy.c *.tab.h *.tab.c *.s
cleansp:
-rm $(proj).out $(proj).lex $(BISON_OUT) $(LEX_OUT)
PHONY += clean cleansp
# GitHub ========================================================================================
commit: clean
git add -A
#echo "Please type in commit comment: "; \
read comment; \
git commit -m"$$comment"
sync: commit
git push -u origin master
PHONY += commit sync
# PHONY =========================================================================================
.PHONY: $(PHONY)
In the current folder I have
[shore#shore-82b6 flex-bison]$ ls
calc2.c calc2.h calc2.l calc2.tab.c calc2.tab.h calc2.y calc2.yy.c calc.l calc.y ccr.l lc.l makefile Note.md samples st.l wc.l
The thing vary confused me is that when I run make run proj=calc2, if calc.y is changed then the make file will run extra instructions and output to calc.c as a result. The following is the shell output:
[shore#shore-82b6 flex-bison]$ make run proj=calc2
bison -d calc2.y
flex --outfile=calc2.yy.c calc2.l
yacc calc2.y
mv -f y.tab.c calc2.c
calc2.yy.c calc2.tab.c calc2.c
Notice this will only happen if calc.y is changed.
So how should I fix this and letting the makefile run the instructions suppose to be in my makefile.
You are being bitten by one of make's built-in rules:
%.c: %.y
# recipe to execute (built-in):
$(YACC.y) $<
mv -f y.tab.c $#
This says, "if I have a file foo.y and I want to build a file foo.c, here's how to do it". This is the normal naming convention for building yacc files.
In your situation you have a file calc2.y which is the yacc file and another file calc2.c which is a normal source file, but make doesn't know that it's a normal source file.
If you want to have your calc2.y not be related to your calc2.c, and instead have calc2.y be related only to calc2.tab.c, you'll have to cancel the built-in rule by declaring it without any recipe like this:
%.c: %.y

Makefile can I execute a configuration only once?

Im trying to create a Makefile which compiles some files and creates some outputs but first I want it to execute the configuration only one time and the next time I type make it wont re-execute the configuration unless I change the parameters for example the prefix.
I tried using touch , FORCE and if, after searching a bit in other posts but Im newbie in gcc and Makefiles so I cant make it work.
My code now is (did not include the other rules because they dont affect the configuration):
XLEN := 32
RISCV_PREFIX := riscv$(XLEN)-unknown-elf-
RISCV_GCC := $(RISCV_PREFIX)gcc
CFLAGS := -O2
WORKING_DIR:= $(shell pwd)
LIBRARY_DIR:= $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
B := $(shell echo $(LIBRARY_DIR))
$(info $(B))
--->(execute this only once)---> CONFIGURATION := configure --prefix=$(LIBRARY_DIR) --with-arch=rv32if --with-abi=ilp32d
RISCV_TEST_DIR:=$(shell pwd)
SCRIPTDIR:=$(RISCV_TEST_DIR)/../../tools
RISCV_OPTIONS = -o
RISCV_LINK = $(RISCV_GCC) $(PROGRAMS) $(RISCV_OPTIONS) $# $(CFLAGS) #produces .elf file!
RISCV_OBJDUMP = $(RISCV_PREFIX)objdump -D #produces a dump file to see the assembly code!
RISCV_OBJCOPY = $(RISCV_PREFIX)objcopy -O binary #produces a bin file!
%.elf: %.c
$(info Generating .elf file from files: $(PROGRAMS_NO_EX))
$(RISCV_LINK)
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.dump: %.elf
$(info Copying assembly to dump file $(PROGRAMS_NO_EX).dump)
#$(RISCV_OBJDUMP) $< > $#
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.bin: %.elf
$(info Generating bin file)
#$(RISCV_OBJCOPY) $< $#
$(info Success!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.hex: %.bin
$(info Generating hex file)
echo cd $(SCRIPTDIR)
$(info Running binary to hex >>>)
python $(SCRIPTDIR)/bin2hex.py $< -a 0x0 > $# || exit -1
$(info Hex Generation Successful!)
$(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
all: $(PROGRAMS_TO_CREATE); if [ -a $(LIBRARY_DIR)/config.status ]; then cd $(LIBRARY_DIR) && $(CONFIGURATION); fi;
configure: config.status
touch configure
config.status:
cd $(LIBRARY_DIR) && $(CONFIGURATION);
.PHONY: all clean
clean:
$(info Cleaning files...)
#rm -rf *.elf *.hex *.map *.objdump *.i *.s *.bin *.dump
$(info Done cleaning!)
Thank you in advance!
I believe the only problem with your configuration statements are incorrect paths in rules for config.status and configure, since they really will be located within $(LIBRARY_DIR). When the paths are correct, it will correctly run configuration only once:
$ cat Makefile
LIBRARY_DIR := library
all: $(LIBRARY_DIR)/config.status
$(info Making $#)
$(LIBRARY_DIR)/config.status: $(LIBRARY_DIR)/configure
cd $(<D) && ./$(<F)
Output:
$ make
cd library && ./configure
Making all
$ make # <--- Invoking second time, no configure step
Making all
make: 'all' is up to date.
With #raspy's help managed to solve the problem like this:
all: $(PROGRAMS_TO_CREATE)
$(PROGRAMS_TO_CREATE):$(LIBRARY_DIR)/config.status
$(LIBRARY_DIR)/config.status:
cd $(LIBRARY_DIR) && $(CONFIGURATION)

Makefile based on sub-directories

I have a C project program that I want to compile and manage with a makefile:
./include: where headers resides
a.h , b.h , c.h
./obj: where object will be stored
-
./src: where source file resides
main.c , a.c , b.c , c.c
How can I create a makefile to create an executable test , and put object files to obj folder ?
You can use this template I made for simple project. I don't know which compiler you are using but you can configure it with the variables in the first sections as well as other useful configs:
#=============================================================================
# Project related variables
EXENAME = test
FILEIDENTIFIER = .c
COMPFLAGS = -pedantic -Wall
COMPSTANDARD = -std=c11
EXELINKS = -lm
DBARGS = -g
BUILDDIR = build/
BINARY_OUTPUT_DIR = $(BUILDDIR)bin/
OBJDIR = obj/
SOURCEDIRS = src/
INCLUDEDIRS = include/
LIBSDIRS = /usr/lib/
#=============================================================================
# Commands variables
COMPILER = gcc
LINKER = ld -r
DISPLAY = printf
MKDIR = mkdir -p
RMDIR = rmdir
RM = rm -f
#=============================================================================
# Other
VOIDECHO = > /dev/null 2>&1
#=============================================================================
# Semi-automatic variables
EXEFINALOBJ = $(OBJDIR)$(EXENAME).o
EXEFINAL = $(BINARY_OUTPUT_DIR)$(EXENAME)
INCLUDEARGS = $(addprefix -I,$(INCLUDEDIRS))
#=============================================================================
# Automatic variables
SOURCES = $(foreach sourcedir,$(SOURCEDIRS),$(wildcard $(sourcedir)**/*$(FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))
OBJECTS = $(patsubst %$(FILEIDENTIFIER),%.o,$(foreach sourcedir,$(SOURCEDIRS),$(subst $(sourcedir),$(OBJDIR),$(wildcard $(sourcedir)**/*$( FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))))
GENERATED_FILES = $(OBJECTS) $(EXEFINALOBJ) $(EXEFINAL)
GENERATED_FOLDERS = $(OBJDIR) $(BINARY_OUTPUT_DIR) $(BUILDDIR)
#=============================================================================
# Special GNU make variables
VPATH = $(SOURCEDIRS)
#=============================================================================
# Rules: Phony Targets
.PHONY: silent
silent:
#make --silent $(EXEFINAL)
.PHONY: all
all: $(EXEFINAL)
.PHONY: debug
debug: COMPFLAGS += $(DBARGS)
debug: all
.PHONY: clean
clean:
#$(DISPLAY) "\n-> Cleaning files...\n"
#$(DISPLAY) " $(foreach file,$(GENERATED_FILES),$(if $(wildcard $(file)),- Removing file $(file)\n,\b))"
#$(RM) $(GENERATED_FILES)
#$(DISPLAY) "\n-> Cleaning folders...\n"
#$(DISPLAY) " $(foreach folder,$(GENERATED_FOLDERS),$(if $(wildcard $(folder)),- Removing folder $(folder)\n,\b))"
#$(RMDIR) $(GENERATED_FOLDERS) $(VOIDECHO) || true
#$(DISPLAY) "\n"
#=============================================================================
# Rules: File Targets
$(EXEFINAL): $(EXEFINALOBJ)
#$(DISPLAY) "\n - Building $# from $^... "
#$(MKDIR) $(BINARY_OUTPUT_DIR)
$(COMPILER) $(EXEFINALOBJ) -o $# $(LIBARGS) $(EXELINKS)
#$(DISPLAY) "Done"
#$(DISPLAY) "\n\n"
$(EXEFINALOBJ): $(OBJECTS)
#$(DISPLAY) "\n - Merging objects files into $#... "
$(LINKER) $(OBJECTS) -o $#
#$(DISPLAY) "Done"
$(OBJDIR)%.o: %$(FILEIDENTIFIER)
#$(DISPLAY) "\n - Building $# from $^... "
#$(MKDIR) $(OBJDIR)
$(COMPILER) $(COMPFLAGS) $(COMPSTANDARD) $(INCLUDEARGS) -c $^ -o $#
#$(DISPLAY) "Done"
The actual configuration is for Linux and uses gcc and ld. It support subfolders for sources and 4 targets are defined:
silent (default): silent build
all: verbose build
debug: debug build
clean: remove files and folders generated by the makefile
If you want to understand exactly how the Makefile work, as MadScientist wrote, look at the GNU make manual at https://www.gnu.org/software/make/manual/html_node/Introduction.html

Resources