compiling multithreading C example with riscv gnu cross compiler - compilation

I'm using homebrew-riscv toolchain on mac machine.
I want to compile a simple multithreading program that is written using pthread library in C using riscv gnu cross compiler. So that, I've used the below command:
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 pthreadExample.c -o pthreadExample -lpthread
And I've got the following warning and error:
warning: implicit declaration of function 'pthread_create' [-Wimplicit-function-declaration]
32 | pthread_create(&tid, NULL, myThreadFun, (void *)&tid);
| ^~~~~~~~~~~~~~
pthreadExample.c:34:5: warning: implicit declaration of function 'pthread_exit' [-Wimplicit-function-declaration]
34 | pthread_exit(NULL);
| ^~~~~~~~~~~~
/opt/homebrew/Cellar/riscv-gnu-toolchain/master/lib/gcc/riscv64-unknown-elf/11.1.0/../../../../riscv64-unknown-elf/bin/ld: cannot find -lpthread
collect2: error: ld returned 1 exit status
Does anyone have any ideas for solving this error? Or should I use another option instead of -lpthread for compiling?
Thanks in advance

you are using the bare metal cross compiler, what you need is:
riscv64-unknown-linux-gnu-gcc
additionally, you are using the -march=rv32i flag, but you are using the 64 bit version of the compiler, that doesn't seem correct to me. If the target machine is a 32 bit one, then perhaps you should use the riscv32-unknown-linux-gnu-gcc

Related

gcc undefined reference to with pthread [duplicate]

