I have a library which until now was just a static library, and I used it as a submodule of my programs.
Now I want to be able to install it and be able to use it both as a static and a shared library.
I installed (apart from the header files) the following files:
$ tree /usr/local/lib/
/usr/local/lib/
├── libalx
│ ├── libalx-base.a
│ ├── libalx-base.so
│ ├── libalx-cv.a
│ ├── libalx-cv.so
│ ├── libalx-gsl.a
│ ├── libalx-gsl.so
│ ├── libalx-ncurses.a
│ ├── libalx-ncurses.so
│ ├── libalx-ocr.a
│ └── libalx-ocr.so
├── pkgconfig
│ ├── libalx-base.pc
│ ├── libalx-cv.pc
│ ├── libalx-gsl.pc
│ ├── libalx-ncurses.pc
│ └── libalx-ocr.pc
The contents of (some of) the pkg-config files are the following:
libalx-base.pc:
Name: libalx-base
Description: The libalx C/C++ library (base module)
URL: https://github.com/alejandro-colomar/libalx
Version: 1~b4
Requires: libbsd-overlay
Requires.private:
prefix=/usr/local/
libdir=${prefix}/lib/
Cflags: -D _GNU_SOURCE -D _POSIX_C_SOURCE=200809L
Libs: -L ${libdir}/libalx/ -l alx-base
libalx-cv.pc:
Name: libalx-cv
Description: The libalx C/C++ library (openCV extension)
URL: https://github.com/alejandro-colomar/libalx
Version: 1~b4
Requires: libalx-gsl
Requires.private: opencv libalx-base
prefix=/usr/local/
libdir=${prefix}/lib/
Cflags: -D _GNU_SOURCE -D _POSIX_C_SOURCE=200809L
Libs: -L ${libdir}/libalx/ -l alx-cv
libalx-gsl.pc:
Name: libalx-gsl
Description: The libalx C/C++ library (GSL extension)
URL: https://github.com/alejandro-colomar/libalx
Version: 1~b4
Requires:
Requires.private: gsl libalx-base
prefix=/usr/local/
libdir=${prefix}/lib/
Cflags: -D _GNU_SOURCE -D _POSIX_C_SOURCE=200809L
Libs: -L ${libdir}/libalx/ -l alx-gsl
I'm using the library in a program that makes use of only two of the modules: base & cv.
I use the following CFLAGS and LIBS (LDFLAGS) in its Makefile:
################################################################################
# cflags
CFLAGS_STD = -std=gnu17
CFLAGS_OPT = -O3
CFLAGS_OPT += -march=native
CFLAGS_OPT += -flto
CFLAGS_W = -Wall
CFLAGS_W += -Wextra
CFLAGS_W += -Wstrict-prototypes
CFLAGS_W += -Werror
CFLAGS_PKG = `pkg-config --cflags opencv`
CFLAGS_PKG += `pkg-config --cflags libalx-cv`
CFLAGS_PKG += `pkg-config --cflags libalx-base`
CFLAGS_D = -D PROG_VERSION=\"$(PROGRAMVERSION)\"
CFLAGS_D += -D INSTALL_SHARE_DIR=\"$(INSTALL_SHARE_DIR)\"
CFLAGS_D += -D INSTALL_VAR_DIR=\"$(INSTALL_VAR_DIR)\"
CFLAGS = $(CFLAGS_STD)
CFLAGS += $(CFLAGS_OPT)
CFLAGS += $(CFLAGS_W)
CFLAGS += $(CFLAGS_PKG)
CFLAGS += $(CFLAGS_D)
export CFLAGS
################################################################################
# libs
LIBS_OPT = -O3
LIBS_OPT += -march=native
LIBS_OPT += -flto
LIBS_OPT += -fuse-linker-plugin
LIBS_PKG = `pkg-config --libs libalx-cv`
LIBS_PKG += `pkg-config --libs libalx-base`
LIBS = $(LIBS_OPT)
LIBS += $(LIBS_PKG)
export LIBS
################################################################################
And I have the following error:
gcc tmp/coins.o tmp/main.o tmp/parse.o -o cv-coins -O3 -march=native -flto -fuse-linker-plugin `pkg-config --libs libalx-cv` `pkg-config --libs libalx-base`
/usr/bin/ld: cannot find /usr/local//lib//libalx/: file format not recognized
collect2: error: ld returned 1 exit status
What is wrong? I assume the problem is in the .pc files, but I tried moving dependencies from requires to requires.private, the other way around, and other things, and none worked. For example, if I move libbsd-overlay to Requires.private, then the linker complains about not finding strnstr.
Related
I am writing a Makefile for a project where all the cpp files are in subdirectories and some of them contains spaces:
└── L0/
│ └──── Commodities API/
│ │ └──── commodities_api.h
│ └──── Communication API/
│ │ └──── communication_api.h
│ └──── L0 Base/
│ │ ├──── L0_base.cpp
│ │ └──── L0_base.h
│ └──── Provision API/
│ │ └──── provision_api.h
│ ├──── L0_commodities.cpp
│ ├──── L0_communication.cpp
│ ├──── L0.cpp
│ ├──── L0_enumerations.h
│ ├──── L0_error_manager.h
│ ├──── L0.h
│ ├──── L0_provision.cpp
This is my Makefile 'til now:
CPP = g++
LFLAGS +=
CFLAGS += -g -MMD
INCLUDES +=
CPP_SRCS := $(shell find sources -name '*.cpp' | sort | uniq | sed 's/ /\\\\ /g')
CPP_DIRS := $(shell find sources -name '*.cpp' -printf '%h\n' | sort | uniq | sed 's/ /\\\\ /g')
OBJS := $(CPP_SRCS:.cpp=.o)
OUT_DIR := out
all:
#echo $(CPP_SRCS)
#echo
#echo $(OBJS)
#echo
#echo $(CPP_DIRS)
lib.so: $(OBJS)
%.o: %.cpp Makefile
#echo "[C] $<"
$(CPP) -c $(CFLAGS) $(INCLUDES) "$<"
This is the output from the "all" target, used to print the three variables:
sources/L0/L0\ Base/L0_base.cpp sources/L0/L0_commodities.cpp sources/L0/L0_communication.cpp sources/L0/L0.cpp sources/L0/L0_provision.cpp sources/L1/Crypto\ Libraries/aes256.cpp sources/L1/L1\ Base/L1_base.cpp sources/L1/L1.cpp sources/L1/L1_login_logout.cpp sources/L1/L1_security.cpp sources/L1/L1_sekey.cpp
sources/L0/L0\ Base/L0_base.o sources/L0/L0_commodities.o sources/L0/L0_communication.o sources/L0/L0.o sources/L0/L0_provision.o sources/L1/Crypto\ Libraries/aes256.o sources/L1/L1\ Base/L1_base.o sources/L1/L1.o sources/L1/L1_login_logout.o sources/L1/L1_security.o sources/L1/L1_sekey.o
sources/L0 sources/L0/L0\ Base sources/L1 sources/L1/Crypto\ Libraries sources/L1/L1\ Base
But when I try to launch make lib.so
make: *** No rule to make target 'sources/L0/L0\', needed by 'lib.so'. Stop.
What can I do to solve this problem? Thanks!
Make use spaces as list delimiter, and there is no good way to escape it (pun intended). Your options include:
Replace the spaces with something else, like dash or underscore
Migrate from Make to e.g. CMake or SCons
For Windows you can reference any file or directory by its short path which is guaranteed not having spaces, see https://superuser.com/questions/348079/how-can-i-find-the-short-path-of-a-windows-directory-file.
i'm doing a static library in asm and i'm trying to use its fonctions after in a c main.
I don't understand why, during the make test rule, the linkage doesnt work since i checked the library dir with -L. and the include dir with -I ./include, as well as the lib itself with -static and -lasm
What can i change ?
Here is my Makefile :
NAME = libasm.a
SRC = ft_write.s \
ft_read.s \
ft_strcmp.s \
ft_strcpy.s \
ft_strdup.s \
ft_strlen.s
SRC_BONUS = ft_atoi_base.s \
ft_list_push_front.s \
ft_list_size.s \
ft_list_sort.s \
ft_list_remove_if.s
SRC_DIR = ./srcs
CC = clang
CFLAGS = -v -L. -I$(INCLUDE) -static -Wall -Wextra -Werror -lasm
NASM = nasm
NASMFLAGS = -f elf64
INCLUDE = ./include
OBJ_DIR = ./objs
OBJ = $(patsubst %.s, ${OBJ_DIR}/%.o, ${SRC})
OBJ_BONUS = $(OBJ) $(patsubst %.s, ${OBJ_DIR}/%.o, ${SRC_BONUS})
BIN = test
all : $(NAME)
$(NAME) : $(OBJ)
ar rcs $# $^
ranlib $(NAME)
#echo "$(NAME) has been created"
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
mkdir -p $(OBJ_DIR)
#echo "\033[0;32mGenerating binary..."
$(NASM) $(NASMFLAGS) $< -o $#
#echo "\033[0m"
test : main.c $(NAME)
$(CC) $< $(CFLAGS) -o $(BIN)
./$(BIN)
bonus : $(OBJ_BONUS)
ar rcs $(NAME) $^
ranlib $(NAME)
#echo "$(NAME) with bonus has been created"
clean :
rm -f $(OBJ_BONUS)
fclean : clean
rm -f $(NAME)
rm -f $(BIN)
and the trace : the problem is the undefined reference (référence indéfinie)
clang main.c -v -g -L. -I./include -static -Wall -Wextra -Werror -lasm -o test
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;#m64
Selected multilib: .;#m64
"/usr/lib/llvm-6.0/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.c -static-define -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -v -resource-dir /usr/lib/llvm-6.0/lib/clang/6.0.0 -I ./include -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-6.0/lib/clang/6.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wall -Wextra -Werror -fdebug-compilation-dir /home/salty/Documents/libasm -ferror-limit 19 -fmessage-length 106 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/main-559408.o -x c main.c
clang -cc1 version 6.0.0 based upon LLVM 6.0.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
./include
/usr/local/include
/usr/lib/llvm-6.0/lib/clang/6.0.0/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
"/usr/bin/ld" -z relro --hash-style=gnu -m elf_x86_64 -static -o test /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/crtbeginT.o -L. -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../.. -L/usr/lib/llvm-6.0/bin/../lib -L/lib -L/usr/lib /tmp/main-559408.o -lasm --start-group -lgcc -lgcc_eh -lc --end-group /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crtn.o
/tmp/main-559408.o : Dans la fonction « check_strlen » :
libasm/main.c:13 : référence indéfinie vers « ft_strlen »
/tmp/main-559408.o : Dans la fonction « check_strcmp » :
libasm/main.c:22 : référence indéfinie vers « ft_strcmp »
/tmp/main-559408.o : Dans la fonction « check_strdup » :
libasm/main.c:33 : référence indéfinie vers « ft_strdup »
/tmp/main-559408.o : Dans la fonction « strdup_test » :
libasm/main.c:42 : référence indéfinie vers « ft_strdup »
/tmp/main-559408.o : Dans la fonction « check_strcpy » :
libasm/main.c:61 : référence indéfinie vers « ft_strcpy »
libasm/main.c:64 : référence indéfinie vers « ft_strcpy »
/tmp/main-559408.o : Dans la fonction « strcpy_test » :
libasm/main.c:75 : référence indéfinie vers « ft_strcpy »
libasm/main.c:94 : référence indéfinie vers « ft_strcpy »
libasm/main.c:98 : référence indéfinie vers « ft_strcpy »
/tmp/main-559408.o:/home/salty/Documents/libasm/main.c:102 : encore plus de références indéfinies suivent vers « ft_strcpy »
/tmp/main-559408.o : Dans la fonction « list_size_test » :
libasm/main.c:176 : référence indéfinie vers « ft_list_size »
/tmp/main-559408.o : Dans la fonction « list_sort_test » :
libasm/main.c:242 : référence indéfinie vers « ft_list_sort »
/tmp/main-559408.o : Dans la fonction « list_push_front_test » :
libasm/main.c:264 : référence indéfinie vers « ft_list_push_front »
/tmp/main-559408.o : Dans la fonction « list_remove_if_test » :
libasm/main.c:287 : référence indéfinie vers « ft_list_remove_if »
/tmp/main-559408.o : Dans la fonction « atoi_base_test » :
libasm/main.c:297 : référence indéfinie vers « ft_atoi_base »
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Makefile:61: recipe for target 'test' failed
make: *** [test] Error 1
And also the dir tree:
./
├── include
│ └── libasm.h
├── libasm.a
├── main.c
├── Makefile
├── objs
│ ├── ft_atoi_base.o
│ ├── ft_list_push_front.o
│ ├── ft_list_remove_if.o
│ ├── ft_list_size.o
│ ├── ft_list_sort.o
│ ├── ft_read.o
│ ├── ft_strcmp.o
│ ├── ft_strcpy.o
│ ├── ft_strdup.o
│ ├── ft_strlen.o
│ └── ft_write.o
└── srcs
├── ft_atoi_base.s
├── ft_list_push_front.s
├── ft_list_remove_if.s
├── ft_list_size.s
├── ft_list_sort.s
├── ft_read.s
├── ft_strcmp.s
├── ft_strcpy.s
├── ft_strdup.s
├── ft_strlen.s
└── ft_write.s
I need a Makefile can be used to build a project with this kind of structure :
Multiple source folders.
all objects in a output dir.
Multiple corresponding target folders for object and dependency files.
│─inc
└─src
│ ├─lib1
│ │ ├─inc
│ │ └─src
│ ├─lib2
│ │ ├─inc
│ │ └─src
│ └─main.c
│
└─output
└─src
├─lib1
│ └─src
│ ├─ lib1_file1.o
│ └─ lib1_file2.o
├─lib2
│ └─src
│ ├─ lib2_file1.o
│ └─ lib2_file2.o
└─main.o
I tried this one, but not work.
LIBNAME=libhello.a
OUTDIR=output
CC = gcc
CFLAGS = -Wall -MD -O2 -c
LFLAGS =
INCS = -Iinc \
-Isrc/lib1/inc \
-Isrc/lib2/inc
SOURCES = src/main.c \
src/lib1/lib1_file1.c \
src/lib1/lib1_file2.c \
src/lib2/lib2_file1.c \
src/lib2/lib2_file2.c
OBJS=$(SOURCES:%.c=${OUTDIR}/%.o)
all: ${LIBNAME}
${LIBNAME}: ${OBJS}
ar crs ${OUTDIR}/$# $^
.PYONY: clean
clean:
#rm -rf ${OUTDIR}
${OUTDIR}/%.o:%.c
#mkdir -p $(#D)
#${CC} ${CFLAGS} ${INCS} $< -o $# ${LFLAGS}
Your makefile will work correctly if you give it the correct source paths. You gave it this:
SOURCES = ... src/lib1/lib1_file1.c ...
but the actual path in your directory structure is:
SOURCES = ... src/lib1/src/lib1_file1.c ...
Hello I am trying to lean make by following a makefile template in this repo
It is a project template to build for stm32f407 microcontroller. I have modified the makefile to include some standard library.
For time and resource saving, the standard library from the vendor should not be recompiled every time I run make. However, it is doing what I don't want it to do.
I am a novice about makefile.
Please take a look at my file and point me to the direction how should I fix it.
# Name of the binaries.
PROJ_NAME=project-template
######################################################################
# SETUP TOOLS #
######################################################################
# This is the path to the toolchain
# (we don't put our toolchain on $PATH to keep the system clean)
TOOLS_DIR = ../toolchain/bin
# The tools we use
CC = $(TOOLS_DIR)/arm-none-eabi-gcc
OBJCOPY = $(TOOLS_DIR)/arm-none-eabi-objcopy
GDB = $(TOOLS_DIR)/arm-none-eabi-gdb
AS = $(TOOLS_DIR)/arm-none-eabi-as
## Preprocessor options
# directories to be searched for header files
INCLUDE = $(addprefix -I,$(INC_DIRS))
# #defines needed when working with the STM library
DEFS = -DUSE_STDPERIPH_DRIVER
# if you use the following option, you must implement the function
# assert_failed(uint8_t* file, uint32_t line)
# because it is conditionally used in the library
# DEFS += -DUSE_FULL_ASSERT
##### Assembler options
AFLAGS = -mcpu=cortex-m4
AFLAGS += -mthumb
AFLAGS += -mthumb-interwork
AFLAGS += -mlittle-endian
AFLAGS += -mfloat-abi=hard
AFLAGS += -mfpu=fpv4-sp-d16
## Compiler options
CFLAGS = -ggdb
# please do not optimize anything because we are debugging
CFLAGS += -O0
CFLAGS += -Wall -Wextra -Warray-bounds
CFLAGS += $(AFLAGS)
## Linker options
# tell ld which linker file to use
# (this file is in the current directory)
LFLAGS = -Tstm32_flash.ld
######################################################################
# SETUP SOURCES #
######################################################################
# This is the directory containing the firmware package,
# the unzipped folder downloaded from here:
# http://www.st.com/web/en/catalog/tools/PF257904
STM_ROOT =../stlib
# This is where the source files are located,
# which are not in the current directory
# (the sources of the standard peripheral library, which we use)
# see also "info:/make/Selective Search" in Konqueror
MY_SRC_DIR = src
STM_SRC_DIR = $(STM_ROOT)/Libraries/STM32F4xx_StdPeriph_Driver/src
STM_SRC_DIR += $(STM_ROOT)/Utilities/STM32F4-Discovery
STM_STARTUP_DIR += $(STM_ROOT)/Libraries/CMSIS/ST/STM32F4xx/Source/Templates/TrueSTUDIO
# Tell make to look in that folder if it cannot find a source
# in the current directory
vpath %.c $(MY_SRC_DIR)
vpath %.c $(STM_SRC_DIR)
vpath %.s $(STM_STARTUP_DIR)
################################################################################
# SETUP HEADER FILES #
################################################################################
# The header files we use are located here
INC_DIRS = ./headers
INC_DIRS += $(STM_ROOT)/Utilities/STM32F4-Discovery/
INC_DIRS += $(STM_ROOT)/Libraries/CMSIS/Include/
INC_DIRS += $(STM_ROOT)/Libraries/CMSIS/ST/STM32F4xx/Include/
INC_DIRS += $(STM_ROOT)/Libraries/STM32F4xx_StdPeriph_Driver/inc/
################################################################################
# SOURCE FILES TO COMPILE #
################################################################################
# My source files
SRCS = main.c
# Contains initialisation code and must be compiled into
# our project. This file is in the current directory and
# was writen by ST.
SRCS += system_stm32f4xx.c
# Contain peripheral library source file
SRCS += stm32f4xx_vectors.c
SRCS += misc.c
SRCS += stm32f4_discovery.c
SRCS += stm32f4xx_rcc.c
SRCS += stm32f4xx_gpio.c
SRCS += stm32f4xx_syscfg.c
SRCS += stm32f4xx_exti.c
SRCS += systick.c
# Startup file written by ST
# The assembly code in this file is the first one to be
# executed. Normally you do not change this file.
ASRC = startup_stm32f4xx.s
# in case we have to many sources and don't want
# to compile all sources every time
OBJS := $(SRCS:.c=.o)
OBJS += $(ASRC:.s=.o)
######################################################################
# SETUP TARGETS #
######################################################################
TEMP_DIR = ./temp
OUT_DIR = ./out
.PHONY: all
all: $(PROJ_NAME).elf
%.o : %.c
#echo "[Compiling ] $^"
#mkdir -p ${TEMP_DIR}
#$(CC) -c -o $(TEMP_DIR)/$# $(INCLUDE) $(DEFS) $(CFLAGS) $^
%.o : %.s
#echo "[Assembling ] $^"
#mkdir -p ${TEMP_DIR}
#$(AS) $(AFLAGS) $< -o $(TEMP_DIR)/$#
$(PROJ_NAME).elf: $(OBJS)
#echo "[Linking ] $#"
#mkdir -p ${OUT_DIR}
#$(CC) $(CFLAGS) $(LFLAGS) $(foreach file, $^, $(TEMP_DIR)/$(file)) -o $(OUT_DIR)/$#
#$(OBJCOPY) -O ihex $(OUT_DIR)/$(PROJ_NAME).elf $(OUT_DIR)/$(PROJ_NAME).hex
#$(OBJCOPY) -O binary $(OUT_DIR)/$(PROJ_NAME).elf $(OUT_DIR)/$(PROJ_NAME).bin
clean:
#rm -f *.o $(OUT_DIR)/* $(TEMP_DIR)/*
flash: all
st-flash write $(OUT_DIR)/$(PROJ_NAME).bin 0x8000000
debug:
# before you start gdb, you must start st-util
$(GDB) -tui $(OUT_DIR)/$(PROJ_NAME).elf
Here is the picture of the command line
Thank you
My test project folder structure looks like:
TOPDIR
├── a
│ └── a.c
├── b
│ └── b.c
├── c
│ └── c.mk
└── makefile
I wrote a test makefile:
MAKE_DIR = $(PWD)
MODULES := a b c
SRC_DIR := $(addprefix ${MAKE_DIR}/,$(MODULES))
BUILD_DIR := $(addprefix ${MAKE_DIR}/build/,$(MODULES))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ := $(patsubst ${SRC_DIR}/%.c,${BUILD_DIR}/%.o,$(SRC))
INCLUDES := $(addprefix -I,$(SRC_DIR))
vpath %.c $(SRC_DIR)
default:
#echo "SRC DIR: ${SRC_DIR}"
#echo "Build DIR: ${BUILD_DIR}"
#echo "Source: ${SRC}"
#echo "Obj: ${OBJ}"
#echo "Includes: ${INCLUDES}"
and it output:
[GNU-GCC]howchen#linux:~/Work/c/c/test/test_make
-> make
SRC DIR: /home/howchen/Work/c/c/test/test_make/a /home/howchen/Work/c/c/test/test_make/b /home/howchen/Work/c/c/test/test_make/c
Build DIR: /home/howchen/Work/c/c/test/test_make/build/a /home/howchen/Work/c/c/test/test_make/build/b /home/howchen/Work/c/c/test/test_make/build/c
Source: /home/howchen/Work/c/c/test/test_make/a/a.c /home/howchen/Work/c/c/test/test_make/b/b.c /home/howchen/Work/c/c/test/test_make/c/c.c
Obj: /home/howchen/Work/c/c/test/test_make/a/a.c /home/howchen/Work/c/c/test/test_make/b/b.c /home/howchen/Work/c/c/test/test_make/c/c.c
Includes: -I/home/howchen/Work/c/c/test/test_make/a -I/home/howchen/Work/c/c/test/test_make/b -I/home/howchen/Work/c/c/test/test_make/c
The ${Obj} variables are NOT on *.o format, why? any problem in my makefile?
UPDATE
regarding Magnus Reftel's help, I first try:
OBJ := $(foreach sdir,$(SRC_DIR),$(patsubst $(sdir)/%.c,$(BUILD_DIR)/%.o,$(filter $(sdir)/%.c,$(SRC))))
and it output like:
Obj:
/home/howchen/Work/c/c/test/test_make/build/a
/home/howchen/Work/c/c/test/test_make/build/b
/home/howchen/Work/c/c/test/test_make/build/c/a.o
/home/howchen/Work/c/c/test/test_make/build/a
/home/howchen/Work/c/c/test/test_make/build/b
/home/howchen/Work/c/c/test/test_make/build/c/b.o
/home/howchen/Work/c/c/test/test_make/build/a
/home/howchen/Work/c/c/test/test_make/build/b
/home/howchen/Work/c/c/test/test_make/build/c/c.o
The output contain both PATH and PATH/*.c these two things, seems still NOT correct because ALL obj files go to folder c ONLY
I think I already got the source file list, which stored in $(SRC), therefore I try:
OBJ := $(patsubst %.c,%.o, $(SRC))
and it output:
Obj: /home/howchen/Work/c/c/test/test_make/a/a.o /home/howchen/Work/c/c/test/test_make/b/b.o /home/howchen/Work/c/c/test/test_make/c/c.o
which seems correct, but not because I need locate the output obj file in my build folder not source folder.
If my first try statement is not correct, where is the problem?
If second way can be improved? which way to get $(OBJ) is best for my case?
Because SRC_DIR holds a list of directories, not just one. The pattern you're matching is therefore /home/howchen/Work/c/c/test/test_make/a /home/howchen/Work/c/c/test/test_make/b /home/howchen/Work/c/c/test/test_make/c/%.c which is surely not what you want. Try combining patsubst with the foreach function. Something along the lines of
OBJ := $(foreach dir,$(SRC_DIR),$(patsubst $(dir)/%.c,getting/the/correct/build/dir/here/is/left/as/an/excercise/to/the/reader%.o,$(filter $(dir)/%,$(SRC))))