Compiling against gpsd on OpenWRT - linking fails - c

I'm trying to compile a tool that uses gps.h, but my compilation seems to fail each time when it tries to link to libgps. The error message I receive is:
/opt/openwrt-sdk/staging_dir/toolchain-arm_cortex-a9+vfpv3_gcc-7.3.0_musl_eabi/bin/../lib/gcc/arm-openwrt-linux-muslgnueabi/7.3.0/../../../../arm-openwrt-linux-muslgnueabi/bin/ld: cannot find -lgps
This is the command I'm compiling with:
arm-openwrt-linux-gcc -o ./bin/eagle src/main.c -I./src -I/opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/include -static -L/opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/lib -lpthread -lgps
Basic code for reference:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gps.h>
int main(void)
{
int rc;
struct gps_data_t gps_data;
if ((rc = gps_open("localhost", "2947", &gps_data)) == -1)
{
printf("code: %d, reason: %s\n", rc, gps_errstr(rc));
return 1;
}
gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);
return 0;
}
And some directory listings in my toolchain - as far as I can tell, libgps has compiled successfully:
# ls -lah /opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/include/ | grep gps
-rw-rw-r-- 1 root root 80K Sep 7 2017 gps.h
# ls -lah /opt/openwrt-sdk/staging_dir/target-arm_cortex-a9+vfpv3_musl_eabi/usr/lib/ | grep gps
lrwxrwxrwx 1 root root 16 Oct 17 18:46 libgps.so -> libgps.so.23.0.0
lrwxrwxrwx 1 root root 16 Oct 17 18:46 libgps.so.23 -> libgps.so.23.0.0
-rwxr-xr-x 1 root root 101K Oct 17 18:46 libgps.so.23.0.0
Many thanks in advance for any help.

Your link command line contains '-static', which prevents linking against *.so shared libraries (aka shared objects, hence 'so'), but still permits linking against *.a static-link libraries (aka archives).
See: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
In the directory whose contents you listed, and which the link command line is directed towards using the '-L' flag, there is a shared object libgps.so, but there is no static-link library libgps.a .
This leaves the linker no way to satisfy the link-time dependency on libgps. The only way to satisfy it, using libgps.so, has been disabled using '-static'.
To fix, either:
Modify the tool's compile recipe, so as to remove '-static' from the link command line, so as to enable use of the shared object, or
Modify gpsd's compile recipe, so as to cause a static-link library libgps.a to built, either in addition to or instead of libgps.so.

Related

Why does the return value -1 become 4294967295 when return type is int64_t?

