How to use make and compile as C99? - linux

I'm trying to compile a linux kernel module using a Makefile:
obj-m += main.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Which gives me:
main.c:54: warning: ISO C90 forbids mixed declarations and code
I need to switch to C99. After reading I noticed I need to add a flag -std=c99, not sure where it suppose to be added.
How do I change the Makefile so it will compile as C99?

The correct way to add compiler flags when compiling modules is by setting the ccflags-y variable. Like this:
ccflags-y := -std=gnu99
See Documentation/kbuild/makefiles.txt in the kernel tree for more information.
Note that I'm using the gnu99 standard instead of c99 since the Linux kernel heavily relies on GNU extensions.

You could just add
CFLAGS=-std=c99
To the top of your makefile, or you can make the code compliant with C90 (as LukeN suggests.)

It's got nothing to do with the makefile. ISO C90 forbids declaring variables anywhere but in the beginning of a block or the file - like this
int main(int argc, char **argv) {
int a; /* Ok */
int b = 3; /* Ok */
printf("Hello, the magic number is %d!\n", b);
int c = 42; /* ERROR! Can only declare variables in the beginning of the block */
printf("I also like %d.. but not as much as %d!\n", c, b);
return 0;
}
Thus it has to be modified to this...
int main(int argc, char **argv) {
int a; /* Ok */
int b = 3; /* Ok */
int c = 42; /* Ok! */
printf("Hello, the magic number is %d!\n", b);
printf("I also like %d.. but not as much as %d!\n", c, b);
return 0;
}
You can only "fix" that in the source code, not in the makefile.
This rule has been relaxed in C99, but in my opinion it's a good idea to separate variable definitions, declarations and initializations from the code below it :)
So to change your makefile to make it compile with C99, you need to change the Makefile in the "build" directory that your makefile is referencing, and add the "-std=c99" at the "gcc" line compiling the source file.

Related

how to prevent some values from being optimized out in linux kernel debugging? [duplicate]

