Make clangd aware of macros given from the compiler - c

I have two executables that are build from the same source (a client and a server) and they're built with the compile options -D CLIENT=0 -D SERVER=1 for the server and -D CLIENT=1 -D SERVER=0 for the client. If I do something like
if (CLIENT) {
// Client specific code
}
clangd complains that CLIENT is not defined. Is there a way to make clangd aware of those macros? (The code compiles just fine, the errors are from clangd, not the compiler)

Is there a way to make clangd aware of those macros?
From getting started with clangd:
Project setup
To understand source code in your project, clangd needs to know the
build flags. (This is just a fact of life in C++, source files are not
self-contained.)
By default, clangd will assume that source code is built as clang
some_file.cc, and you’ll probably get spurious errors about missing
#included files, etc. There are a couple of ways to fix this.
compile_commands.json
compile_commands.json file provides compile commands for all source
files in the project. This file is usually generated by the build
system, or tools integrated with the build system. Clangd will look
for this file in the parent directories of the files you edit. Other
tools can also generate this file. See the compile_commands.json
specification.
compile_commands.json is typically generated with CMake build system, but more build systems try to generate it.
I would suggest moving your project to CMake, in the process you will learn this tool that will definitely help you in further C-ish development.
compile_flags.txt
If all files in a project use the same build flags, you can put those
flags, one flag per line, in compile_flags.txt in your source root.
Clangd will assume the compile command is clang $FLAGS some_file.cc.
Creating this file by hand is a reasonable place to start if your
project is quite simple.
If not moving to cmake, create a compile_flags.txt file with the content for example like the following, and clangd should pick this file up:
-DCLIENT=1
-DSERVER=1

Related

How does CMake add_executable work internally (dependencies and automatic source discovery)?

I am working on my first CMake/C project and I crossed a problem with my build that makes me re-question how compilation work.
I would like people to explain to me what exactly happens when you call add_executable and how make builds C file dependencies.
What I thought
I thought that, when calling add_executable (name, sources), CMake would see sources as a superset of the necessary source files to build the target name. So internally, he analyzes the REAL MINIMAL dependencies, by analyzing the file containing main, and recursively adding the included .h files, with their associated declarations in the .c files.
What seem to happen (I want confirmation)
CMake sees sources as the real minimum dependencies for the executable. It seems it will compile ANYTHING in sources, whether or not it is used anywhere.
Consequence
This for me is really annoying. In my project I use source discovery, meaning that anything in the src directory is added to the sources. Then, if I want to compile a unit test (make this_unit_test), it is, in fact, going to compile every .o file in my source directory instead of compiling the necessary files only. Which means that if something does not build in a part of my project, I can not build any tests anymore.
What can I do?
If CMake is indeed done in a way that you need to specify yourself the minimal dependencies for any executable, how can I still use automatic source/test discovery? The best solution would be from the CMakeList file, a function that takes a list of source files, and return the subset of it corresponding to what is actually included at some point by the file containing main. What do people do to resolve that problem?
No, CMake does not scan for minimal source dependencies for your executable, and how could it? CMake doesn't scan the source files, and has no knowledge about what includes/definitions your executable ultimately needs or doesn't need. This functionality would have to happen at the compilation stage (after CMake completes), because it is the pre-processor/compiler that parses your source files and interprets them for semantics (meaning). There are static analysis tools out there that can help achieve something like this, such as include-what-you-use.
Using source discovery techniques in CMake (such as file(GLOB ...)) can be error prone:
As you have seen, the source discovery mechanism may grab files that you do not need for building a particular target.
Even worse, source discovery may leave out files that are required for building a particular target.
The CMake documentation itself even warns against doing this!
Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
As a general rule of thumb, it is always safest to list each individual file that is required for each target explicitly, for example:
add_executable(MyExe
main.c
MyHelperFunctions.c
MyOtherStructs.c
)

Compile entire C project instead of few files

I have an entire library made in C. It has almost 10 folders with a lot of files.
I have created a filename.c file in root folder and trying to compile it in mac using gcc test.c -o test however its not including header files. Generally I have to add all the header files gcc test.c libaudio.c -o test
How can I compile entire project instead of just one file.
Makefiles will solve your problem. You can create your own rules to clear the project (remove the generated files), build the project indicating where is your compiler (compile the source files located in some specific path, extension, etc), set the output path and so on, without typing a large compilation order.
https://www.gnu.org/software/make/manual/make.html
Edit: There you will be able to find how to add shared, static or raw libraries to your proyect through makefiles.
Use a Makefile. make the utility the reads the configuration within the Makefile will automate the running of the individual commands, such that you only need to name the item you wish to be rebuilt.
make myprogram
And make will use the dependency information stored in the Makefile's rules to determine what other elements are "out of date", rebuilding those and assembling them into myprogram.
This is a decent "first time" tutorial for "make".
Here is the full blown documentation for "make"
Once you master the concepts within make, you can then use other tools that make maintaining Makefiles either easier, more portable, or both.
Some tools that improve upon "make" include "cmake", "automake", "the autotools collection", "scons", "waf", "rake", "doit", "ninja", "tup", "redo", and "sake". There are more, and some are programming language specific, or limited to a particular enviornment.
The reason I recommend "make" over the others is because "make" is a baseline that will always be present, and the features in the other tools are often not understood or recognized to be needed until you get enough experience with "make".
In C, the concept of project is not part of the language, it depends generally of the tools / platform / library you have to build.
On Linux based platforms, you may have a makefile describing the project, or the library may have a cmake script.
You should be able to find the build instructions in you library documentation.
I definitely recommend the make approach as it is scalable.
If you really only have a couple of files, gcc will accept multiple .c files on the command line and link them all to generate one executable.