In this code, I have a function whose return value is -1, but when assigned to int64_t type, the value obtained is 4294967295 instead of -1, but when assigned to int32_t type, it is -1. The return value of that zip_name_locate is of type int (4 bytes on my system). why is that?
#include <inttypes.h>
#include <stdio.h>
#include <zip.h>
int main() {
const char * path = "/home/www/api/default/current/public/static/doc/test.xlsx";
int error = ZIP_ER_NOENT;
zip_t* zip = zip_open(path, ZIP_RDONLY, &error);
int32_t n = zip_name_locate(zip, "xl/worksheets/_rels/sheet2.xml.rels", ZIP_FL_NODIR);
printf("%d\n", n);
int64_t j = zip_name_locate(zip, "xl/worksheets/_rels/sheet2.xml.rels", ZIP_FL_NODIR);
printf("%" PRId64 "\n", j);
return 0;
}
output:
-1
4294967295
This is my system information:
➜ ~ uname -r
3.10.0-1062.12.1.el7.x86_64
➜ ~ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
➜ ~ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Thanks for answering, here are some answers to your questions:
About libzip, Because this is related to a bug I encountered in the process, so I need to use zip
My system is 64bit CentOS 7.7
zip_name_locate does return zip_int64_t type
I printed n and j in gdb, n is -1, j is 4196160, it seems that gdb cannot print integers of type int64_t, but this output indicates that j should not be -1
Because we used an old version of libzip in a certain environment and caused a bug, so we wanted to find the most fundamental reason, we used the built-in version 0.11
PRId64 is ld on my system
int64_t j = -1; and int64_t j = (int64_t)((zip_int64_t)-1); successful conversion
sizeof(long) is 8
I made a mistake. On my system, I have an old version of libzip and a new version of libzip, but when I tried to introduce the old version of libzip with the -L flag, the new version was actually introduced. The method I compiled is
gcc -L /usr/lib64 -lzip test1.c -o test and /usr/lib64 is where the old version of libzip dynamic shared library is located.
In my system, there are some libzip library files under /usr/lib64 and /usr/local/lib64, the old version under /usr/lib64, and the new version under /usr/local/lib64:
ls -lh /usr/local/lib64/libzip.so*
lrwxrwxrwx 1 root root 11 Jun 1 22:21 /usr/local/lib64/libzip.so -> libzip.so.5
lrwxrwxrwx 1 root root 13 Jun 1 22:21 /usr/local/lib64/libzip.so.5 -> libzip.so.5.3
-rwxr-xr-x 1 root root 162K Jun 1 23:18 /usr/local/lib64/libzip.so.5.3
ls -lh /usr/lib64/libzip.so*
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so
lrwxrwxrwx 1 root root 11 Jun 2 00:07 /usr/lib64/libzip.so.2 -> libzip.so.5
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so.2.1.0
-rwxr-xr-x 1 root root 57K Jun 2 00:02 /usr/lib64/libzip.so.5
I learned that the objdump command can check which shared libraries are dependent, so I checked it out and the following is the output:
objdump -p test | grep so
NEEDED libzip.so.2
NEEDED libc.so.6
required from libc.so.6:
Then I checked through ldconfig and found that libzip.so.2 points to the new version:
ldconfig -v | grep libzip
libzip.so.5 -> libzip.so.5.3
libzip.so.2 -> libzip.so.5
So in my question, it was based on a wrong judgment from the beginning, leading to incomprehensible imagination. If you are using a new version of libzip, the return value of zip_name_locate of libzip in the new version is zip_int64_t. This type is int64_t type on my system. When the 4294967295 return value of this type is assigned to int32_t, it causes overflow, so would be -1, and j would be 4294967295.

Cannot use function cpuset_create from shared C library <cpuset.h>