I picked up the following demo off the web from https://computing.llnl.gov/tutorials/pthreads/
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
But when I compile it on my machine (running Ubuntu Linux 9.04) I get the following error:
corey#ubuntu:~/demo$ gcc -o term term.c
term.c: In function ‘main’:
term.c:23: warning: incompatible implicit declaration of built-in function ‘exit’
/tmp/cc8BMzwx.o: In function `main':
term.c:(.text+0x82): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
This doesn't make any sense to me, because the header includes pthread.h, which should have the pthread_create function. Any ideas what's going wrong?
For Linux the correct command is:
gcc -pthread -o term term.c
In general, libraries should follow sources and objects on command line, and -lpthread is not an "option", it's a library specification. On a system with only libpthread.a installed,
gcc -lpthread ...
will fail to link.
Read this or this detailed explanation.
For Linux the correct command is:
gcc -o term term.c -lpthread
you have to put -lpthread just after the compile command,this command will tell to the compiler to execute program with pthread.h library.
gcc -l links with a library file.Link -l with library name without the lib prefix.
in eclipse
properties->c/c++Build->setting->GCC C++ linker->libraries in top part add "pthread"
Running from the Linux terminal, what worked for me was compiling using the following command (suppose the c file I want to compile is called test.c):
gcc -o test test.c -pthread
Hope it helps somebody!
If you are using cmake, you can use:
add_compile_options(-pthread)
Or
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
I believe the proper way of adding pthread in CMake is with the following
find_package (Threads REQUIRED)
target_link_libraries(helloworld
${CMAKE_THREAD_LIBS_INIT}
)
Acutally, it gives several examples of compile commands used for pthreads codes are listed in the table below, if you continue reading the following tutorial:
https://computing.llnl.gov/tutorials/pthreads/#Compiling
Compile it like this : gcc demo.c -o demo -pthread
In Visual Studio 2019 specify -pthread in the property pages for the project under:
Linker -> Command Line -> Additional Options
Type in -pthread in the textbox.
You need to use the option -lpthread with gcc.
you need only Add "pthread" in proprieties=>C/C++ build=>GCC C++ Linker=>Libraries=> top part "Libraries(-l)".
thats it
check man page and you will get.
Compile and link with -pthread.
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
....
Since none of the answers exactly covered my need (using MSVS Code), I add here my experience with this IDE and CMAKE build tools too.
Step 1: Make sure in your .cpp, (or .hpp if needed) you have included:
#include <functional>
Step 2 For MSVSCode IDE users:
Add this line to your c_cpp_properties.json file:
"compilerArgs": ["-pthread"],
Step 2 For CMAKE build tools users:
Add this line to your CMakeLists.txt
set(CMAKE_CXX_FLAGS "-pthread")
Note: Adding flag -lpthread (instead of -pthread) results in failed linking.
From man gcc,
-pthread
Define additional macros required for using the POSIX threads library.
You should use this option consistently for both compilation and linking.
This option is supported on GNU/Linux targets,
most other Unix derivatives,
and also on x86 Cygwin and MinGW targets.
It is correct that -pthread is an option and the best way to handle this.
There are statements in some answers that it generates different compiled code. This is misleading.
If you wish to duplicate -pthread, you could use -lpthread -D_REENTRANT=1. So there are two things going on with the -pthread option.
Indeed it links with the pthread library as many answers express. Also, the order of the pthread library is important because it may override some weak symbols. So a correct version using -lpthread may need to have it multiple times on the command line.
The other important part is the _REENTRANT define. Note, that this is in the implementation namespace. Some people may care for portability and other not. However, it is very important that it is defined as the first thing in the compilation unit. This symbol will alter the way that many system headers files are parsed.
You can include #define _REENTRANT 1 at the top of every source file, but it is much easier to have it on the command line. Again, the -pthread is the best way to achieve this. Also, gcc may change the way this is implemented in the future. However, I think it is important for programmers to understand what is going on.
term.c: In function ‘main’: term.c:23: warning: incompatible implicit
declaration of built-in function ‘exit’
You never included <stdlib.h>, where exit() is declared. Also, I think newer versions of gcc have removed the need for _REENTRANT.
Why features.h?
Example on godbolt, without -pthread.
So, it is NOT generating different code. Ie, the backend of the compiler is NOT different. It is only conditional compilation and linking to different libraries. It does not generate 'lock free' code or add appropriate machine barriers because you have used this option.
In Anjuta, go to the Build menu, then Configure Project.
In the Configure Options box, add:
LDFLAGS='-lpthread'
Hope it'll help somebody too...
Sometimes, if you use multiple library, check the library dependency.
(e.g. -lpthread -lSDL... <==> ... -lSDL -lpthread)

Linking difference between clang and gcc

I am running fedora 23 and just compiled and installed casadi 2.4.1 (however, I do not think that this is casadi specific).
I am trying to compile and run a simple test program:
#include <iostream>
#include <casadi/casadi.hpp>
using namespace casadi;
int main () {
const SX m(42);
const SX n(23);
const SX x = m + n ;
std::cout << x << std::endl;
}
It works fine with gcc:
$ g++ test.cpp -std=c++11 -I$HOME/local/include -L$HOME/local/lib -lcasadi && ./a.out
SX(65)
But using clang, I get a linker error:
$ clang++ test.cpp -std=c++11 -I$HOME/local/include -L$HOME/local/lib -lcasadi && ./a.out
/tmp/test-cde41f.o: In function `casadi::GenericMatrix<casadi::Matrix<casadi::SXElement> >::dimString() const':
test.cpp:(.text._ZNK6casadi13GenericMatrixINS_6MatrixINS_9SXElementEEEE9dimStringEv[_ZNK6casadi13GenericMatrixINS_6MatrixINS_9SXElementEEEE9dimStringEv]+0x2b): undefined reference to `casadi::Sparsity::dimString() const'
/tmp/test-cde41f.o: In function `void casadi::Sparsity::set<casadi::SXElement>(casadi::SXElement*, casadi::SXElement const*, casadi::Sparsity const&) const':
test.cpp:(.text._ZNK6casadi8Sparsity3setINS_9SXElementEEEvPT_PKS3_RKS0_[_ZNK6casadi8Sparsity3setINS_9SXElementEEEvPT_PKS3_RKS0_]+0x6f0): undefined reference to `casadi::Sparsity::dimString() const'
test.cpp:(.text._ZNK6casadi8Sparsity3setINS_9SXElementEEEvPT_PKS3_RKS0_[_ZNK6casadi8Sparsity3setINS_9SXElementEEEvPT_PKS3_RKS0_]+0x743): undefined reference to `casadi::Sparsity::dimString() const'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am pretty confident that the symbol is defined in the library. However, I fail to understand what clang is missing here. Is there some special c++11 ABI flag that I need to pass to the linker or something like that?
I would suspect version skew. Unless you do something special, clang uses some gcc stdc++ library, for which it searches. That was the case the last time I used clang for much. They may use their own std c++ library now. But if casadi was compiled with one version of gcc and you used clang which uses the std c++ library for another version of gcc, you can see linker errors like this.
You may learn something if you run clang -V to get version information. Also, gcc -v to get gcc version information, and verify that the version of gcc clang wants is the same as the version with which you are compiling.

OpenMP not available on mac with gcc 4.9

The OpenMP website says: "GCC 4.9 supports OpenMP 4.0 for C/C++".
I'm using gcc 4.9.1 from brew, yet I see this error when I try to compile liblinear: omp.h file not found.
Specifically:
Compiling liblinear version 1.93
Source code page:
http://www.csie.ntu.edu.tw/~cjlin/liblinear/
external/liblinear-1.93_multicore/matlab/train.cpp:7:10: fatal error: 'omp.h' file not found
#include <omp.h>
^
1 error generated.
mex: compile of ' "external/liblinear-1.93_multicore/matlab/train.cpp"' failed.
Here's the matlab code used to compile liblinear, which contains a file that contains #include <omp.h>:
% Compile liblinear
if ~exist('liblinear_train')
fprintf('Compiling liblinear version 1.93\n');
fprintf('Source code page:\n');
fprintf(' http://www.csie.ntu.edu.tw/~cjlin/liblinear/\n');
mex -outdir bin ...
COMPFLAGS="$COMPFLAGS -fopenmp" -largeArrayDims ...
external/liblinear-1.93_multicore/matlab/train.cpp ...
external/liblinear-1.93_multicore/matlab/linear_model_matlab.cpp ...
external/liblinear-1.93_multicore/linear.cpp ...
external/liblinear-1.93_multicore/tron.cpp ...
"external/liblinear-1.93_multicore/blas/*.c" ...
-output liblinear_train;
end`
UPDATE
I changed the gcc version in mexopts.sh (side note: I copied it from /Applications/MATLAB_R2013a_Student.app/bin/mexopts.sh to ~/.matlab/R2013a). Specifically, I changed CC=xcrun -sdk macosx10.9 clang to CC='gcc-4.9'.
I think Matlab does indeed use this compiler, because when I run this code:
if ~exist('anigauss')
fprintf('Compiling the anisotropic gauss filtering of:\n');
fprintf(' J. Geusebroek, A. Smeulders, and J. van de Weijer\n');
fprintf(' Fast anisotropic gauss filtering\n');
fprintf(' IEEE Transactions on Image Processing, 2003\n');
fprintf('Source code/Project page:\n');
fprintf(' http://staff.science.uva.nl/~mark/downloads.html#anigauss\n\n');
mex -Dchar16_t=uint16_T -outdir bin ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss.c ...
-output anigauss
end
Matlab prints:
dyld: Library not loaded: /usr/local/opt/mpfr2/lib/libmpfr.1.dylib
Referenced from: /usr/local/Cellar/gcc49/4.9.1/libexec/gcc/x86_64-apple-darwin14.0.0/4.9.1/cc1
Reason: Incompatible library version: cc1 requires version 4.0.0 or later, but libmpfr.1.dylib provides version 3.0.0
gcc-4.9: internal compiler error: Trace/BPT trap: 5 (program cc1)
/Applications/MATLAB_R2013a_Student.app/bin/mex: line 1343: 77128 Abort trap: 6 gcc-4.9 -c -I/Applications/MATLAB_R2013a_Student.app/extern/include -I/Applications/MATLAB_R2013a_Student.app/simulink/include -DMATLAB_MEX_FILE -fno-common -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -mmacosx-version-min=10.9 -fexceptions -Dchar16_t=uint16_T -DMX_COMPAT_32 -O2 -DNDEBUG "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c" -o bin/anigauss_mex.o
mex: compile of ' "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c"' failed.
Yet when I try to compile liblinear, I get the very same error message as usual.
COMPFLAGS="$COMPFLAGS /openmp" -largeArrayDims ...
^^^^^^^
This was probably written for Microsoft Visual C/C++ or for Intel C/C++ Compiler on Windows. Unix systems, including OS X, traditionally use - to denote command line flags.
To enable OpenMP support in GCC you should change /openmp to -fopenmp in the compiler flags COMPFLAGS.
It appears that in addition to passing the wrong OpenMP flag, mex is using the wrong compiler. Compare the error outputs from GCC and Clang:
GCC
foo.c:1:25: fatal error: nonexistent.h: No such file or directory
#include <nonexistent.h>
^
compilation terminated.
Clang
foo.c:1:10: fatal error: 'nonexistent.h' file not found
#include <nonexistent.h>
^
1 error generated.
Clang, or at least the version that Apple ships with Xcode, does not support OpenMP. Consult the MATLAB documentation of the mex command on how to select a different compiler. Basically, you have to execute:
mex -setup
If MATLAB detects several usable compilers, it should present you with the ability to pick one of them. Unfortunately, according to this table, MATLAB might not support GCC on OS X (at least it is not listed in the table).

Should gcc builtins always be resolved during the compilation step, or the linker step?

In running gcc 3.4.3 on a Solaris 5.11 box I see that builtin functions are left undefined during compilation, but are resolved against libgcc.a when the Solaris linker links against libgcc.a.
On gcc 4.5.2 on another Solaris box, the same builtin functions are resolved during compilation of the .o, and the linker isn't concerned about them.
A boiled down example file compiled on gcc 3.4.3:
# cat ctzll.c
int func(unsigned long long x)
{
return __builtin_ctzll(x);
}
# cat main.c
int main(void)
{
return func(0xc0ffee);
}
First compile ctzll.c, and check the symbols:
# nm ctzll.o
U __ctzdi2
0000000000000000 T func
Now compile main.c, and link the objects:
# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
/usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2
So, if I understand correctly, the Solaris linker resolved __ctzdi2 (the internal representation of __builtin_ctzll).
Now, compile with gcc 4.5.2 on the other Solaris machine:
#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func
The symbol has been resolved fine in the object file, and it has been inlined into the .o assembly as:
8: 48 0f bc 45 f8 bsf -0x8(%rbp),%rax
Is the 3.4.3 compiler behaving correctly? I'd have expected the actual compilation to handle the builtins, like 4.5.2, by referencing the 64 bit version of libgcc.a. The lack of uniformity across the compilers is causing upstream problems in my project as the builtin remains undefined and the linker isn't resolving the symbols as I'm not linking against the OS specific 64 bit libraries (libgcc.a). I'm not sure if the 3.4.3 compiler is misconfigured causing the .o files to have undefined builtin functions caught by linking, or if the newer compilers are just smarter and I need to add the 64 bit libraries to the linker to handler the older compiler.
The 3.4.3 seems to show a valid libgcc.a which contains the definition of _ctzdi2:
# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:
The whole point of libgcc.a is to implement builtin operations that gcc can't emit code for (which includes not only __builtin_ functions, but also things like 'long long' math operations on some 32-bit platforms).
Obviously the newer gcc got smarter about emitting code.

Link error when compiling gcc atomic operation in 32-bit mode

I have the following program:
~/test> cat test.cc
int main()
{
int i = 3;
int j = __sync_add_and_fetch(&i, 1);
return 0;
}
I'm compiling this program using GCC 4.2.2 on Linux running on a multi-cpu 64-bit Intel machine:
~/test> uname --all
Linux doom 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
When I compile the program in 64-bit mode, it compiles and links fine:
~/test> /share/tools/gcc-4.2.2/bin/g++ test.cc
~/test>
When I compile it in 32-bit mode, I get the following error:
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccEVHGkB.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test>
Although I will never actually run on a 32-bit processor, I do need a 32-bit executable so I can link with some 32-bit libraries.
My 2 questions are:
Why do I get a link error when I compile in 32-bit mode?
Is there some way to get the program to compile and link, while still being able to link with a 32-bit library?
The answer from Dan Udey was close, close enough in fact to allow me to find the real solution.
According to the man page "-mcpu" is a deprecated synonym for "-mtune" and just means "optimize for a particular CPU (but still run on older CPUs, albeit less optimal)". I tried this, and it did not solve the issue.
However, "-march=" means "generate code for a particular CPU (and don't run on older CPUs)". When I tried this it solved the problem: specifying a CPU of i486 or better got rid of the link error.
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccYnYLj6.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i386 test.cc
/tmp/ccOr3ww8.o(.text+0x22): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i486 test.cc
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=pentium test.cc
From the GCC page on Atomic Builtins:
Not all operations are supported by
all target processors. If a particular
operation cannot be implemented on the
target processor, a warning will be
generated and a call an external
function will be generated. The
external function will carry the same
name as the builtin, with an
additional suffix `_n' where n is the
size of the data type.
Judging from your compiler output, which refers to __sync_add_and_fetch_4, this is what's happening. For some reason, GCC is not generating the external function properly.
This is likely why you're only getting an error in 32-bit mode - when compiling for 64-bit mode, it compiles for your processor more closely. When compiling for 32-bit, it may well be using a generic arch (i386, for example) which does not natively support those features. Try specifying a specific architecture for your chip family (Xeon, Core 2, etc.) via -mcpu and see if that works.
If not, you'll have to figure out why GCC isn't including the appropriate function that it should be generating.

Resources