Embox compilation and flashing

I am interested in attempting to compile, package and flash Embox to an MCU, from either a Windows or Mac machine (cross-compilation), via JTAG, and I have a number of concerns.
Observe what I believe to be the normal way of writing Embox apps and deploying/flashing them to an MCU:
As you can see, in my understanding above:
Embox source code is compiled (via make) into some file (Object file?), <file>.<ext>
At the same time, my app's source code is cross-compiled (somehow) into an Object file (myapp.o) that is compatible with Embox
Some tool combines: (a) the Embox <file>.<ext> produced by make, (b) myapp.o and (c) any other libs I specify. It takes these as inputs and produces a single application image that is ready to be flashed via JTAG
My concerns, also identified in the illustration:
What is the exact name and file extension of the Embox "artifact" produced by running make on Embox source code? Is this artifact different depending on whether you are on Windows or Mac? What tools besides make are necessary to produce this artifact?
What is this magic tool that takes in Object/interim files and produces a single app image? What is the exact name and file extension of this app image?
What tools do I need to cross-compile myapp.c and myapp.h into a myapp.o that is Embox compatible?
I'm one of the Embox developers, who is responsible for build tools.
Basile has given a correct overview of the process as a whole:
the source is compiled into a relocatable embox.o with ld -r,
then linked into embox ELF binary,
... which in turn is additionally transformed into .bin and .srec that are used for flashing quite often.
Binary artifacts go into build/base/bin.
Let me add few details.
First of all, you'll probably won't need to dig into the details of linking your application against Embox. Instead, the proper way is to integrate your app into Mybuild - the Embox build system - and let it handle low-level linkage details for you. So it's worth building vanilla Embox first and see it running on an emulator.
Building and running Embox for ARM
I would suggest you to start with arm/qemu template. This won't fit into your MCU, but if your application doesn't do something unusual, it would be easier to test it on QEMU before porting it to the target MCU. Anyway, this is a good starting point to check that a dev environment is sane and everything builds OK.
Developing on Linux would really make your life easier, like just sudo apt-get install build-essential plus few packages and installing a cross-compiler. However, if you're going to develop on Windows, you may find this guide useful. In addition, you'll need to patch make to make it work on Windows: Issue 504. And here is how to setup QEMU.
The recommended cross-compiler for ARM is the official GNU Tools for ARM.
So basically, here are steps to prepare a Linux dev machine for building and running Embox for ARM:
sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
sudo apt-get update
sudo apt-get install build-essential gcc-arm-none-eabi u-boot-tools qemu-system
Clone the repository:
git clone https://github.com/embox/embox embox
cd embox
Build arm/qemu:
make confload-arm/qemu
make
confload target initializes a conf/ directory with a predefined template called arm/qemu. conf/ is where a configuration of the target image (Embox + your app) resides.
Run QEMU. There's a handy wrapper for that, that infers the necessary options from the Embox configuration and runs QEMU properly:
sudo ./scripts/qemu/auto_qemu
If everything goes fine, you'll see something like that. Type help to list available commands.
Adding your application as an Embox command
Personally, when trying something new to me I usually "mimic" someone else's approaches to get the first feedback from the application/system. Here, I'd suggest to derive, e.g. an existing cat command, throw everything away from it, effectively turning it into a Hello world application.
For now, create a directory hello in src/cmds and add there two files:
hello.c file
/**
* Plain C Hello World application.
*/
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello world!\n");
return 0;
}
As you can see, this is a regular C program, that doesn't use any Embox-specific APIs. Let's integrate it into Embox now.
Hello.my file
(refer to Cat.my):
package embox.cmd.hello
#AutoCmd
#Cmd(name = "hello",
help = "<This is what `help hello` will output>",
man = '''
<What is shown when running `man hello`>
''')
module hello {
source "hello.c"
depends embox.compat.libc.all // for stdio
}
Now add the newly defined module into the configuration.
conf/mods.config file
package genconfig
configuration conf {
...
include embox.cmd.hello.hello
}
Build and run
Run make. This will compile hello.c and link it with Embox appropriately. After that, run it with sudo ./scripts/qemu/auto_qemu and type hello into the embox>prompt.
That's it.
Regarding your questions
To summarize:
Embox source code is compiled (via make) into some file (Object file?), <file>.<ext>
At the same time, my app's source code is cross-compiled (somehow) into an Object file (myapp.o) that is compatible with Embox
Both your application and Embox itself are compiled together with a regular (cross-)compiler, defined in conf/build.conf through a CROSS_COMPILE variable.
Some tool combines: (a) the Embox <file>.<ext> produced by make, (b) myapp.o and (c) any other libs I specify. It takes these as inputs and produces a single application image that is ready to be flashed via JTAG
These are linked with ld as part of the build process.
What is the exact name and file extension of the Embox "artifact" produced by running make on Embox source code? Is this artifact different depending on whether you are on Windows or Mac?
The main build artifacts are build/base/bin/embox (ELF) and build/base/bin/embox.bin (binary). If I'm not mistaken, these all have the same extension on all build platforms (well, may be there will be embox.exe instead of embox, but that's unlikely).
What tools besides make are necessary to produce this artifact?
The cross-compiler, essentially. GNU Tools for ARM embedded processors is a good choice.
Plus some quirks in case of Windows (see above).
What is this magic tool that takes in Object/interim files and produces a single app image? What is the exact name and file extension of this app image?
There's no such magic tool. :)
What tools do I need to cross-compile myapp.c and myapp.h into a myapp.o that is Embox compatible?
This is, again, hidden beneath Mybuild. In a nutshell, it:
compiles myapp.c using the cross-compiler into myapp.o
if the app is defined as a #AutoCmd module, it:
registers the app in a command registry by storing a pointer to main among with some metadata like name
strips away the main symbol from the object file to prevent conflicts in case of multiple apps
links myapp.o as it were a part of Embox into embox.o and then into embox ELF
Its the first time I heard about Embox, but the tool to combine Embox with your code is obviously a linker (so a cross ld from binutils, see documentation of ld). To understand more about linkers, read Levine's book Linkers and loaders
The Embox produced by compiling Embox source code is probably a library (libembox.a), or a relocatable object file embox.o - possibly produced by ld -r).
The produced application image is probably a raw binary file (.bin) but it could be an ELF file if it is loaded by the GRUB loader.
I guess that the building process is quite similar to the Linux kernel build process.
BTW, I would imagine that developing on a Linux system could be simpler, since Linux uses the same kind of tools daily. So you might install Linux on your development laptop.
You need a cross-compiler (for your target platform) to compile your code to be combined with Embox.