I am trying to port a C project from a CentOS 7 (Core) to an Ubuntu 20.04.1 LTS (Focal Fossa) system. The program compiles and runs without problem on CentOS and also compiles without error on the Ubuntu system. However, when I try to execute the program on Ubuntu, I encounter the following error:
ERROR aff_prog_alloc #aff-executor.c:299 => cpuset_create: No such file or directory
The function cpuset_create is part of the <cpuset.h> library and the flag -lcpuset is included when compiling. The following is the output from the ldd command, showing the path for the <cpuset.h> library on our Ubuntu system:
$ ldd ./aff-executor
linux-vdso.so.1 (0x00007ffed97eb000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8c179d5000)
libcpuset.so.1 => /lib/x86_64-linux-gnu/libcpuset.so.1 (0x00007f8c177c8000)
libbitmask.so.1 => /lib/x86_64-linux-gnu/libbitmask.so.1 (0x00007f8c175c4000)
libnuma.so.1 => /lib/x86_64-linux-gnu/libnuma.so.1 (0x00007f8c175b7000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f8c175ac000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c173ba000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c17a22000)
I verified that the library actually exists at this location:
$ll /lib/x86_64-linux-gnu/libcpuset.*
-rw-r--r-- 1 root root 67952 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.a
lrwxrwxrwx 1 root root 18 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so -> libcpuset.so.1.1.0
lrwxrwxrwx 1 root root 18 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so.1 -> libcpuset.so.1.1.0
-rw-r--r-- 1 root root 52232 Nov 21 2016 /lib/x86_64-linux-gnu/libcpuset.so.1.1.0
Can anyone help with identifying why cpuset_create does not work on this system despite it having the correct syntax and inputs?
==================================
Update/Additional Info
The following code is what I need to use for my project. Everything works fine until the cpuset_create function which has been returning -1. I checked this program on a different Ubuntu (16.04.5 LTS (Xenial Xerus)) and it executed without problem on it, with cpuset_create returning the expected 0.
#define _GNU_SOURCE
#include<stdio.h>
#include <bitmask.h>
#include <cpuset.h>
#include <errno.h>
#include<numa.h>
typedef struct cpuset cpuset_t;
struct bitmask * get_mems_all(void);
/* return a bitmask describing all the available memory nodes */
struct bitmask * get_mems_all(void)
{
struct bitmask *ret;
if (numa_available() != -1){
printf("NUMA is available\n");
return numa_get_mems_allowed();
}
ret = bitmask_alloc(cpuset_mems_nbits());
printf("ret: %p\n",ret );
if (!ret)
printf("bitmask_alloc err");
bitmask_setbit(ret,0);
return ret;
}
int main(){
int err;
struct bitmask *mem_bm;
mem_bm=get_mems_all();
printf("mem_bm: %p\n",mem_bm );
numa_bitmask_clearbit(mem_bm, 1);
numa_bitmask_setbit(mem_bm,0);
char buff[256];
bitmask_displaylist(buff, sizeof(buff), mem_bm);
printf("buff: %s\n",buff );
printf("mem_bm: %p\n",mem_bm );
printf("cpuset lib version: %d\n",cpuset_version() );
cpuset_t *cpuset=cpuset_alloc();
printf("cpuset: %p\n",cpuset );
err = cpuset_setmems(cpuset,mem_bm);
printf("err cpuset_setmems: %d\n", err);
char* path="/AFF_1000/";
err = cpuset_create(path, cpuset);
printf("err cpuset_create: %d\n", err);
return 0;
}
Compilation:
gcc -Wall -O2 -std=gnu99 test.c -o test -lcpuset -lbitmask -lnuma
Output on Ubuntu 20.04.1 LTS (Focal Fossa):
$./test
NUMA is available
mem_bm: 0x55a34b2ac120
buff: 0
mem_bm: 0x55a34b2ac120
cpuset lib version: 3
cpuset: 0x55a34b2ac1d0
err cpuset_setmems: 0
err cpuset_create: -1
Expected output (this is from Ubuntu 16.04LTS (Xenial Xerus)):
$./test
NUMA is available
mem_bm: 0x1c39670
buff: 0
mem_bm: 0x1c39670
cpuset lib version: 3
cpuset: 0x1c396b0
err cpuset_setmems: 0
err cpuset_create: 0
$cset set -l
cset:
Name CPUs-X MEMs-X Tasks Subs Path
------------ ---------- - ------- - ----- ---- ----------
root 0-63 y 0-1 y 500 2 /
AFF_1000 ***** n 0 n 0 0 /AFF_1000
system 0-63 n 0 n 349 0 /system
However, I am unable to run the same program as root on Ubuntu 16.04 as well. I get the following error:
sudo ./test
./test: error while loading shared libraries: libcpuset.so.1: cannot open shared object file: No such file or directory
Does anyone know why this is happening? I do not know if this last problem is related to why my program won't run on the Ubuntu 20.04.

Why can't I read /proc/pid/mem when I have read permission?

I would like to read the content of the memory file associated to one of my process (with PID 2614). I started to write a very small C program to check I can open it:
#include <stdio.h>
#include <errno.h>
int main() {
FILE* f = fopen("/proc/2614/mem", "rb");
if(!f) {
printf("Error %d\n", errno);
return -1;
}
fclose(f);
return 0;
}
When I run it I get a permission denied error:
$ gcc -o read read.c && ./read
Error 13
However, I have read permission:
$ whoami
pierre
$ ll /proc/2614/mem
-rw------- 1 pierre pierre 0 août 18 19:44 /proc/2614/mem
What's going on?
I know it is possible to read the file because I am able to do it on another system (and some other SO answers already did that). Here is information about my system:
$ uname -a
Linux pierre-computer 4.15.0-112-generic #113~16.04.1-Ubuntu SMP Fri Jul 10 04:37:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
And the information for the system on which I can read it:
$ uname -a
Linux not-pierre-computer 3.2.0-4-686-pae #1 SMP Debian 3.2.89-2 i686 GNU/Linux
Are there restrictions on some systems?

