I have a project with this kind of tree:
/arch/arm/include/
/include/
I want to include files from /arch/arm/include/ with #include <arch/header.h> and files from /include with #include <header.h>.
How to do this in a Makefile ?
Thanks
this can be solved by creating a symbolic link include/arch that points to arch/arm/include
ln -s arch/arm/include include/arch
then in the makefile:
CFLAGS += -I/include
Use -I< include directory > option.
ex:
$(CC) -o $(TGT) test.c -I/include
You can add this method in your makefile. Assuming your filesystem looks like this
--------------------------------
| | |
include arch src
| |
arm makefile
|
include
LIBS_INC = -I../include
LIBS_INC += -I../arch/arm/include
Related
I am still newish to makefile patterns. I have been working on a project based on a template makefile and project structure, however I have a good sense of what all the makefile instructions are doing.
I would like to modify this so that all the .c files in /src/mains, each with a different main call gets compiled to its own executable.
The original template had no /src/mains folder, and only one file in the /src could contain a main function call.
First the project structure
root
|
|------ Makefile
|
|------ build
| |
| |--- apps
| | |--- prog
| | |--- hello
| |
| |---- objects
| |--- *.o
|
|----- include
| |--- *.h
|
|------ src
|--- *.c // for each .h (no main calls)
|--- mains
|--- prog.c (call to main)
|--- hello.c (call to different main)
Current Makefile
Without manually writing new linking rules for each make, I found no success. I am just going to leave the cleaner, unmodified makefile here, I'd like to change this so that it automatically builds all the files in mains to /build/apps
As of right now it makes an executable called prog in /build/apps, using a main function call from within /src
CXX := gcc
CXXFLAGS := -pedantic-errors -Wall -Wextra -Werror
LDFLAGS := -lm
BUILD := ./build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := prog # OP: this probably needs to become a wildcard, right?
INCLUDE := -Iinclude/
SRC := $(wildcard src/*.c)
OFLAGS := -O1 -flto
OBJECTS := $(SRC:%.c=$(OBJ_DIR)/%.o)
DEPENDENCIES := $(OBJECTS:.o=.d)
all: build $(APP_DIR)/$(TARGET)
$(OBJ_DIR)/%.o: %.c
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -MMD -o $# $(OFLAGS)
$(APP_DIR)/$(TARGET): $(OBJECTS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -o $(APP_DIR)/$(TARGET) $^ $(LDFLAGS)
-include $(DEPENDENCIES)
build:
#mkdir -p $(APP_DIR)
#mkdir -p $(OBJ_DIR)
clean:
-#rm -rvf $(OBJ_DIR)/*
-#rm -rvf $(APP_DIR)/*
If you could modify the Makefile outright that would be great, I would also appreciate any explanation so I don't need a template next time.
Also more generally, How do you like to structure your projects?
Thanks!
Make has no knowledge of programming languages at all. It is simply a tool that receives your set of rules and dependency trees.
So create a target that has all your programs as dependencies. Add it to the .PHONY target, as it is not a real file.
Also write your rules so that each program can be built independently from the others. You can have synergies, if your programs are built with common modules.
The options -p, -n and -d are helpful to debug the Makefile. Reading the manual and tutorials is a must, as always.
I have this Makefile:
CFLAGS = -ffreestanding -O2 -nostdlib -lgcc
BUILD_DIR = ../build
BIN = $(BUILD_DIR)/os.bin
LINKER_SCRIPT = linker.ld
OBJ_FILES := $(shell find $(BUILD_DIR) -iname '*.o')
.PHONY: all
all:
#make -C boot
#make -C kernel
$(CC) -T $(LINKER_SCRIPT) -o $(BIN) $(CFLAGS) $(OBJ_FILES)
After compiling (doing make in boot and kernel directories) there should be files with .o extension, however OBJ_FILES is empty. Only after calling make again OBJ_FILES contains the .o files paths which are needed to link. So my question is how do I update OBJ_FILES after compiling in the boot and kernel directories, because OBJ_FILES doesn't update/refresh.
Let's say you have following structure:
.
|-- Makefile
|-- boot
| |-- Makefile
| |-- boot.c
| `-- boot.h
|-- kernel
| |-- Makefile
| |-- kernel.c
| `-- kernel.h
`-- main.c
and your Makefile looks like this
location = $(CURDIR)
OBJ_FILES = $(shell find $(location) -name '*.o')
all: make_common
gcc -o main main.c $(OBJ_FILES)
make_common:
#make -C boot
#make -C kernel
clean:
-rm boot/boot.o
-rm kernel/kernel.o
Your source code is quite simple:
> cat boot/boot.h
int boot();
> cat boot/boot.c
int boot() {
return 1;
}
> cat kernel/kernel.h
int kernel();
> cat kernel/kernel.c
int kernel() {
return 2;
}
> cat main.c
#include "boot/boot.h"
#include "kernel/kernel.h"
int main() {
int result = boot() + kernel();
return 0;
}
"inner" Makefiles contain
> cat boot/Makefile
all:
gcc -c boot.c
> cat kernel/Makefile
all:
gcc -c kernel.c
you will get what you are looking for
> make clean
rm boot/boot.o
rm: boot/boot.o: No such file or directory
make: [clean] Error 1 (ignored)
rm kernel/kernel.o
rm: kernel/kernel.o: No such file or directory
make: [clean] Error 1 (ignored)
> make
gcc -c boot.c
gcc -c kernel.c
gcc -o main main.c ..../boot/boot.o ..../kernel/kernel.o
VAR = val
Expanded when the variable is used.
So my question is how do I update OBJ_FILES after compiling in the boot and kernel directories, because OBJ_FILES doesn't update/refresh.
OBJ_FILES variable won't change its value once make started executing the rules.
See 3.7 How make Reads a Makefile for full details:
GNU make does its work in two distinct phases. During the first phase it reads all the makefiles, included makefiles, etc. and internalizes all the variables and their values and implicit and explicit rules, and builds a dependency graph of all the targets and their prerequisites. During the second phase, make uses this internalized data to determine which targets need to be updated and run the recipes necessary to update them.
It’s important to understand this two-phase approach because it has a direct impact on how variable and function expansion happens; this is often a source of some confusion when writing makefiles.
What you can do instead is restart make once it built kernel and boot:
all: $(BIN)
$(BIN) : $(OBJ_FILES)
$(CC) -T $(LINKER_SCRIPT) -o $# $(CFLAGS) $(OBJ_FILES)
Makefile :
#$(MAKE) -C boot
#$(MAKE) -C kernel
touch $# # <---- Causes the Makefile to be re-read.
.PHONY: all
I have searched and tried a few examples to get a simple project done using non-recursive makefiles. In the past, I had used simple single directory codebase but now I am putting together an environment for more than one engineer :-)
+--app
| +-- obj/
| +-- Makefile
| +-- first.c
| +-- second.c
|
+--lib1
| +-- obj/
| +-- Makefile
| +-- foo.c
| +-- bar.c
|
+--lib2
| +-- obj/
| +-- Makefile
| +-- sample.c
Nothing fancy- just two directories (maybe a third later) with library code and multiple applications all in the "app" directory. I want to keep the .o and .d files in a separate obj/ directory for cleanliness.
I would like to be able to do a "make" in each of the sub-directories like lib1 and lib2 to verify the libraries. They will produce libabc.a and libxyz.a respectively.
I wrote some simple Makefile but my rules don't work and I tried to understand the GNU make manual but am getting lost.
lib1/Makefile:
lib_src = foo.c bar.c
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src))
libabc.a: $(lib_obj)
#echo [Archive... $(#F)]
#$(AR) -cr libabc.a $^
obj/%.c : %.c
$(CC) $(CFLAGS) -c -o $# $<
app/Makefile:
ALL_APP = first second
% : %.c libabc.a libxyz.a
$(CC) $(CLFAGS) $^ -o $#
include ../lib1/Makefile
include ../lib2/Makefile
Now, I have trouble defining the same target in each Makefile (obviously). Like I couldn't define a clean in lib1/Makefile and app/Makefile because lib1 is included there. Makes sense though I was hoping that I could do a make clean in lib1 alone.
now when I do a make in "app", there is no rule to make obj/foo.o. I guess because the paths are all bogus. "obj/" refers to the lib1/obj/ but as the Makefile got included, that is all lost.
What am I doing wrong and can I get my project built using really simple Makefiles like I have above. Most examples online are fairly complex since they try to achieve more (I believe).
Thanks in advance (and sorry for a topic that has been discussed many times). I would rather not learn automake and cmake right now, if I can avoid it. I am hoping that my project is simple enough to not warrant use of these powerful tools.
Best regards,
Let's start with lib1/Makefile:
lib_src = foo.c bar.c
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src))
libabc.a: $(lib_obj)
#echo [Archive... $(#F)]
#$(AR) -cr libabc.a $^
obj/%.c : %.c
$(CC) $(CFLAGS) -c -o $# $<
We introduce the variable HERE, and make a couple of small changes:
HERE := ../lib1
lib_src := foo.c bar.c
lib_obj := $(patsubst %.c,$(HERE)/obj/%.o,$(lib_src))
$(HERE)/libabc.a: $(lib_obj)
#echo [Archive... $(#F)]
#$(AR) -cr $# $^
$(HERE)/obj/%.c : $(HERE)/%.c
$(CC) $(CFLAGS) -c -o $# $<
This makefile will still work just as before when invoked from within lib1/. But once we make corresponding changes to lib2/Makefile, we can change app/Makefile:
ALL_APP = first second
% : %.c ../lib1/libabc.a ../lib2/libxyz.a
$(CC) $(CLFAGS) $^ -o $#
include ../lib1/Makefile
include ../lib2/Makefile
Now for the clean rule. We rename lib1/Makefile => lib1/lib1.mak and lib2/Makefile => lib2/lib2.mak, write a new lib1/Makefile:
include lib1.mak
clean:
#rm -f lib*.a obj/*
do the same in lib2/, and modify app/Makefile:
...
include ../lib1/lib1.mak
include ../lib1/lib1.mak
clean:
#rm -f $(ALL_APP)
#$(MAKE) -C ../lib1 clean
#$(MAKE) -C ../lib2 clean
(We could do it without recursion, but it would be more complicated, and there's really nothing wrong with using recursive Make in this way.)
Some further refinements are possible. For instance, it's not good to have paths hard-coded into lib1/lib1.mak and lib2/lib2.mak this way, and that can be fixed. But this is enough for one day.
My directory structure is /home/akshayaj/Desktop/System Programs/dictionary/
Inside dictionary I have 3 files:
libdictionary.c (implements all the functions except main),
libentrypoint.c (contains main()),
libdictionary.h (contains declaration of all the functions)
Both C files include the header file
Now I wrote a make file for the above project. It goes like this:-
CFLAGS=-I /home/akshayaj/Desktop/System Programs/dictionary/
libdict: libentrypoint.o libdictionary.o
cc $(CFLAGS) -o libdict libentrypoint.o libdictionary.o
libentrypoint.o: libentrypoint.c libdictionary.h
cc $(CFLAGS) -c libentrypoint.c
libdictionary.o: libdictionary.c libdictionary.h
cc $(CFLAGS) -c libdictionary.c
Now when I ran it, I got these errors:-
cc -I /home/akshayaj/Desktop/System Programs/dictionary/ -c libentrypoint.c
cc: error: Programs/dictionary/: No such file or directory
make: *** [libentrypoint.o] Error 1
Where am I going wrong?
Note:- In CFLAGS I have given the whole path because I saw it in a similar question, but that didn't work. Here is the link to that question.
C Compile Error (No such file or directory, compilation terminated)
Try to use path /home/akshayaj/Desktop/System\ Programs/dictionary/, where \ handles the space.
Think about how that command line would be parsed...
cc -I /home/akshayaj/Desktop/System Programs/dictionary/ -c libentrypoint.c
^^ ^------------------------------^ ^------------------^ ^-----------------^
| | | |
Command -I arg BAD ARG -c arg
As you can see, the space between "System" and "Programs" is read as a separator between two command args.
Your options are either:
Change the path so that the space is removed (recommended). e.g. /home/akshayaj/Desktop/System-Programs/dictionary/.
Add a backslash before the space to escape it. e.g.:
/home/akshayaj/Desktop/System\ Programs/dictionary/
As a general rule, it's not wise to use paths with spaces in them when building stuff using make, or just building stuff in general. It makes ambiguities like this hard to solve.
I'm doing a project in which I need to connect to an AR.Drone 2.0. I have a functional GUI in Java, but to control the drone I have to use it's SDK which is a C library. I wrote the necessary functions to combine Java and C via JNI, but because of the modifications I did to an example delivered with the SDK, it doesn't build anymore. It is thought to be built with a makefile (which I also have tried changing without success) running the make command. The problem is I am very new to C and makefiles, and I have searched the web a lot but have not found any solution. So here's how the library looks like:
.: Folder root
|
+ src: Sources
|
+ ARDroneLib: The AR.Drone Library
| |
| + Soft: Containing the "interesting" part of the whole lib
| | |
| | + More subdirs... (Build: contains a makefile, Common: c and h files, Lib: stuff)
| |
| + Many other subdirectories (FFMPEG, ITTIAM, VLIB, VP_SDK)
|
+ DroneControl: My own code
|
+ Source:The source files
| |
| + Navdata: Code to retrieve the navigation data
| | |
| | + navdata.c
| | + navdata.h
| |
| + Video: Code to retrieve the drone's video stream
| | |
| | + video_stage.c
| | + video_stage.h
| |
| + ardrone_testing_tool.c: Main file, containing the main function, etc.
| + ardrone_testing_tool.h: Its header
| + dronecontrol_ARDrone: My own file, containing JNI methods (also has an init() function which calls main() in ardrone_testing_tool.c)
| + dronecontrol_ARDrone: Its header
| + vars.h: Some shared variables
|
+ Build:Contains the makefile
|
+ makefile: The makefile
Here's the makefile in ./src/DroneControl/Build/:
SDK_PATH:=$(shell pwd)/../../ARDroneLib
PC_TARGET=yes
USE_LINUX=yes
ifdef MYKONOS
include $(ARDRONE_CUSTOM_CONFIG)
include $(ARDRONE_BUILD_CONFIG)
else
include $(SDK_PATH)/Soft/Build/custom.makefile
include $(SDK_PATH)/Soft/Build/config.makefile
endif
ifeq "$(RELEASE_BUILD)" "yes"
ARDRONE_TARGET_DIR=$(shell pwd)/../../../
else
ARDRONE_TARGET_DIR=$(shell pwd)/../../../Debug
endif
TARGET=linux_sdk_demo
SRC_DIR:=$(shell pwd)/../Sources
# Define application source files
GENERIC_BINARIES_SOURCE_DIR:=$(SRC_DIR)
GENERIC_BINARIES_COMMON_SOURCE_FILES+= \
Navdata/navdata.c \
Video/video_stage.c
GENERIC_INCLUDES+= \
$(SRC_DIR) \
$(LIB_DIR) \
$(SDK_PATH)/Soft/Common \
$(SDK_PATH)/Soft/Lib
GENERIC_TARGET_BINARIES_PREFIX=
GENERIC_TARGET_BINARIES_DIR=$(ARDRONE_TARGET_DIR)
GENERIC_BINARIES_SOURCE_ENTRYPOINTS+= \
ardrone_testing_tool.c
GENERIC_INCLUDES:=$(addprefix -I,$(GENERIC_INCLUDES))
GENERIC_LIB_PATHS=-L$(GENERIC_TARGET_BINARIES_DIR)
GENERIC_LIBS=-lpc_ardrone -lgtk-x11-2.0 -lrt
SDK_FLAGS+="USE_APP=yes"
SDK_FLAGS+="APP_ID=linux_sdk_demo"
export GENERIC_CFLAGS
export GENERIC_LIBS
export GENERIC_LIB_PATHS
export GENERIC_INCLUDES
export GENERIC_BINARIES_SOURCE_DIR
export GENERIC_BINARIES_COMMON_SOURCE_FILES
export GENERIC_TARGET_BINARIES_PREFIX
export GENERIC_TARGET_BINARIES_DIR
export GENERIC_BINARIES_SOURCE_ENTRYPOINTS
export GENERIC_LIBRARY_SOURCE_DIR=$(GENERIC_BINARIES_SOURCE_DIR)
.PHONY: $(TARGET) build_libs
all: build_libs $(TARGET)
$(TARGET):
#$(MAKE) -C $(SDK_PATH)/VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
mv $(ARDRONE_TARGET_DIR)/ardrone_testing_tool $(TARGET)
mv $(TARGET) $(ARDRONE_TARGET_DIR)/
$(MAKECMDGOALS): build_libs
#$(MAKE) -C $(SDK_PATH)/VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
build_libs:
#$(MAKE) -C $(SDK_PATH)/Soft/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
But when I try to make this, the make command gives me following error:
Libs already extracted
Building target static
/bin/sh: 1: ./autoConf.bash: Permission denied
make[2]: *** [build] Error 126
Checking required Ubuntu packages ...
ok.
Building ARDroneTool/Lib
Building ARDroneTool/Lib
ld ardrone_testing_tool
/usr/bin/ld: cannot find -lswscale
/usr/bin/ld: cannot find -lavformat
/usr/bin/ld: cannot find -lavcodec
/usr/bin/ld: cannot find -lavutil
collect2: ld returned 1 exit status
make[3]: *** [/home/user/workspace/AutoFlight/lib/native/DroneControl/src/DroneControl/Build/../../..//ardrone_testing_tool] Error 1
make[2]: *** [all] Error 2
make[1]: *** [build_app] Error 2
make: *** [linux_sdk_demo] Error 2
I have not been able to figure out what -lwscale, -lavformat, etc. are. I have also tried the make command as su (mainly because that "Permission denied" error), and hope this is the right place to ask this.
So does anybody have suggestions on how to get this compiled into a dynamically linked library (.so file)? Any help would be highly appreciated!
UPDATE 1: The permission denied error is now solved (thanks #eyalm)
UPDATE 2: It works now. I've rewritten the makefile but I don't know what's different now that could affect ld's path.
autoConf.bash is probably not executable. Running with su will not help. try:
# chmod a+x autoConf.bash
> /usr/bin/ld: cannot find -lswscale
> /usr/bin/ld: cannot find -lavformat
> /usr/bin/ld: cannot find -lavcodec
> /usr/bin/ld: cannot find -lavutil
> collect2: ld returned 1 exit status
It could be that these dependencies (i.e., libswscale, libavformat, libavcodec,
and libavutil) are either not present on your system, or are present
in directories that are not part of ld's standard search path.
If the dependencies are absent, then you would need to install them. On Debian-derived systems you could use the apt-file command to find the package you would need to install. For example:
% apt-file -l find libswscale.a
libswscale-dev
% apt-file -l find libavutil.a
libavutil-dev
...etc...
If these libraries are already present on your system, but are in non-standard locations,
you could use ld's -L option to add the relevant directories to its search path. For example:
% ld ..other-options... -L SEARCHDIR1 -L SEARCHDIR2 ... -lswscale -lavutil ...etc...
Note that the -L SEARCHDIR options need to appear before the -l
LIB options.