This question already has answers here:
Is there a way to tell GCC not to optimise a particular piece of code?
(3 answers)
Closed last year.
This is a code in linux (5.4.21)
When I use a virtual machine and connect gdb to the linux process, I can use break points and follow code. For example, I set breakpoint on a function arm_smmu_device_probe. When I follow with 'next' command, I see some values, for example, 'smmu' or 'dev' below are shown to have been optimized out. How can I make them not optimized out so that I can see them in gdb?
static int arm_smmu_device_probe(struct platform_device *pdev)
{
int irq, ret;
struct resource *res;
resource_size_t ioaddr;
struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
bool bypass;
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
dev_err(dev, "failed to allocate arm_smmu_device\n");
return -ENOMEM;
}
smmu->dev = dev;
if (dev->of_node) {
ret = arm_smmu_device_dt_probe(pdev, smmu);
} else {
ret = arm_smmu_device_acpi_probe(pdev, smmu);
if (ret == -ENODEV)
return ret;
}
I tried chaning -O2 to -Og in the top Makefile but the kernel build fails then.
Recently I found how to do this. (from Is there a way to tell GCC not to optimise a particular piece of code?, flolo's answer)
If you want a function aaa(...) not to be optimzed, you can do it like this.
#pragma GCC push_options
#pragma GCC optimize ("O0")
aaa ( ... )
{
function body
}
#prgma GCC pop_options
In some cases, this putting #pragma causes some discrepancy between the #include header file and the function source. So in this case (not often) you need to add this #praga around the corresponding #include statement. If linux/bbb.h causes this kind of problem, do this.
#pragma GCC push_options
#pragma GCC optimize ("O0")
#include <linux/bbb.h>
#pragma GCC pop_options
This works sure and I'm enjoying(?) debug/analysis this way.

Clang performs better than MSVC on Windows

The c++ code compiled by clang runs a lot faster than the same code compiled by MSVC. And I checked the ASM code, found out that clang automatically uses SIMD instructions for speed purposes. So I rewrite the main calculation part by using AVX Intrinsics code. Still, the program compiled by Clang gains a 10% benefit of speed.
Is it common sense that Clang performs better than MSVC on Windows? Or I missed some important optimization configurations of MSVC.
I've tested these code:
static __inline int RGBToY(unsigned char r, unsigned char g, unsigned char b) {
return (66 * r + 129 * g + 25 * b + 0x1080) >> 8;
}
void ToYRow_C(const unsigned char* src_argb0, unsigned char* dst_y, int width) {
int x;
for (x = 0; x < width; ++x) {
dst_y[0] = RGBToY(src_argb0[2], src_argb0[1], src_argb0[0]);
src_argb0 += 3;
dst_y += 1;
}
}
And the compiling flags for Clang: -O2 -mavx2, flags for MSVC: /O2 /arch:AVX2.
Processing a 2560x1440 image on a clang-compiled program costs 1.2ms, and 4.2ms for a MSVC-compiled program.

GCC error: 'for' loop initial declaration used outside C99 mode

I'm getting error: 'for' loop initial declaration used outside C99 mode when I try to compile with make. I found a wiki that says
Put -std=c99 in the compilation line: gcc -std=c99 foo.c -o foo
Problem is I don't know how to specify this in make. I opened Makefile, found CC = gcc and changed it to CC = gcc -std=c99 with no results. Any ideas?
Put CFLAGS=-std=c99 at the top of your Makefile.
To remove the error without using C99, you just need to declare your iterator variable at the top of the block the for loop is inside.
Instead of:
for (int i = 0; i < count; i++)
{
}
Use:
int i;
//other code
for (i = 0; i < count; i++)
{
}
NEW: i tried make CFLAGS=-std=c99,finally useful.
OLD:if you have added CFLAGS=-std=c99 into MakeFile,and got error too.
maybe use make clean before make is a good idea.

G++: linker doesnt seem to link correctly

I try to compile a program I have to control a DAQ device. In Windows, g++ compile and links OK, but in Linux it doesn't. The linker (called by G++) displays:
g++ -Wall -o "acelerar-30-0" "acelerar-30-0.cpp" (en el directorio: /home/poly/)
/tmp/ccRLpB4q.o: In function `main':
acelerar-30-0.cpp:(.text+0x429): undefined reference to `AdxInstantAoCtrlCreate'
collect2: ld returned 1 exit status
Ha fallado la compilaciĆ³n.
The cpp file is this (cut):
include stdlib.h
include stdio.h
include math.h
include "compatibility.h"
include "bdaqctrl.h"
include "comunes.h"
using namespace Automation::BDaq;
define deviceDescription L"USB-4704,BID#0"
int32 channelStart = 0;
int32 channelCount = 1;
double voltaje[0];
int32 modo;
int32 ms;
int main(int argc, char* argv[])
{
if (argc!=3)
salidaerror(argv[0],1);
channelStart = atoi(argv[1]);
ms = atoi(argv[2]);
if (channelStart<0||channelStart>1||ms<10)
salidaerror(argv[0],1);
ErrorCode ret = Success;
InstantAoCtrl * instantAoCtrl = AdxInstantAoCtrlCreate();
...
I have been several hours on this, and can't find the answer. The SDK is for Debian/Ubuntu, and it has the same code for Linux and Windows.
Any hints? Thanks
EDIT: Removed some marks as the formatting was incorrect
In my (limited) experience, typical gcc behavior will require that you specify the library containing that function as an argument on the command line like so:
-lsome_library
This is required even if the library is in your library path (additional library paths can be specified with -L). Find the appropriate library file containing that function and use its filename minus extensions and leading "lib" in the argument format above.

Compiling/Linking CUDA and CPP Source Files

I am working through a sample program that uses both C++ source code as well as CUDA. This is the essential content from my four source files.
matrixmul.cu (main CUDA source code):
#include <stdlib.h>
#include <cutil.h>
#include "assist.h"
#include "matrixmul.h"
int main (int argc, char ** argv)
{
...
computeGold(reference, hostM, hostN, Mh, Mw, Nw); //reference to .cpp file
...
}
matrixmul_gold.cpp (C++ source code, single function, no main method):
void computeGold(float * P, const float * M, const float * N, int Mh, int Mw, int Nw)
{
...
}
matrixmul.h (header for matrixmul_gold.cpp file)
#ifndef matrixmul_h
#define matrixmul_h
extern "C"
void computeGold(float * P, const float * M, const float * N, int Mh, int Mw, int Nw);
#endif
assist.h (helper functions)
I am trying to compile and link these files so that they, well, work. So far I can get matrixmul_gold.cpp compiled using:
g++ -c matrixmul_gold.cpp
And I can compile the CUDA source code with out errors using:
nvcc -I/home/sbu/NVIDIA_GPU_Computing_SDK/C/common/inc -L/home/sbu/NVIDIA_GPU_Computing_SDK/C/lib matrixmul.cu -c -lcutil_x86_64
But I just end up with two .O files. I've tried a lot of different ways to link the two .O files but so far it's a no-go. What's the proper approach?
UPDATE: As requested, here is the output of:
nm matrixmul_gold.o matrixmul.o | grep computeGold
nm: 'matrixmul.o': No such file
0000000000000000 T _Z11computeGoldPfPKfS1_iii
I think the 'matrixmul.o' missing error is because I am not actually getting a successful compile when running the suggested compile command:
nvcc -I/home/sbu/NVIDIA_GPU_Computing_SDK/C/common/inc -L/home/sbu/NVIDIA_GPU_Computing_SDK/C/lib -o matrixmul matrixmul.cu matrixmul_gold.o -lcutil_x86_64
UPDATE 2: I was missing an extern "C" from the beginning of matrixmul_gold.cpp. I added that and the suggested compilation command works great. Thank you!
Conventionally you would use whichever compiler you are using to compile the code containing the main subroutine to link the application. In this case you have the main in the .cu, so use nvcc to do the linking. Something like this:
$ g++ -c matrixmul_gold.cpp
$ nvcc -I/home/sbu/NVIDIA_GPU_Computing_SDK/C/common/inc \
-L/home/sbu/NVIDIA_GPU_Computing_SDK/C/lib \
-o matrixmul matrixmul.cu matrixmul_gold.o -lcutil_x86_64
This will link an executable binary called matrimul from matrixmul.cu, matrixmul_gold.o and the cutil library (implicitly nvcc will link the CUDA runtime library and CUDA driver library as well).

Resources