c binary file greater than source file [duplicate]

This question already has an answer here:
size of executable files?
(1 answer)
Closed 7 years ago.
I have a c source file with name simple.c (file size 68 bytes) and I compiled it using gcc. The output binary file size is 7151 bytes.
C Source code:
int main()
{
int a = 10;
int b = 34;
int c = a + b;
return c;
}
I haven't included any header files.
I don't know, how does the C binary file becomes bigger than the source file. Can anyone please explain?
test#test-desktop:~/Desktop/c$ ls -l
total 4
-rw-rw-r-- 1 test test 68 Jul 15 15:04 simple.c
test#test-desktop:~/Desktop/c$ gcc simple.c
test#test-desktop:~/Desktop/c$ ls -l
total 12
-rwxrwxr-x 1 test test 7151 Jul 15 15:04 a.out
-rw-rw-r-- 1 test test 68 Jul 15 15:04 simple.c
The above is the terminal output.
You have a certain one-time overhead even without including anything. There is code running before main() (which is setting up stdin, stdout, and stderr, signal handler tables etc.), and code running after that function returns (e.g. checking for anything registered with atexit() and similar things). This is called the C runtime, traditionally located in crt0.o, which is linked into any executable.
It'll be the debug and symbol information. Optimize and strip it:
Use gcc -Os to optimize for smallest size.
Use strip a.out to remove the symbols and debug info.
There are also the CRT startup files providing the bulk of your binary that process argc, argv etc and setup your environment. You can opt out of those using -nostartfiles but you probably don't want to do that.

editline/history.h and editline/readline.h not found/working on macOS when trying to compile with developer tools installed already

