Skip to content

Instantly share code, notes, and snippets.

@xuhdev
Last active May 9, 2023 13:30
  • Star 46 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save xuhdev/1873316 to your computer and use it in GitHub Desktop.
# Makefile template for a shared library in C
# https://www.topbug.net/blog/2019/10/28/makefile-template-for-a-shared-library-in-c-with-explanations/
CC = gcc # C compiler
CFLAGS = -fPIC -Wall -Wextra -O2 -g # C flags
LDFLAGS = -shared # linking flags
RM = rm -f # rm command
TARGET_LIB = libtarget.so # target lib
SRCS = main.c src1.c src2.c # source files
OBJS = $(SRCS:.c=.o)
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CC) ${LDFLAGS} -o $@ $^
$(SRCS:.c=.d):%.d:%.c
$(CC) $(CFLAGS) -MM $< >$@
include $(SRCS:.c=.d)
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS} $(SRCS:.c=.d)
@devendranaga
Copy link

does -O2 and -g can co exist?

@0x4C4A
Copy link

0x4C4A commented Jul 27, 2015

@devnaga

does -O2 and -g can co exist?

From man gcc:

Unlike most other C compilers, GCC allows you to use -g' with-O'. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops.

Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.

tl;dr - yes it can.

@saqib-ahmed
Copy link

Can you please explain its working. I mean I can see that you have generated .o files and linked em together to make the .so. I want to know like step by step execution of this makefile. (I'm new to makefiles and bash, so you might want to elaborate $^, $&lt; etc).

@Tibalt
Copy link

Tibalt commented Apr 16, 2017

There are tons information on google about Makefile. Please google by yourself. @saqibahmed515

@behnejad
Copy link

could you tell me how can i build static library with your Makefile? and how can i specify a special directory for .d and .o files.

@nnop
Copy link

nnop commented Aug 17, 2018

Better using -MMD -MP for dependencies auto-generation.

@InspectorConstructor
Copy link

much appreciated! needed this in a pinch.

@nainesh1311
Copy link

What about header file ?

@xuhdev
Copy link
Author

xuhdev commented Aug 1, 2019

@nainesh1311 You don't need to add them to the Makefile, because we should only send source files directly to the compiler and the compiler will find header files automatically.

@dr-begemot
Copy link

dr-begemot commented Oct 2, 2019

Fix
$(SRCS:.c=.d):%.d:%.c
to
$(SRCS:.c=.o):%.o:%.c

And...
Why do you use the -MM option if you don’t have an entry point in `$(SRCS:.c=.d)? Where you using .d file?
https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/GCC/options/MM

$(CC) $(CFLAGS) -MM $< >$@ create some .d files

@xuhdev
Copy link
Author

xuhdev commented Oct 2, 2019

@dr-begemot $(SRCS:.c=.d):%.d:%.c is correct. The *.d files are used in the include line. $(SRCS:.c=.o):%.o:%.c is not needed because they are subsumed by the content of *.d files. In your link, there is an example that states main.d contains:

main.o: main.c hello-world.h print-line.h

which is exactly what your "correction" tries to add (with header files also taken care of).

@dr-begemot
Copy link

@xuhdev
okay, then where entry point to
$(SRCS:.c=.d):%.d:%.c
?

You wrote: $(TARGET_LIB): $(OBJS)
where OBJS is $(SRCS:.c=.o), .c=.o, not .c=.d

I really want to understand)

@xuhdev
Copy link
Author

xuhdev commented Oct 3, 2019

$(SRCS:.c=.d):%.d:%.c is used to generate *.d files.

$(SRCS:.c=.o) are expressed in the generated *.d files. (Try to use this template in a minimum project and inspect the generated *.d files yourself.) I can write a post explaining this template, but I will not be able to do it until weekend.

@dr-begemot
Copy link

How to force your way accept include path -I?

@xuhdev
Copy link
Author

xuhdev commented Oct 28, 2019

@singh667
Copy link

can any one tell me how to add shared library in my main project make file

@dr-begemot
Copy link

can any one tell me how to add shared library in my main project make file

-l

for example:
gcc -w -Wall -g $(SRCS) -o test.exe $(FLAGS) -lsqlite3 -lcrypto -lconfig -lprotobuf-c -lcurl $(INCLUDE)

@singh667
Copy link

singh667 commented Jan 19, 2021

thanks for response

but one think i am not understanding actually i install embedded eclipse for windows when i create shared library output fill generated lib.so file as for my knowladge lib.so file generate base on linux system . why its happen like that

if i successfully generated library then where i add the this line

gcc -w -Wall -g $(SRCS) -o test.exe $(FLAGS) -lsqlite3 -lcrypto -lconfig -lprotobuf-c -lcurl $(INCLUDE)

in make
please consider the my attachment of make file

##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [2.27.0] date: [Sat Apr 28 17:58:48 IST 2018]
##########################################################################################################################

# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
#	2017-02-10 - Several enhancements + project update mode
#   2015-07-22 - first version
# ------------------------------------------------

######################################
# target
######################################
TARGET = InfaLoraNodeRev1


######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og


#######################################
# paths
#######################################
# source path
SOURCES_DIR =  \
Drivers/CMSIS \
Drivers/STM32L1xx_HAL_Driver \
Drivers \
InfaLibrary \
Application/User \
Application \

# firmware library path
PERIFLIB_PATH = 

# Build path
BUILD_DIR = build

######################################
# source
######################################
# C sources
C_SOURCES =  \


# ASM sources
ASM_SOURCES =  \
startup_stm32l152xe.s


######################################
# firmware library
######################################
PERIFLIB_SOURCES = 


#######################################
# binaries
#######################################
#BINPATH = usr/bin
#PREFIX = arm-none-eabi-
#CC = $(BINPATH)/$(PREFIX)gcc
#AS = $(BINPATH)/$(PREFIX)gcc -x assembler-with-cpp
#CP = $(BINPATH)/$(PREFIX)objcopy
#AR = $(BINPATH)/$(PREFIX)ar
#SZ = $(BINPATH)/$(PREFIX)size
#HEX = $(CP) -O ihex
#BIN = $(CP) -O binary -S

#BINPATH = E:\Rakesh.KS\ECLIPSE\GNU Tools ARM Embedded\7 2017-q4-major\bin
PREFIX = arm-none-eabi-
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
AR = $(PREFIX)ar
SZ = $(PREFIX)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
 
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m3

# fpu
# NONE for Cortex-M0/M0+/M3

# float-abi


# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# macros for gcc
# AS defines
AS_DEFS = 

# C defines
C_DEFS =  \


# AS includes
AS_INCLUDES = 

# C includes
C_INCLUDES =  \
-IInc \

# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -mdivide-enabled

CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"


#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32L152RETx_FLASH.ld

# libraries
LIBS = -lc -lm -lnosys 
LIBDIR = 
LDFLAGS = $(MCU) -specs=nano.specs -u _printf_float -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections

# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin


#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@

$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(HEX) $< $@
	
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(BIN) $< $@	
	
$(BUILD_DIR):
	mkdir $@		

#######################################
# clean up
#######################################
clean:
	-rm -fR .dep $(BUILD_DIR)
  
#######################################
# dependencies
#######################################
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)

# *** EOF ***

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment