Cmake Debug flag condition for one build with multiple projects - c

I need help in compiling my projects with debug flag.
I have compiled with -DCMAKE_BUILD_TYPE=Debug .. in build folder.
I am able to run the binary after the compilation. However, the Debug flag is not being turned on. I am sort of stuck at this point. Any kind soul is willing to give a kind advise or direction on this?
My build tree is as such:
project
|------ CMakeLists.txt (The main Cmake)
|------ ProjectA
| |----- src
|.c files
| |----- include
|.h files
| |----- CMakeList.txt
|------ ProjectB
| |----- src
|.c files
| |----- include
|.h files
| |----- CMakeList.txt
|
|------ build
| |----- ...
|------ bin
| |---- executables
I have set my cmake flag in the project A and B as such:
#cmake output directory
...
#compiler
...
set(CMAKE_C_FLAGS "... -DDEBUG ...")
#Linking
...
#add executables
...
My top level CMakeLists.text is such:
project(..)
...
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)

In main CMakeLists.txt add below line
## Configure debug flag to enable debug log
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall")
Generate Makefile:
cmake ..... -DCMAKE_ARCH="x86_64" -DCMAKE_BUILD_TYPE=Debug

Related

How to build target by name in CMake?

I have cmake project that consist of multiple targets.
MyProject/
/target1
/Some stuff
/CMakeLists.txt // here add_executable(target1 main.c)
/target2
/target3
...
CMakeLists.txt // root CMakeLists.txt file
/build // folder for build files
I wand to build only target1 and put it into /build folder inside my project
I could build all targets
[MyProject/build]$ cmake ..
[MyProject/build]$ make
How to build only target1?
I guess it must be something like this?
[MyProject/build]$ cmake ..
[MyProject/build]$ cmake --build . --target target1 -- -j 12
Suppose you set an executable inside CMakeLists.txt
add_executable( my_exe ${my_exe_sources} )
Then you can call make my_exe -j 2
Your commands should work fine
cmake ..
cmake --build . --target target1 -- -j 12
will build target1 and its dependencies only.

How to write "CMakeLists.txt" for a big project with multiple subdirectories?