Linking a library built from source code to a program managed by autotools

I have a c program which needs a library named libnuma to be installed. But I dont have root access in the parallel machine in which I need to run this program. So I downloaded the source code of libnuma and compiled it. I have a libnuma.a file which i assume is the library. I need to link this library with the c program that I have. This program uses autotools for generating the configuration files and the makefile. I am new to autotools. Please tell me what I have to do to link this library without being root.
Ajay.
It should be sufficient to set CPPFLAGS and LDFLAGS. First, try:
$ ./configure LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include
(where libnuma.a is /path/to/lib/libnuma.a and numa.h is /path/to/include/numa.h.
That is, specify the directories.) If that does not work, check config.log to see what went wrong. If the configure script for the program you are using was built with an old version of autoconf, you may need to do:
$ LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include ./configure
instead. (The second invocation will only work in Bourne shells. With csh/tcsh, you will need to set the environment variables some other way, for example with env.) You also have the option of making those settings in the environment of your shell (eg, in a .bashrc) or in a config.site file.

From nmake: "no rule to make target `*.rc'"

I am in the process of trying to build putty tray, a variant of putty, from source on a Windows 7 system. I need to build it, not just download it, because I need to implement some additional functionality. I'm using nmake and (shouldn't be relevant) the Microsoft C++ compiler. To be precise, I'm working in a cmd window, I'm in the WINDOWS folder of the putty sources, and I'm running the command nmake -f MAKEFILE.VC.
C sources are compiling correctly, but then I'm running into an error that I don't understand:
no rule to make target `*.rc' needed by `pageant.res'
I understand perfectly well what it would mean if it said it couldn't make a particular file: it would mean the file was missing. But I don't get how this makes sense with a wild card.
The presumably relevant part of MAKEFILE.VC is
pageant.res: *.c *.h *.rc ..\windows\pageant.rc ..\windows\rcstuff.h \
..\windows\pageant.ico ..\windows\pageants.ico \
..\windows\version.rc2 ..\windows\pageant.mft
rc $(RCFL) -r $(RCFLAGS) ..\windows\pageant.rc
And, yes, there are *.rc files in the folder: PAGEANT.RC, PLINK.RC, PSCP.RC, PSFTP.RC, PUTTY.RC, PUTTYTEL.RC
Any ideas?
Have you considered trying gmake instead of nmake?
Much of the makefile-driven open source project world finds nmake too limiting and has standardized on the Gnu's gmake as a much better tool. I haven't checked to be sure, but this has the feel of an nmake limitation and PuTTY is certainly the sort of project that would use gmake.
A good place to find a native Windows build of gmake is at the GnuWin32 project. Check out the other packages available there. They are a good source of native Windows builds of a lot of the familiar and useful Gnu tools. They have an advantage over projects like Cygwin that their tools work at the normal CMD prompt, and don't require installation beyond having their bin folder in your PATH, which their nice Windows installer will take care of for you.

Resources