Installing twitcurl on OS X - c++

I am attempting to install twitcurl on OS X and have met with some problems.
At first, running make would return the clang error: ld: unknown option: -soname. I looked through the responses from other users with similar problems on OS X and found the following advice:
In the makefile, change:
LDFLAGS += -Wl,-rpath-link=$(STAGING_DIR)/usr/lib
to:
LDFLAGS += -rpath=$(STAGING_DIR)/usr/lib
change:
$(CC) -shared -Wl,-soname,lib$(LIBNAME).so.1 $(LDFLAGS) -o lib$(LIBNAME).so.1.0 .o -L$(LIBRARY_DIR) -lcurl
to:
$(CC) -dynamiclib -shared -Wl,-install_name,lib$(LIBNAME).dylib.1 $(LDFLAGS) -o lib$(LIBNAME).dylib .o -L$(LIBRARY_DIR) -lcurl
I tried this, but the only result was another clang error: clang: error: unknown argument: '-rpath=/usr/lib'
Any advice towards installing twitcurl on an OS X system will be greatly appreciated.
----UPDATE----
I just wanted to put in one place all the steps I took to make this work, in case any OS X users with similar problems come across this in the future. My thanks to Andy Piper for the crucial pieces.
open the makefile and replace:
LDFLAGS += -Wl,-rpath-link=$(STAGING_DIR)/usr/lib
with:
LDFLAGS += -rpath $(STAGING_DIR)/usr/lib
and:
$(CC) -shared -Wl,-soname,lib$(LIBNAME).so.1 $(LDFLAGS) -o lib$(LIBNAME).so.1.0 .o -L$(LIBRARY_DIR) -lcurl
with:
$(CC) -dynamiclib -shared -Wl,-install_name,lib$(LIBNAME).dylib.1 $(LDFLAGS) -o lib$(LIBNAME).dylib *.o -L$(LIBRARY_DIR) -lcurl
(note that this is different by two characters from the advice another OS X user gave above)
after running make, copy libtwitcurl.dylib into /usr/lib/
Downloading the twitterClient (which is also the only code example I could find) will be the same, but for compiling it or your own programs you will need to link -lcurl as well. (g++ appname.cpp -ltwitcurl -lcurl)
Finally, once you compile a program, the path name will likely be incorrect in the executable which is created. Use install_name_tool to correct it. For me this looks like:
install_name_tool -change libtwitcurl.dylib.1 /usr/lib/libtwitcurl.dylib nameofexecutable
but if that doesn't work for you, use otool to find the actual path:
otool -L nameofexecutable
and then the first argument after -change should be the erroneous path for libtwitcurl. You can use otool again after running install_name_tool to be sure the change was successful.

I can get the shared / dynamic library to compile but needed to make a couple of adjustments to your Makefile:
LDFLAGS += -rpath $(STAGING_DIR)/usr/lib
and
$(CC) -dynamiclib -shared -Wl,-install_name,lib$(LIBNAME).dylib.1 $(LDFLAGS) -o lib$(LIBNAME).dylib *.o -L$(LIBRARY_DIR) -lcurl
I've now also built the associated twitterClient utility. To do so, I had to symbolically link libtwitcurl.dylib as libtwitcurl.dylib.1 and also change the consumer key and secret in the code to match a valid one from apps.twitter.com on my account. Works fine.
I assume you want to use the twitcurl library from code? Twitter maintains a Ruby-based utility, twurl, which has a similar function and may also be useful.

Related

Igraph makevars will not link to static library, i can use data structures but cannot functions while importing igraph c++ library