I am working on this tutorial on building your own LISP (http://www.buildyourownlisp.com/chapter4_interactive_prompt) and for some reason when I try to compile I get this:
REPL.c:4:10: fatal error: 'editline/readline.h' file not found
#include <editline/history.h>
^
1 error generated.
I have installed the macOS developer tools, and brew is showing readline is installed and it doesn't know what to do when I try brew install editline.
This is my code:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <editline/readline.h>
4 #include <editline/history.h>
5
6 int main(int argc, char** argv) {
7
8 /* version/exit info */
9 puts("Edward Version 0.0.1");
10 puts("Press Ctrl+c to Exit\n");
11
12 /* endless loop for main REPL */
13 while (1) {
14 /* output prompt and read line */
15 char* input = readline("lispy> ");
16
17 /* put input in history */
18 add_history(input);
19
20 /* Echo input back */
21 printf("No you're a %s\n", input);
22
23 /* free input */
24 free(input);
25 }
26 return 0;
27 }
It is obviously very basic, but I really want to get this project rolling so I'm hoping I can figure this out. This is what I'm using to compile:
cc -std=c99 -Wall REPL.c -ledit -o REPL
Include only
#include <editline/readline.h>
which should exist if the command line tools are installed. This file contains the
"readline wrapper" for libedit, including the history functions as well.
An include file <editline/history.h> does not exist on OS X.
I tested your code with that modification, and it compiled and ran without problems.
Using OSX Yosemite. I removed #include<editline/history.h>
and then used cc -std=c99 -Wall test.c -ledit -o test
Works fine now
I'm on El Capitan,
Remove #include <editline/history.h>,
and use cc -std=c99 -Wall test.c -ledit -o test works for me.
Add the flag -ledit before the output flad, it's a linking process, allows the compiler to directly embed calls to editline in your program. Or, you'll get the below error message,
Undefined symbols for architecture x86_64:
"_add_history", referenced from:
_main in prompt-086f90.o
"_readline", referenced from:
_main in prompt-086f90.o
ld: symbol(s) not found for architecture x86_64
I'm on Ubuntu 14.04.
try this:
sudo apt-get install libeditline-dev
and include like this:
#include <editline.h>
finally compile like this:
add -leditline in the flag
I hope this can help.
I'm on OSX Mavericks and removing the line worked for me:
#include <editline/history.h>
The solution for those following along on FreeBSD (might work on other Unices as well):
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
...
And run:
$ cc test.c -Wall -std=c99 -lreadline -o test
Without "-lreadline" in the compile step it is not linked in and you will get errors about undefined reference to "readline" function.
I started in on Build your own list and ran into the same problem.
None of the above answers worked for me. After a little research I found out that macOs doesn't have the gnu readline library that provides the readline functions, Different versions of MacOs provide emulation of readline using a library called editline. to begin...
man editline
#include <histedit.h>
Ok, editline gives you some structs for line input and history,
and functions to operate on them. First you have to instantiate these structs. The documentation for editline is not very helpful because it doesn't contain any examples. Apple makes the header file available so that helps a little. http://www.opensource.apple.com/source/libedit/libedit-13/src/histedit.h
I am new to this and it was still pretty confusing to me. there is some version of the source code to libedit available as a debian package. Fortunately someone wiser than I has already dug into it and implemented a command line using lbedit. His code is here: https://www.cs.utah.edu/~bigler/code/libedit.html.
I took Mr Bigler's code, and the code from Build your own list, and put them together to get this.
/* repl-macos.c
* Repl code example from builyourownlisp.com
* Modified by NB aug 2017
* Code example for editline from
* www.cs.utah.edu/~bigler/code/libedit.html
*/
#include <stdio.h>
#include <string.h>
#include <histedit.h>
char* prompt(EditLine *e){
return "lispy> ";
}
int main(int argc, char** argv){
EditLine *el; // Line editor state
History *herstory; // the rest is history
// Temp Variables
int count;
const char *usrin;
int keepreading = 1;
HistEvent ev;
// Initialize the editline state
el = el_init(argv[0], stdin, stdout, stderr);
el_set(el, EL_PROMPT, &prompt);
el_set(el, EL_EDITOR, "emacs");
// Initialize history
herstory = history_init();
if(!herstory){
fprintf(stderr, "Couldn't initialize history\n");
return 1;
}
//set history size
history(herstory, &ev, H_SETSIZE, 800);
// Set up the call back functions for history functionality
el_set(el, EL_HIST, history, herstory);
puts("Begin moLisp interpreter");
puts("Type 'exit' at prompt to exit");
while(keepreading){
usrin = el_gets(el, &count);
// add the command to the history, and echo it back to the user
if(count > 0){
history(herstory, &ev, H_ENTER, usrin);
if(strcmp(usrin, "exit\n"))
printf("No, You're a %s", usrin);
else{
puts("bye");
--keepreading;
}
}
}
// Clean up memory
// by freeing the memory pointed to within the structs that
// libedit has created.
history_end(herstory);
el_end(el);
return 0;
}
Notice: The instantiation of the structs that are used happens outside of
the while loop, and so do the functions that free the memory those structs are using. Because of this, I added the command to exit, otherwise I think there's a memory leak if the only way to exit the while loop is by interrupting the program. To compile:
gcc repl-macos.c -ledit -Wall -o repl-edit
-ledit is needed to link editline
If it has any relevance, I am using macOs 10.4.11
and here's my compiler, output of
gcc --version
powerpc-apple-darwin8-gcc-4.0.0 (GCC) 4.0.0 20041026 (Apple Computer, Inc. build 4061)
Now the only problem with this, and the book points this out, is that
c-code is supposed to be portable and this isn't. The next step would be to add preprocessor directives so that it uses readline on linux and editline on macos.
If you are on ubuntu add the editline library
sudo apt-get install libtedit-dev
On Debian Buster 10, I had to install the package with:
sudo apt install libeditline-dev
Instead of:
#include <editline/readline.h>
#include <editline/history.h>
I just included:
#include <editline.h>
ran the program with -leditline flag and worked perfectly.

Resources