Problems with inclusion of C header file with automatically generated makefile - c

I have started to develop the C language software in the Xilinx Vitis IDE which Eclipse based. Organization of my project is following:
-Application
-Drivers
-drivers
-Adc
-Pwm
-Pwm.c
-Pwm.h
-Utils
-Bits.h
-Maths.h
All the directories i.e. Application, Drivers and Utils are linked into the workspace via "Link folder" option. The only one way how I was able to include the Bits.h into the Pwm.c was to specify the whole path to the Bits.h on my disk. Otherwise the compiler reports fatal error: Bits.h: No such file or directory.
The compilation process is managed by the automatically generated makefile with this content:
# Makefile generated by Xilinx.
PROCESSOR = ps7_cortexa9_0
LIBRARIES = ${PROCESSOR}/lib/libxil.a
BSP_MAKEFILES := $(wildcard $(PROCESSOR)/libsrc/*/src/Makefile)
SUBDIRS := $(patsubst %/Makefile, %, $(BSP_MAKEFILES))
ifneq (,$(findstring win,$(RDI_PLATFORM)))
SHELL = CMD
endif
all: libs
#echo 'Finished building libraries'
include: $(addsuffix /make.include,$(SUBDIRS))
libs: $(addsuffix /make.libs,$(SUBDIRS))
clean: $(addsuffix /make.clean,$(SUBDIRS))
$(PROCESSOR)/lib/libxil.a: $(PROCESSOR)/lib/libxil_init.a
cp -f $< $#
%/make.include: $(if $(wildcard $(PROCESSOR)/lib/libxil_init.a),$(PROCESSOR)/lib/libxil.a,)
#echo "Running Make include in $(subst /make.include,,$#)"
$(MAKE) -C $(subst /make.include,,$#) -s include "SHELL=$(SHELL)" "COMPILER=arm-none-eabi-gcc" "ASSEMBLER=arm-none-eabi-as" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra -g3 -O0"
%/make.libs: include
#echo "Running Make libs in $(subst /make.libs,,$#)"
$(MAKE) -C $(subst /make.libs,,$#) -s libs "SHELL=$(SHELL)" "COMPILER=arm-none-eabi-gcc" "ASSEMBLER=arm-none-eabi-as" "ARCHIVER=arm-none-eabi-ar" "COMPILER_FLAGS= -O2 -c" "EXTRA_COMPILER_FLAGS=-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra -g3 -O0"
%/make.clean:
$(MAKE) -C $(subst /make.clean,,$#) -s clean
clean:
rm -f ${PROCESSOR}/lib/libxil.a
It is obvious that my "solution" is unacceptable. So I would like to ask you for an advice how to resolve this issue correctly. Thanks in advance for any suggestions.

You can add include paths to the project. These are paths where the compiler will search for include files. Any include file located in one of the directories in the include paths list should be found; you do not need to specify its path when including the file.
How you do this in the Xilinx environment appears to depend on how your project is set up.
If it is a managed make project:
Properties -> C/C++ Build
In "Tools Settings" tab select the "Include Paths"
If it is a standard make project:
Properties->C/C++ Include Paths and Symbols>
Then "Add External Include Path"
If it gives you the option to add the path as absolute or relative path, choose relative path; this allows another user to put the project, with the same internal directory structure, in a different place on the hard drive, which is what you want. In the screenshots in the documentation I referenced, the paths appear relative.
See this documentation for more details, screenshots, etc.
Note: I am answering based on the documentation; I have not worked with this IDE myself.
Note also that you can use relative paths in an #include directive, but they are not necessarily relative to the location of the file that includes them. They are more likely to be relevant to the root of the project (basically, wherever 'make' will be effectively run).

Related

implement subdirectory in makefile

WARNFLAGS = -W -Wall -Werror
OPTFLAGS = -O3
CFLAGS += $(WARNFLAGS) $(OPTFLAGS)
CC = gcc
DOBJS = /Desktop/Sysprog/Uebungsblatt6/a4/awesome2/awesome.h /Desktop/Sysprog/Uebungsblatt6/a4/awesome3/awesome.h
#MODULES = awesome2 awesome3
$(OBJS): /Desktop/Sysprog/Uebungsblatt6/a4/awesome2/awesome.h /Desktop/Sysprog/Uebungsblatt6/a4/awesome3/awesome.h
awesome:
$(CC) $(CFLAGS) awesome.c -o $#
clean:
rm -f *~ *.o awesome
I have tried everything, but donĀ“t know how to include a headerfile from a subdirectory, into makefile.
My awesome.c is in directory a4, awesome.h is in directory awesome2 and awesome3, and I want to compile awesome.c, but if I compile it does do not find awesome.h. How can I make it work.
You need to include the .h file in your .c file.
There are two forms of the include directive you can put in your C source file:
#include "path/filename.h"
This version, with the file to include between quotes, includes a file relative to the directory of the .c file. You could of course put an absolute path there, but that is not recommended as you have to adapt it whenever you move the code/.h-file to another machine or place.
#include <path/filename.h>
With the file to include between < and >, the file will be searched relative to an include path you provide the compiler. In your case:
INC= /Desktop/Sysprog/Uebungsblatt6/a4/
$(CC) $(CFLAGS) awesome.c -o -I$(INC) $#
The -I switch is used by many compilers to provide it with a standard include path. It may be different for your compiler (and a guru may provide some adjustment, as my Make is rusty).

How to add headers to a Makefile?

I have the following Makefile. How to add also some header files that I have in the project folder (e.g. header1.h with its relative header1.c) ?
CC := gcc
CFLAGS := -Wall -Wextra -Wpedantic -O3
CFILES := $(shell ls *.c)
PROGS := $(CFILES:%.c=%)
all: $(PROGS)
.PHONY: all clean
clean:
rm -f *~ $(PROGS)
Even adding them one by one would be ok (no need to use the wildcard).
I suppose I should edit the following line:
CFILES := $(shell ls *.c)
But how?
First, don't use $(shell ls *.c) but better $(wildcard *.c). Please take time to read the documentation of GNU make
Then, you usually don't want headers in Makefile-s, you want dependencies on headers.
For example, if you know that foo.o needs both foo.c and header.h (because you have some #include "header.h" in your foo.c) you would add a dependency like
foo.o: foo.c header.h
in your Makefile... See also this example.
There is some way to automate such dependencies, using GCC options; read about Invoking GCC, notably preprocessor options like -M
(details depend upon your project and coding conventions)
For a simple project of a few dozen of files totalizing a few thousand lines, you should first write your Makefile explicitly, with the dependencies. Later you might automatize that (but in simple projects that is not worth the trouble).
In some cases, a header file *.h or a C file *.c is generated by some utility (e.g. swig, bison, ... or your own script or program). Then you add appropriate specific rules in your Makefile.
You might use make --trace or remake with -x to debug your Makefile.
Look for inspiration into the source code of some existing free software project (e.g. on github).

What is Eclipse CDT is doing with 'make' under the hood

I'm on Windows 7 and have MinGW/gcc installed. I'm using the Eclipse CDT plugin to compile and build my first simple C programs, and am trying to follow what exactly the plugin is doing under the hood.
I create a new "Hello World!" C project with the following directory structure:
helloworld/
src/
helloworld.c
Where helloworld.c is:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
puts("Hello World!");
return EXIT_SUCCESS;
}
So I created a Run Configuration in Debug Mode (as opposed to "Release Mode", not a "Debug Configuration" in typical Eclipse parlance!) and ran my app, and it works beautifully, printing "Hello World!" to the Eclipse console.
Now I'm looking on my file system and the file/project structure is like so:
helloworld/
src/
helloworld.c
Debug/
src/
helloworld.d
helloworld.o
subdir.mk
helloworld.exe
makefile
objects.mk
source.mk
I assume that running my Run Configuration in Eclipse (hence compiling/building/running helloworld inside Eclipse) created everything under Debug. Furthermore I assume that helloworld.d and helloworld.o are compiled binaries, and that helloworld.exe is the packaged executable containing those binaries and everything they'red linked to (stdio and stdlib). I also assume makefile is the actual Make file (buildscript), and that the *.mk files are somehow inputs to that buildscript. So, for starters, if any of those assumptions are wrong, please begin by correcting me!
When I open makefile I see this:
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include src/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: helloworld
# Tool invocations
helloworld: $(OBJS) $(USER_OBJS)
#echo 'Building target: $#'
#echo 'Invoking: Cross GCC Linker'
gcc -o "helloworld" $(OBJS) $(USER_OBJS) $(LIBS)
#echo 'Finished building target: $#'
#echo ' '
# Other Targets
clean:
-$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) helloworld
-#echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include ../makefile.targets
Please note: I am not looking for someone to explain to me how Make works, I can RTFM for that ;-)
I am just trying to understand what it would take to compile, build and run helloworld from the command-line, outside of Eclipse. What command line invocations would I need to accomplish this, and why? Once I see that, combined with perusing Make docs, I should be able to fill in the gaps and understand everything that is going on.
That depends a bit on the paths that Eclipse generates in the files source.mk and objects.mk but most likely you need to cd into the Debug folder.
Inside of that, you can then run make all to compile the project.
If Eclipse generated absolute paths, you can use make -f .../path/to/helloworld/Debug/makefile all from anywhere.
The *.o files are the object file(s) created by compilation. these files are typically build by a command like:
Gcc -ansi -Wall -pedantic -c helloworld.c -o helloworld.o
(apologies foe capitalization of gcc, my iPad insists on correct my typing)
The *.exe is the actual executable, which may or may not contain the library functions. This depends on static versus dynamic linking. The executable is created typically by:
Gcc helloworld.o -o helloworld.exe
The *.d files are dependency files, built by gcc attempting to determine dependencies between files, typically built with the following command
MAKEDEPEND = gcc -M $(CPPFLAGS) -o $*.d $<
(Rule taken from make online documentation).
So,to answer your final question, to compile from the command line, a command like:
Foo gcc -ansi -WAll -pedantic helloworld.c -o helloworld.exe
Should do the trick for you. Note, the flags to the compiler are the minimum that I like to use, you will probably have a different set of switches.
Hopes this help,
T

What is wrong with this Makefile? (header files not found)

I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)

Why does this makefile not apply includes to all objects?

This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.

Resources