How to link objects from different directory (running ld) - c

I'm writing simple makefile project.
I'm trying to build the program in two steps:
compile source files and save object files in an different directory
link the objects into an executable
consider something simple like:
all:
gcc -o ~/some_dir/main.o -c main.c
ld -o my_program main.o
the problem is the invoke directory isn't "~/some_dir" so ld doesn't find the object file... how can I include "some_dir" in ld search path?
In the more global perspective, I have object files in various directories and I'd like to link them all together using a single linker command file.
Thanks.

You're makings things far more complicated than they need to be and should let make do more of the work for you. Below is your simple example re-written
SRCS=main.c
BUILDDIR=~/somedir
OBJS=$(SRCS:%.c=$(BUILDDIR)/%.o)
CFLAGS=-g
all: my_program
my_program: $(OBJS)
$(CC) $(CFLAGS) -o $# $^
$(BUILDDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
It defines a number of variables at the top, such as SRCS which would contain a list of your source files, the directory where you're storing the object files and generates a list of what object files you'll be building. Then it uses $(OBJS) to define that they are dependencies of my_program. The $# in the make rule is a variable meaning "the thing that we are building" and $^ is the list of dependencies. You can add other dependencies to my_program and don't need to change the command being ran.
Then there is a rule that defines how object files in $(BUILDDIR) are built from source files in the current directory.

Related

cmake convert to object file

I have a Keil project for an ARM target that I converted to a Makefile for a command line build system. I was also thinking of using cmake but I cannot find the right command/cmakey way to do the task. My Makefile converts a whole bunch of source files from different directories and creates object files out of them. Then the linker takes all these object files to make an executable taking in a bunch of flags and memory map files. So I can't just use the add_executable command. What can be the best way to do this in cmake?
EDIT:
So here is what the Makefile is trying to do(basically replicating the way Keil is building the project)
OBJECT_FILES=out/abc.o out/def.o out/xyz.o
all: binary.hex
binary.hex: binary.axf
$(ELFTOHEX) $(FLAGS) binary.hex
out/binary.axf: $(OBJECT_FILES)
ARMLINK $(MANY_FLAGS) $^ -o $#
out/abc.o: ../../../src/modules/abc.c
ARMCC -o $# $(FLAGS) $^
out/def.o: ../../../src/utilities/def.c
ARMCC -o $# $(FLAGS) $^
out/xyz.o: src/xyz.c
ARMCC -o $# $(FLAGS) $^
You can use add_library with OBJECT signature:
add_library(yourlib OBJECT sources)
and then link them into executable, for instance:
add_executable(yourexe $<TARGET_OBJECTS:yourlib>)

C actualize files through makefile all at once

I am working on project, where i use couple of .c and .h files.
I created Makefile where i actualize executable program based on changes in all of these files.
Problem is, when i use make, program is compiled, but when i execute program, it runs without any change. I need to save ( working in vim so :w ) all included files, even when i changed only one.
If i don't save all these files, program is compiled, but executes the same thing as it did before change.
Could someone explain me why is that ?
Makefile code :
CC=gcc
CFLAGS=-WALL
execFile: execFile.o functions.h newDataTypes.h
Thank you.
The reason you are not getting execFile updated is because you're NOT updating it. Or at least you don't seem to be in this particular case.
There are many ways to get about doing this. However since you are using gcc and I assume you're using gnu make the following is probably the best solution you can execute1.
Given the files:
-rw-r--r-- 1 user sudo 73 Nov 4 22:54 exeFile.c
-rw-r--r-- 1 user sudo 74 Nov 4 22:54 exeFile.h
-rw-r--r-- 1 user sudo 90 Nov 4 22:55 hello_world.c
-rw-r--r-- 1 user sudo 888 Nov 4 23:03 Makefile
cat exeFile.c
#include <stdio.h>
#include "exeFile.h"
int main()
{
hello_world();
}
exeFile.h
#ifndef _EXEFILE_H
#define _EXEFILE_H
extern void hello_world();
#endif
hello_world.c
#include <stdio.h>
#include "exeFile.h"
void hello_world()
{
printf("Hello World\n");
}
you can set up a make file that generates dependencies and ensures that the program will always be compiled correctly:
CC=gcc
CFLAGS=-Wall
SOURCES=exeFile.c hello_world.c
EXE=exeFile
OBJ=$(SOURCES:%.c=%.o)
DEPDIR := .deps
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = #mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $#
%.o: %.c
%.o: %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cc
%.o : %.cc $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cxx
%.o : %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
$(EXE): $(OBJ)
$(CC) -o $# $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) $(EXE)
dev-clean: clean
$(RM) -r $(DEPDIR)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES))))
Let's go over the relevant parts about dependencies
DEPDIR =
This implementation places dependency files into a subdirectory named .deps .
$(shell mkdir -p $(DEPDIR) 2>/dev/null)
GCC does not create subdirectories for output, this line ensures that the DEPDIR directory always exists.
DEPFLAGS = ...
These are GCC-specific flags which tell the compiler to generate dependency info.
-MT $#
Set the name of the target in the generated dependency file.
-MMD
Generate dependency information in addition to compiling. -MMD omits system headers from the generated dependencies: if you prefer to preserve system headers as prerequisites, use -MD instead.
-MP
Adds a make target for each prerequisite in the list, this avoids errors when deleting files.
-MF $(DEPDIR)/$*.Td
Write the generated dependency file to a temporary file $(DEPDIR)/$*.Td e.g. hello_world.c will generate hello_world.Td as temp dependency content for use in Makefile.
POSTCOMPILE = ...
First rename the generated temporary dependency file to the real dependency file. We do this in a separate step to side-step compile errors. Next we explicitly touch the files to avoid a gcc bug.
%.o : %.c
Delete the built-in rules for building object files from .c files, so that our rule is used instead. Do the same for the other built-in rules.
... $(DEPDIR)/%.d
Declare the generated dependency file as a prerequisite of the target, so that if it’s missing the target will be rebuilt.
$(DEPDIR)/%.d: ;
Create a pattern rule with an empty recipe, so that make won’t fail if the dependency file doesn’t exist.
.PRECIOUS: $(DEPDIR)/%.d
Mark the dependency files precious to make, so they won’t be automatically deleted as intermediate files.
include ...
Include the dependency files that exist: translate each file listed in SOURCES into its dependency file. Use wildcard to avoid failing on non-existent files.
1 See Auto-Dependencies Generation for details.
Fix:
Tell make that the executable depends only on the object file and the object file depends on the header files:
execFile: execFile.o
execFile.o: functions.h newDataTypes.h
Explanation:
In order to build your executable two steps are needed:
compilation of C source files (that include header files) to produce object files,
linking of the object files to produce the executable.
So, when changing your header files you must re-compile, that is re-built the object files, not just re-link that would produce the same executable from the same object files.
In your Makefile the dependencies are not properly defined. You did not tell make that the object file (execFile.o) shall be rebuilt when your header files change. Instead, you told it that the executable (execFile) shall be rebuilt.
First of all, your dependencies are mistaken. Your executable does not depend on the .h header files, as they are using only at compilation time. The dependencies are normally between .o files and .h files, as when you modify one .h file, the including .c file must be compiled to generate the .o file. so in case you have execFile.o (which, on lack of complete information, I'll suppose it depends on execFile.c, which #includes functions.h and newDataTypes.h, the rule should be:
execFile.o: execFile.c functions.h newDataTypes.h
As it has been pointed out in other responses, there's no need to write the command to build the .o file, as there is a default rule like this:
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
(observe there's a -c option to the compiler indicating to compile only and don't link, we'll return here below) which means that once you detect the .o is outdated (as the dependencies on .c and .hs mark) it will be compiled with the above command, which result in:
gcc -Wall -o execFile.o -c execFile.c
making the appropiate compilation.
Other thing is the dependencies of the executable file. These have to be included, as make(1) doesn't know which object files form your final executable. In this case, assuming you have your program execFile depend on execFile.o and a.o, b.o and c.o, I normally use to write:
execFile_objs = execFile.o a.o b.o c.o
execFile: $(execFile_objs)
$(CC) $(LDFLAGS) -o $# $(execFile_objs)
so any of the .os is changed (because an indirect change in a source file) the whole program is linked again (but only the touched files are compiled)
NOTE
In the case (not normal) that you have a Makefile to create a program that has only one source file and several include files you can compile each time the whole thing each time you modify one source file, in this way:
execFile: execFile.c functions.h newDataTypes.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# execFile.c
This will execute
gcc -Wall -o execFile execFile.c
Observe that there is no -c (compile only, don't link) option in this command.
There's no mention of the include files (they are included because of the #include directives in the code... and you only state here that the executable depends also (and have to be built) in case any of the .h files are modified.
Automatic dependency rules are a little confusing at first, as they induce you to think there are such rules to make any kind of file from any other kind of file (well, there are for .c -> .o files, and .c -> <nothing> to compile directly to an executable) normally you have to include dependencies in such cases when your target depends on more files than the automatic rule states. In such cases, it is very important not to include any command, so the compiler selects the automatic rule (when you don't include a command to generate the target, the make(1) program tries to use a default rule for it, or nothing at all if you have not included commands, it only assumes your dependencies are indirect through this fake target --- and, as this fake target is not built in the process, it will fail always and be followed)

Creating a Makefile in Raspbian

I'm trying to create a Makefile for my C program in Raspbian (Raspberry Pi).
My program consists of a bunch of .c and .h Files. I've looked at countless Makefiles, but I just don't unterstand how it works with multiple files. There are always .o files in the Makefile but as I understand object files are the result of compiling, so I dont have any o. Files as I am trying to compile my .c Files.
Please explain to me how this works.
Edit:
Thank you. So I tried this and it starts compiling but there are errors 'multiple definition'. Example:
These are my Files:
main.c main.h
calibration.c calibration.h
file.c file.h
frame.c frame.h
gamepad.c gamepad.h
gpio.c gpio.h
uart.c uart.h
types.h
this is my makefile:
all: main
main: main.o calibration.o file.o frame.o gamepad.o gpio.o uart.o
%.o: %.c
gcc -c -std=c99 -Wall $< -o $# -lncurses
Where can i put 'types.h'?
With every file I get errors 'multiple definitions'
A very simple but typical makefile could look like this
SOURCES = source1.c source2.c source3.c
OBJECTS = $(SOURCES:%.c=%.o)
TARGET = myExecutable
$(TARGET): $(OBJECTS)
gcc $^ -o $#
%.o: %.c
gcc -c $< -o $#
The complicated parts:
SOURCES = source1.c source2.c source3.c This is a variable definition, it assigns the string "source1.c source2.c source3.c to the variable SOURCES.
$(SOURCES:%.c=%.o) This is a shorthand for the patsubst text function. It takes all text from the $(SOUCES) variable, and replaces the pattern %.c with %.o, i.e. it takes e.g. the string source1.c and replace it with source1.o.
$(TARGET): $(OBJECTS) This makes myExecutable depend on all object files, meaning if one object file is modified then the command in the rule will be executed.
gcc $^ -o $# This calls the gcc command, passing all dependencies ($^) as arguments (that is, all object files), and tells gcc to output a file with the name of the target ($#).
%.o: %.c This is the rule that makes object files depend in their source file. So if you have source1.c then source1.o will depend on that source file.
gcc -c $< -o $# This is the command that compiles the source file (the first dependency, $<) to an object file (with the -c option) and name it as the target of the rule ($#).
Also note that if you invoke make without a specific target, then the first rule will be selected. In the case of the above makefile, it will be the $(TARGET): $(OBJECTS) rule which will make sure that all object files are build from the source files, and then link the object files into the resulting executable.
The basic syntax of a make rule is:
target … : prerequisites …
recipe
…
…
On the left of the semicolon are the targets. The targets are your object files(.o). On the right of the semicolon are the files that you will need to create this file. Those files are the source files(.c).
Lets give a basic example of what such a rule could look like.
%.o: %.c
gcc -c $< -o $#
The % sign is a wildcard. %.o means everything that ends with .o. So, if you want to make an object file, you can say make file.o, and make will try to find a rule with which it can make this target. This happens to be the rule I just showed as an example, because file.o matches %.o.
Then the recipe. This is what will be executed. Usually it's about invoking the compiler(gcc), and feeding it the source file to generate the object file. That's what we do with gcc -c $< -o $#. The $< and $# mean target and prerequisites respectively.
So, what happens when you 'just' want to build your program? You usually will type make, and it will build. The default rule that's used when you type make, is all. So, if you make a rule about all, then you can specify what files you want to create to build your program. Example of such a rule:
all: main
Then, when make is invoked, it will find that rule and finds out it needs main. To create main you need another rule:
main: file.o
This rule says that to build main, you need file.o. So, when you put all of the example rules together you get this:
all: main
main: file.o
%.o: %.c
gcc -c $< -o $#
Note that you can specify more than one file, so instead of file.o, you can say file.o main.o other_file.o etc. Every prerequisite that you specify will be made, if they can find a rule to make it.

How to write a single makefile, c files are in src and h files are in inc folder?

I am trying to write a makefile which should pick the sources from src/ and headers from inc/
~/Linuz/src: 1.c, 2.c, 3.c ...
~/Linuz/inc: abc.h, dyz.h
Please help me to create a makefile which should be available at
~/Linuz/some_other_dir/Makefile
PS: Trying to compile it for my linux machine.
Thank you for your suggestions.
all: my_program
%.o: ../src/%.c
$(CC) $(CFLAGS) -I../inc/ -c -o $# $^
my_program: 1.o 2.o 3.o
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f *.o my_program
If you put your Makefile in the ~/Linuz/some_other_dir/, the following rule
%.o: ../src/%.c
will get the c files from the ../src/ folder (~/Linuz/src/) and create the object (*.o) files in the same folder of the Makefile.
The -I../inc/ option means that the makefile canl get a header files from the ../inc/ folder (~/Linuz/inc/).
The my_program: 1.o 2.o 3.o rule means that the makefile will create the binary in the same directory of Makefile from the object files 1.o and 2.o and 3.o
From the make manual:
$^ The names of all the prerequisites, with spaces between them.
For prerequisites which are archive members, only the member named is
used (see Archives). A target has only one prerequisite on each other
file it depends on, no matter how many times each file is listed as a
prerequisite. So if you list a prerequisite more than once for a
target, the value of $^ contains just one copy of the name. This list
does not contain any of the order-only prerequisites; for those see
the `$|' variable, below.
$# The file name of the target of the rule. If the target is an
archive member, then ‘$#’ is the name of the archive file. In a
pattern rule that has multiple targets (see Introduction to Pattern
Rules), ‘$#’ is the name of whichever target caused the rule's recipe
to be run.

Makefile Subdirectories

I'm attempting to organize my project directory as follows
shell
|inc/[header files]
|obj/[object files]
|src/[source files]
|Makefile
|Executable
Everything compiles without error with everything in the root folder, but I'm running into difficulty modifying my makefile to accommodate having everything in different directories.
Here's how my makefile looked without directories
OBJS = shutil.o parser.o sshell.o
HEADER_FILES = shell.h parser.h
EXECUTABLE = sshell
CFLAGS = -Wall
CC = gcc
#Create main executable
$(EXECUTABLE): $(OBJS)
$(CC) -o $(EXECUTABLE) $(OBJS)
#Create object files
%.o: %.c
$(CC) $(CFLAGS) -I. -c -o $# $<
$(OBJS) : $(HEADER_FILES)
I've tried adding the directories into the definitions (for the obj/ and inc/ directories)
OBJS = obj/shutil.o obj/parser.o obj/sshell.o
And modified every instance of %.o and %.c to obj/%.o and src/%.c
Everything should be okay as far as I can tell, but I get this error when I go to make from the root directory
gcc -Wall -Iinc -c -o obj/shutil.o src/shutil.c
src/shutil.c:8:23: fatal error: inc/shell.h: No such file or directory
compilation terminated.
Can anyone find what I'm doing wrong here? I've been struggling with this for days.
Change -I. to -I${CURDIR}. The former adds the directory of the source being compiled to the include path list, which would be shell/src. The latter adds shell, this is probably what you want.
You may also take a look at Building multiple executables with similar rules for a micro non-recursive make framework.
Your compiler is looking for inc/shell.h, which it shouldn't. Generally, no build system dependent path should be in the source file, but the details of the build system should rather be defined via compiler flags.
That is, your source file src/shutil.c should look like:
#include "shell.h"
and your compiler invocation be the same, with the -Iinc passing the include path.
By keeping the paths out of the source files, implementation and installation of header files is much simpler.
Okay, it took some thorough frustration, but I got it now.
I changed my definitions at the top to include the file paths, as so:
OBJS = obj/shutil.o obj/parser.o obj/sshell.o
HEADER_FILES = inc/shell.h inc/parser.h
And it seems the key was -I./inc, instead of -Iinc as I expected.
obj/%.o: src/%.c
$(CC) $(CFLAGS) -I./inc -c -o $# $<

Resources