I am trying to install my C++ igraph library from https://github.com/igraph/igraph to visual studio code using the following method this is my makefile made according to this link.
CXX = g++
CXX_FLAGS = -std=c++17 -O3 -march=native -DNDEBUG
LIB = -Llib
INC = -Iinclude
.PHONY: all
all: a.out
a.out: main.cpp
$(CXX) $(CXX_FLAGS) $(INC) $(LIB) -ligraph -lm -lstdc++ -lgomp -lpthread -o $# main.cpp
.PHONY: clean
clean:
rm a.out
The compiler will always return something like:
g++ -std=c++17 -O3 -march=native -DNDEBUG -Iinclude -Llib -ligraph -lm -lstdc++ -lgomp -lpthread -o a.out main.cpp
/usr/bin/ld: /tmp/ccqJLfvi.o: in function `main':
main.cpp:(.text.startup+0x9): undefined reference to `igraph_rng_default'
/usr/bin/ld: main.cpp:(.text.startup+0x16): undefined reference to `igraph_rng_seed'
collect2: error: ld returned 1 exit status
make: *** [Makefile:12: a.out] Error 1
If i only want to use data structures such as igraph_t graph* it will work, but if i try to call fucntion it will return error and will not generate a.out file. It would be incredablly good if someone would be able to explain why this happens cuz it really got on my nerve right now.
Please follow the instructions in the documentation to set up your package to link to igraph.
Instructions to install igraph: https://igraph.org/c/html/latest/igraph-Installation.html Note that you must both build and install the package. Make a note of the location you used to install it to (the value of CMAKE_INSTALL_PREFIX)
Instructions on compiling your first igraph program: https://igraph.org/c/html/latest/igraph-Tutorial.html Unless you are already comfortable with writing C programs and linking them to external libraries, I strongly recommend that you use CMake to set up your project, as described in the linked tutorial. CMake works the same way on all platforms (Windows/macOS/Linux) and will automatically figure out how to link your program to igraph correctly. When configuring your project, be sure to set CMAKE_PREFIX_PATH to the location where you installed igraph earlier.

GCC Shared Library Problems

I'm trying to create a shared library on ubuntu using gcc
I just have one simple class(shared.h and shared.cpp) and one client to use it (main.cpp)
This is my makefile and I'm still not able to to get the program to compile.
all:
#compile object(fPIC: creates position independent code)
gcc -fPIC -Wall -g -c shared.cpp
#compile shared library
gcc -shared -Wl,-soname,libshared.so.1 -o libshared.so.1.0.1 shared.o -lc
#link shared library
gcc -g -o main main.cpp -L. -lshared
I'm confident the first line is correct
I am unsure what "-lc" does. I think it passes something to the linker?
I don't want to install the library, I just want to be able to link it from the current directory. I have tried: export LD_LIBRARY_PATH=.
but it does not seem to make a difference. Everything is in the current directory.
ERROR: /usr/bin/ld: cannot find -lshared
how do I get the compiler to check the current directory for my library?
The problem is not that it's not looking in the directory, the problem is that you've named the library "libshared.so.1.0.1". When you use -lshared, it's looking for a file named 'libshared.so' or 'libshared.a' in the library search path.
Most of the time, when using versioned system libraries, you'll provide a link to the latest one as 'libshared.so', even if you have installed 'libshared.so.1' or 'libshared.so.1.0.1'.
In your case, if you continue to leave the file named 'libshared.so.1.0.1', you'll want to create 2 symbolic links:
libshared.so - So that the library can be found using ld
libshared.so.1 - Since you declared the SO name as libshared.so.1 when building it, you need to provide this link, otherwise, the executable will not be able to find the proper shared library at runtime.
You don't write any dependencies, which is the purpose of Makefile-s. And you probably need to force the run path Perhaps something like
.PHONY: all clean
CXX=g++
CXXFLAGS=-g -Wall
all: main
main: main.o libshared.so
$(LINK.cpp) -o $# $< -Wl,-rpath,. -L. -lshared
libshared.so: shared.pic.o
$(LINK.cpp) -shared -o $^ $<
main.o: main.cc shared.hh
%.pic.o: %.cc
$(CXX) $(CXXFLAGS) -fPIC -c -o $# $<
#
clean:
rm -f *.o *.so main *~

How do you build for Basic 64-bit Amazon Linux from Arch Linux?

I figured it wouldn't work, but i just uploaded my program file from local machine to a new instance on Amazon EC2. Than tried to run it:
[ec2-user#domU-12-31-39-14-2A-1A ~]$ ./webserver.net
-bash: ./webserver.net: /lib/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory
Apparently there is no /lib/ld-linux-x86-64.so.2. It is a 64 bit Instance.
How would i compile/link on local machine targeting the EC2 instance. I don't want to build it on the instance.
My Makefile
OBJECTS= ./obj/hello.o
LDFLAGS = -L/usr/lib -lwt -lwthttp
./bin/webserver.net : $(OBJECTS)
g++ -o ./bin/webserver.net $(OBJECTS) $(LDFLAGS)
./obj/hello.o : ./src/hello.cpp
g++ -c ./src/hello.cpp -o ./obj/hello.o
.PHONY: clean
clean:
-rm -f obj/*.o bin/webserver.net core *~ src/*~
Update Statically linked file. There were undefined references until I added each library manually and in the right order. Is this necessary? or am I doing it wrong?
g++ -static -pthread -o ./bin/out.net ./obj/hello.o -lwthttp -lwt -lboost_thread -lboost_system -lboost_program_options -lboost_random -lboost_signals -lboost_filesystem -lboost_regex -lboost_serialization -lboost_date_time -lssl -lcrypto -lz -ldl
An ugly but simple solution might be to link statically your program.
A more elaborate solution could be to mimic the environment of the EC2 instance in e.g. a chroot-ed environment on your local machine.
In between you might copy the EC2's /usr/include and /usr/lib/libc.so... etc.. locally, but that is risky.
Perhaps also you could compile locally, and link on the EC2... (but that might not work)
A dynamic library lib*.so can be built with dependencies on other dynamic libraries. (for instance, try ldd /usr/lib/libgtk-3.so or ldd on some other system *.so library on your machine).
A static library lib*.a is essentially only a mix of *.o object files and don't know its dependencies.
So when linking statically, you need indeed to link all the libraries, in the correct order.

boost and cpp-netlib make compile ERROR

[SOLVED] created symlinks from /usr/lib/lib/* to /usr/lib*
[UPDATE 3] NEW VERSION:
Ok, I think I fixed something
use find / -name "libboost_system.*"
outout was
/usr/include/boost/lib/libboost_system.so
/usr/include/boost/lib/libboost_system.a
/usr/include/boost/lib/libboost_system.so.1.46.1
/usr/lib/lib/libboost_system.so
/usr/lib/lib/libboost_system.a
/usr/lib/lib/libboost_system.so.1.46.1
/usr/local/include/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/link-static/threading-multi/libboost_system.a
/usr/local/include/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/threading-multi/libboost_system.so.1.46.1
/usr/local/lib/libboost_system.so
/usr/local/lib/libboost_system.a
/usr/local/lib/libboost_system.so.1.46.1
/root/tmp/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/link-static/threading-multi/libboost_system.a
/root/tmp/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/threading-multi/libboost_system.so.1.46.1
why are these files in /usr/lib/lib ? and is it a problem ?
and the ls -l /usr/lib/lib | grep boost_system
ls -l /usr/lib/lib | grep boost_system
-rw-r--r-- 1 root root 21574 2011-05-09 15:15 libboost_system.a
lrwxrwxrwx 1 root root 25 2011-05-09 15:15 libboost_system.so -> libboost_system.so.1.46.1
-rwxr-xr-x 1 root root 20053 2011-05-09 15:15 libboost_system.so.1.46.1
atm my makefile looks like
LIBPATH=-I/usr/local/include/cpp-netlib
LIBS=$(LIBPATH) -lboost_system -lboost_filesystem -lboost_thread -lpthread
LD=g++ -g
CPP=g++ -c -g $(LIBS)
P=.
OBJ=$(P)/tmp/main.o $(P)/tmp/CLink.o $(P)/tmp/CFetcher.o
main: $(OBJ); $(LD) $(OBJ) $(LIBS) -o $#
$(P)/tmp/CLink.o: $(P)/src/CLink.cpp $(P)/include/CLink.h; $(CPP) -c $< -o $#
$(P)/tmp/CFetcher.o: $(P)/src/CFetcher.cpp $(P)/include/CFetcher.h; $(CPP) -c $< -o $#
$(P)/tmp/main.o: $(P)/src/main.cpp $(P)/include/CLink.h $(P)/include/CFetcher.h ; $(CPP) -c $< -o $#
all:
touch $(P)/tmp/*.o;
touch main;
rm -f $(P)/tmp/*.o;
rm -f main;
make main;
The Compiler output is lie
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/main.cpp -o tmp/main.o
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/CLink.cpp -o tmp/CLink.o
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/CFetcher.cpp -o tmp/CFetcher.o
g++ -g ./tmp/main.o ./tmp/CLink.o ./tmp/CFetcher.o -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -o main
So for me all looks nice but when i try to run the program
./main
./main: error while loading shared libraries: libboost_system.so.1.46.1: cannot open shared object file: No such file or directory
The -l flags must come after the source files on linker command-line.
Yes, that means you'll have to split the LD definition to LD and LIBS, put all the -L and -l flags in the later and change the link command to:
$(LD) $(OBJ) $(LIBS) -o $#
The library (.so (dynamic) or .a (static)) files have to be the same version as the headers. While there are boost 1.46.1 headers installed in /usr/local/include/boost_1_46_1/, the corresponding library files don't seem to be installed at all. The only installed libraries are version 1.40.0 in /usr/lib, so the linker finds those (/usr/lib would be searched by default even if you didn't include the -L/usr/lib flag), but they don't contain the symbols expected by 1.46.1.
Note that when linking against shared library (using shared libraries is strongly recommended in Linux), the linker looks for the file with .so extension, but that is usually symlink to a file with added version suffix and the linker reads it and records the target name in the binary. That way programs compiled against the .1.40 will continue to work when 1.46 is installed, because the libboost*.so.1.40.0 may (and have to) stay around after the .so is redirected to the 1.46.1 version.
It should be even possible to install like:
/usr/local/lib/boost_1_46_1/libboost_system-mt.so -> /usr/local/lib/libboost_system-mt.so.1.46
/usr/local/lib/libboost_system-mt.so.1.46 -> /usr/local/lib/libboost_system-mt.so.1.46.1
/usr/local/lib/libboost_system-mt.so.1.46.1
and compile using -L/usr/local/lib/boost_1_46_1, though I currently can't find any package that would do it to confirm this. This way you could have development files for multiple versions installed and switch between them using explicit -I and -L flags while dynamic linker would still find the runtime files, for which it only looks in /usr/local/lib, /usr/lib and /lib (it can be configured in /etc/ld.so.conf, but that's the default).
Execute your application with strace. This will show the location were you app is looking for your boost libs. In my case an app was looking in /usr/lib/x86_64-linux-gnu for boost libs where the actual location was /usr/lib/lib. A simple export statement adding the paths for the boost shared libs in my case LD_LIBRARY_PATH=/usr/lib/lib worked a treat.
output from strace
open("/usr/lib/x86_64-linux-gnu/libboost_system.so.1.46.1", O_RDONLY) = -1 ENOENT (No such file or directory)
exit_group(127) = ?

LIBPATHS not being used in Makefile, can't find shared object

I'm having trouble getting a sample program to link correctly (in this case against the ICU library). When I do 'make', everything builds fine. But when I run it, it says it can't find one of the .so's. I double checked they're all installed in /usr/local/lib. What I discovered was it was looking in /usr/lib. If I symlink from there to there actual location, it works.
Why is my LIBPATHS being ignored or not used?
Here is the Makefile
CC = g++
INCPATHS = -I/usr/local/include
CFLAGS = -c -Wall $(INCPATHS)
LIBPATHS = -L/usr/local/lib/
LIBS = $(LIBPATHS) -licuio -licui18n -licuuc -licuio -licudata
EXECUTABLE = prog
print_linking = echo -e "\033[32m" "Linking: $<" "\033[39m"
print_compiling = echo -e "\033[33m" "Compiling: $<" "\033[39m"
print_cleaning = echo -e "\033[31m" "Cleaning: `pwd`" "\033[39m"
all: main
# [target]: [dependencies]
# <tab> system command
main: main.o
#$(print_linking)
#$(CC) -o $(EXECUTABLE) main.o $(LIBS) >> /dev/null
main.o: main.cpp
#$(print_compiling)
#$(CC) $(CFLAGS) main.cpp
clean:
#$(print_cleaning)
#rm -rf *.o *~ $(EXECUTABLE)
Your LIBPATHS tells the linker where to find the library when linking to resolve symbols.
At runtime, you need to tell the loader where to find the library. It doesn't know about what happened at compile time. You can use the LD_LIBRARY_PATH variable as mentioned above, or check into /etc/ld.so.conf and it's friends.
The path to the dynamic libraries isn't stored in the executable by default. You can either:
use LD_LIBRARY_PATH at runtime to give a path where to search for dynamic libraries
use -Wl,-Rpath at link time to store a path in the executable
One solution is to add /usr/local/lib to the environment variable LD_LIBRARY_PATH.
You can do this in your .profile or .cshrc
You can also get the linker to store the full path to the library in the executable.
Both solutions have different tradeoffs with respect to using the execultable by different users and/or on different machines.