I am working on a simulation project: Taking an embedded C codebase from a target platform and trying to simulate it on a Host computer for debugging or single stepping into the code.
OS: Ubuntu Linux 14.04, IDE: CodeLite, Makefile Generator: Cmake. I am confused about how to write CMakeLists.txt for the project. Following is the structure of codebase (it's all written in C):
|ARQSim\
|-->ARQSim.h
|-->ARQSim.c
|-->BaseStationCode\
| |->downlink.c
| |->neoncopy.c
| |->armCore\
| | |->common\
| | | |->Bsconfig.h
| | | |->config.h
| | |->MacSource\
| | | |->lib\
| | | | |->arqCommon.h
| | | | |->OverTheAir.h
| | | |->source\
| | | | |->beacon.c
| | | | |->proxyDhcp.c
| | | | |->ARQ\
| | | | | |->arqCommon.c
| | | | | |->arqInterface.c
| | | | | |->fragmentation\
| | | | | | |->fragBookkeeping.c
| | | | | | |->fragProcessAck.c
| | | | | |->reassembly\
| | | | | | |->reasmBookkeeping.c
| | | | | | |->reasmProcessAck.c
I am totally new to Cmake. I have read up a lot of resources on CMake and threads here on StackOverflow. But I get confused every time. Few questions I have:
Do I need only one CMakeLists.txt at root directory or every directory needs a different CMakeLists.txt file?
How to add the source files recursively in CMakeLists.txt?
What are the basic commands I need to put in CMakeLists.txt for MakeFile generation?
An example based on the structure of code mentioned above would be appreciated.
Do I need only one CMakeLists.txt at root directory or every directory needs a different CMakeLists.txt file?
You would typically have one at each level of the tree where it makes sense
eg:
root/
+--- CMakeLists.txt // your root CMakeLists
+--- foo/
| +--- CMakeLists.txt // foo component's CMakeLists
| +--- foo.c
| +--- tests/
| +--- CMakeLists.txt // foo test's CMakeLists
| +--- foo_tests.c
+--- bar/
+--- CMakeLists.txt // bar component's CMakeLists
+--- bar.c
+--- bar_impl/ // no CMakeLists for this dir, it is part of bar
| +--- bar_impl.c
+--- tests/
+--- CMakeLists.txt // bar test's CMakeLists
+--- bar_tests.c
Project root CMakeLists.txt:
In your project root CMakeLists.txt you specify minimum cmake requirement, the project name, and include the subdirectories which have your various components in them
root/CMakeLists.txt:
cmake_minimum_required (VERSION 3.5)
project (my_project C)
add_subdirectory(foo)
add_subdirectory(bar)
Component CMakeLists.txt:
Then in each component subdirectory, you have another CMakeLists.txt file where you add libraries, executables etc
root/foo/CMakeLists.txt:
add_library(foo foo.c)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(tests)
root/foo/tests/CMakeLists.txt:
add_executable(foo_test foo_tests.c)
target_link_libraries(foo_test foo)
You follow this structure for bar etc...
root/bar/CMakeLists.txt:
add_library(bar
bar.c
bar_impl/bar_impl.c)
target_include_directories(bar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(bar foo)
add_subdirectory(tests)
root/bar/tests/CMakeLists.txt:
add_executable(bar_test bar_tests.c)
target_link_libraries(bar_test bar)
Generating build files:
To bootstrap your build, you point cmake at your root/CMakeLists.txt
cd root
mkdir build
cd build
cmake ..
(or use your ide's build manager to generate its build configuration)
Further reading
For details on the various functions I've used here, consult the documentation:
cmake_minimum_required
project
add_subdirectory
target_include_directories
target_link_libraries
Finally, to answer your second question:
How to add the source files recursively in CMakeLists.txt?
This is not recommended (see this discussion for further details).
It is better to explicitly list each file you want to include in your target.
Note that if you have source files in several separate directories, yet they all belong in the same logical target, then you don't need a CMakeLists.txt file for each directory - just list the subdirectory in the filename
Example:
foo/
+--- foo.c
+--- bar.c
+--- baz/
+--- baz.c
+--- bang.c
If you want a single target foo for all the above files, you would create it as follows:
add_library(foo
foo.c
bar.c
baz/baz.c
baz/bang.c)
Or if you really wanted to use a variable to store the list of SRCS
set(SRCS
foo.c
bar.c
baz/baz.c
baz/bang.c)
add_library(foo ${SRCS})
I was also looking for a more general way of adding CMakeLists.txt files to my projects. I decided to write a CMake generator (partly because I wanted to understand how CMake works):
https://github.com/Aenteas/cmake-generator
It has a couple of additional features such as creating python wrappers (SWIG).
Writing a generator that suits everyone is impossible but I hope it will give you an idea in case you want to make your customized version.

How to link files within other directories?

I have a project that is big enough to benefit from having its files classified by directory. I'm trying to build one kernel module out of all of them.
The documentation states the following:
--- 3.6 Descending down in directories
A Makefile is only responsible for building objects in its own
directory. Files in subdirectories should be taken care of by
Makefiles in these subdirs. The build system will automatically
invoke make recursively in subdirectories, provided you let it know of
them.
To do so, obj-y and obj-m are used.
ext2 lives in a separate directory, and the Makefile present in fs/
tells kbuild to descend down using the following assignment.
Example:
#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/
If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular)
the corresponding obj- variable will be set, and kbuild will descend
down in the ext2 directory.
However, this seems to be different from what I need. What comes out of this is two independent .ko files; one in each directory, each an amalgamation of the object files in its own directory.
This is my project (simplified):
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- subdir
|
+--- Makefile
|
+--- bar.c
I would think that ending up with something like this would be reasonable:
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- foo.o (containing foo.c's stuff)
|
+--- subdir
| |
| +--- Makefile
| |
| +--- bar.c
| |
| +--- bar.o (containing bar.c's stuff)
|
+--- kernel-module.ko (containing foo.o and subdir/bar.o)
What I really end up with is this:
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- foo.o (containing foo.c's stuff)
|
+--- subdir
| |
| +--- Makefile
| |
| +--- bar.c
| |
| +--- bar.o (containing bar.c's stuff)
| |
| +--- bar.ko (containing bar.o)
|
+--- kernel-module.ko (containing only foo.o)
I'm hoping that building one module per directory is not a fundamental assumption of Kbuild's design. Shipping several modules sounds like a lot of mess for no gain.
This is my root Makefile:
KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
all:
make -C ${KERNEL_DIR} M=$$PWD
modules:
make -C ${KERNEL_DIR} M=$$PWD $#
clean:
make -C ${KERNEL_DIR} M=$$PWD $#
This is subdir/Makefile:
obj-m += bar.o
This is foo.c:
int external_function(void);
int test(void)
{
return external_function();
}
And this is subdir/bar.c:
int external_function(void)
{
return 4;
}
make (in the root directory) spits the following warning:
WARNING: "external_function" [(...)/kernel-module.ko] undefined!
And my attempts to insert kernel-module.ko are refused:
$ sudo insmod kernel-module.ko
insmod: ERROR: could not insert module kernel-module.ko: Unknown symbol in module
$ dmesg | tail -1
[11688.540153] kernel_module: Unknown symbol external_function (err 0)
How do I tell Kbuild that subdir/bar.o is supposed to be part of kernel-module.ko and not its own module?
One solution is to append bar's object file to the kernel module's object listing. The problem with this code:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
Is that it's telling Kbuild to descend to subdir/, but it's not telling it to include the results of that in kernel-module.
This would fix that:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o subdir/bar.o
However, I don't like this solution at all because it breaks the DRY principle: It means bar.o has to be named twice; one in /Makefile and the other one in /subdir/Makefile.
Also, this solution doesn't prevent Kbuild from creating the redundant subdir/bar.ko module.
Finally, certain documentation states that it is "NOT recommended practice" for some completely unstated reason.
So this solution is pretty bad. I don't think I will stick to it.
Another solution (which branches from the previous one) is to just delete subdir/Makefile and, within the root Makefile, instead of this:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
do this:
obj-m += kernel-module.o
kernel-module-objs += foo.o subdir/bar.o
This fixes the DRY issue and prevents subdir/bar.ko from being generated but still suffers from discouraged practice.
I will stick to this solution in the meantime, but since neither of them is ideal, I guess I'll leave the question open for a while.

C Code analysis with vera++

I would use vera++ to analyse several C libraries that I developed.
These libraries are contained into 4 different folders and there isn't a main.c file.
It is possible to check the libraries code with vera++? Or vera++ requires the main.c?
Thanks
To check a file .c or .h run vera++ as
vera++ my_file.c
If you want to run only specific rules you can do
vera++ -R T013 my_file.c
I use the following to run vera++ on all files in src/ and include/ matching *.c and *.h
find src/ include/ -type f -regextype sed -iregex ".*/*\.\(c\|h\)" -print | xargs vera++

Build file (Rake or Make?) for building a few simple libraries with common options?

So, I have a set of different libraries in C and C++ that I need to build with some common options. My current "template" makefile looks something like so:
#Change this for different MCUs. Standard includes atmega328
VARIANT = ../variants/standard
HDRS=RedBot.h
OBJS=RedBot.o RedBotAccel.o RedBotMotor.o RedBotSensor.o
CPPFLAGS = -I../arduino/ -I./ -DF_CPU=16000000UL -Os -mmcu=atmega328p
CC=avr-gcc
CPP=avr-g++
AR=avr-ar
default: libredbot.a
libredbot.a: ${OBJS}
${AR} crs libredbot.a $(OBJS)
.c.o: ${HDRS}
${CC} -I ${VARIANT} ${CFLAGS} -c $*.c
.cpp.o: ${HDRS}
${CPP} -I ${VARIANT} ${CPPFLAGS} -c $*.cpp
clean:
rm -f ${OBJS} core a.out errs *.a
I place the makefile in the same folder as all the sources. However, this is ugly for a few reasons. For one, it's only a template. I have to duplicate this across about 15 libraries. And I need for the compilation options to be very easy to change across all libraries, because multiple targets is common. Currently, the best thing I can think of is making a root makefile with the options passed to each library makefile. However, I still have to keep track of all the files (the OBJS bit). And not all libraries are capable of being built on all targets.
Can someone point me either to a more comprehensive makefile, or possibly an example build file for something like Rake that could handle this?
Make one (or more) template files that you put in a common base folder, then in each project directory place a makefile which sets flags specific to the library being built, as well as listing only the source files. Then it includes the common makefile(s) templates, which contains implicit rules and variables that takes the local flags for building.
So a structure something like this:
project root
|-- makefiles
| |-- rules.mk
| |-- vars.mk
| |-- exe.mk
| `-- lib.mk
|-- libraryA
| |-- Makefile
| `-- (other sources and headers for this library)
|-- libraryB
| |-- Makefile
| `-- (other sources and headers for this library)
|-- programA
| |-- Makefile
| `-- (other sources and headers for this program)
`-- programB
|-- Makefile
`-- (other sources and headers for this program)
The rules.mk contains rules such as clean or the implicit build rules like .c.o.
The vars.mk contains global variables and uses local flag variables to set the global flag variables like CFLAGS.
The exe.mk contains rules to make an executable program.
The lib.mk contains rules to make a library.
A local makefile will then look something like this:
LOCAL_CFLAGS = <some C flags specific to just this library/executable>
# Other local flags, e.g. LOCAL_LDFLAGS, LOCAL_LIBS, etc.
TARGET = <name of target executable/library>
LOCAL_SOURCES = <list of all source files for $(TARGET)>
LOCAL_HEADERS = <list of all headers>
include ../makefiles/vars.mk
include ../makefiles/rules.mk
include ../makefiles/exe.mk # If making an executable
include ../makefiles/lib.mk # If making a library
# Note: Don't include both the above two files
The vars.mk file can look something like this
CFLAGS = <some common C flags>
CFLAGS += $(LOCAL_CFLAGS)
# All other flag variables
HEADERS = $(LOCAL_HEADERS)
CFILES = $(filter %.c,$(LOCAL_SOURCES))
CXXFILES = $(filter %.cpp,$(LOCAL_SOURCES))
OBJECTS = $(CFILES:%.c=%.o)
OBJECTS += $(CFILES:%.cpp=%.o)
I ended up writing my own little hacky thing with Ruby to get this done easily. You can draw inspiration from it here: https://github.com/Earlz/make-wiring/blob/master/build.rb
Basically, it consists of a "template" makefile that takes many environment variables. And the build.rb script just passes them off to the makefile without you having to manually specify everything on the command line. Usage thus would look like so:
./build.rb build redbot
./build.rb build arduino
or whatever, and all flags and arguments are neatly contained within build.rb, instead of being spread among dozens of makefiles or being manually specified on the command line

Resources