How to specify static linking in makefile? - macos

I usually use the "--enable-static" option when running a configure script to statically link the resulting executable.
However, right now I am trying to compile g3data, which comes only with a makefile (no configure file). I tried adding the "-bstatic" option in the makefile (the "-static" option does not work on my system: Mac OS X 10.6.8, see here for an explanation), but while the compilation was successful and I can run the program, it was not statically linked...
What should I do to achieve static linking in a makefile like this? Here is what I have right now:
CC=gcc
CFLAGS=-Wall `pkg-config --cflags gtk+-2.0` -arch i386 -arch x86_64 -arch ppc -bstatic
LIBS=`pkg-config --libs gtk+-2.0`
LDFLAGS=-arch i386 -arch x86_64 -arch ppc -bstatic
#bindir ?= /usr/bin
#mandir ?= /usr/share/man
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
all: g3data
g3data: main.o sort.o points.o drawing.o #g3data.1.gz
$(CC) $(CFLAGS) -o g3data main.o sort.o points.o drawing.o $(LIBS) -bstatic
strip g3data
main.o: main.c main.h strings.h vardefs.h
sort.o: sort.c main.h
points.o: points.c main.h
drawing.o: drawing.c main.h
#g3data.1.gz: g3data.sgml
# rm -f *.1
# onsgmls g3data.sgml | sgmlspl /usr/share/sgml/docbook/utils-0.6.14/helpers/docbook2man-spec.pl
# gzip g3data.1
clean:
rm -f *.o g3data g3data.1.gz *~ manpage.*
install:
install g3data $(bindir)
install g3data.1.gz $(mandir)/man1
uninstall:
rm $(bindir)/g3data

Assuming -bstatic is the right option for your linker, and assuming you do have static versions of the necessary libraries, I would expect you need to put that option before the list of $(LIBS), as if it's like the -Bstatic option for the GNU linker then it only affects libraries listed after the option.

Related

compiler error gcc-8: error: unrecognized command line option '-no-pie'

I am trying to compile using this makefile but got this error. I can compile using school's linux computer with gcc 6.3. I tried using my MacOS mojave using a few different version of gcc from homebrew (gcc-8, gcc-4.9, gcc-6) but I get this error consistently.
CC = gcc-8
OPT = -O3 -g
LIBS = -lz -lcvp -lz
FLAGS = -std=c++11 -L. $(LIBS) $(OPT) -no-pie
OBJ = myprogram.o
DEPS = cvp.h myprogram.h
all: cvp
cvp: $(OBJ)
$(CC) $(FLAGS) -o $# $^
%.o: %.cc $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
.PHONY: clean
clean:
rm -f *.o cvp
Going off information found here: https://github.com/xd009642/tarpaulin/issues/7#issuecomment-317180523
The problem may very well be related to how gcc is built: "Builds of gcc that don't have the --enable-default-pie flag set at compile time because they are too old or have the --disable-default-pie flag just don't have the -no-pie linker flag"
You might need to update or recompile gcc for that environment to be able to use that flag if important to you.

How to build static library .a for ARM using cross compiler?

I was trying to compile statically cpp-netlib and rpclib for ARM device.(Same as ZEDboard)
Everything i did is changed the compiler and system settings in CMakeLists.txt file.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /home/a/buildroot-2018.05/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/)
set(tools /home/a/buildroot-2018.05/output/host/bin/)
set(CMAKE_C_COMPILER ${tools}arm-buildroot-linux-uclibcgnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}arm-buildroot-linux-uclibcgnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
After Makefile is created by cmake i ran make and no output has been produced. As i understand build directories should appear.
For the rpclib things went better. It has compiled the librpc.a file but unftunately its not linking to my program.
arm-buildroot-linux-uclibcgnueabihf-g++ -I/home/a/rpclib/include/ -Xlinker -static /home/a/rpclib/librpc.a main.cpp
produces this output:
/home/a/buildroot-2018.05/output/host/lib/gcc/arm-buildroot-linux-uclibcgnueabihf/6.4.0/../../../../arm-buildroot-linux-uclibcgnueabihf/bin/ld: cannot find -lgcc_s
/home/a/buildroot-2018.05/output/host/lib/gcc/arm-buildroot-linux-uclibcgnueabihf/6.4.0/../../../../arm-buildroot-linux-uclibcgnueabihf/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
but there is gcc_s in the sysroot directory.
~/buildroot-2018.05/output/host/arm-buildroot-linux-uclibcgnueabihf$ find ./ -name *gcc_s*
./sysroot/lib/libgcc_s.so
./sysroot/lib/libgcc_s.so.1
./sysroot/usr/include/boost/asio/detail/gcc_sync_fenced_block.hpp
./sysroot/usr/include/boost/atomic/detail/caps_gcc_sync.hpp
./sysroot/usr/include/boost/atomic/detail/ops_gcc_sync.hpp
./sysroot/usr/include/boost/atomic/detail/ops_gcc_sparc.hpp
./sysroot/usr/include/boost/atomic/detail/caps_gcc_sparc.hpp
./sysroot/usr/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
./lib/libgcc_s.so
./lib/libgcc_s.so.1
I guess i am missing something important about cross-compilation.
So basically i have 3 questions:
Can you suggest some resources about cross-compilation for embdedd devices?
How to compile cpp-netlib?
How to link already compiled librpc?
Actually buildroot supports building static libraries.
Steps to build a custom library using buildroot:
Create a folder inside buildroot/package folder with the name of target library.
e.g. my path looks like this /home/a/buildroot-2018.05/package/rpclib
Create Config.in file in target library dir with the needed parameters which can be checked in buildroot manual or better
Create [package-name].mk
Then add entry in /buildroot/package/Config.in
Then package can be marked for installation in menuconfig/target pacckages
My Config.in file for rpclib
config BR2_PACKAGE_RPCLIB
bool "rpclib"
depends on BR2_INSTALL_LIBSTDCPP
depends on BR2_USE_WCHAR
help
rpclib is a modern C++ msgpack-RPC server and client library
http://rpclib.net
My rpclib.mk file
RPCLIB_VERSION = v2.2.1
RPCLIB_SITE = $(call github,rpclib,rpclib,$(RPCLIB_VERSION))
RPCLIB_INSTALL_STAGING = YES
RPCLIB_INSTALL_TARGET = NO
RPCLIB_CONF_OPTS = -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF
$(eval $(cmake-package))
And entry in Config.in in the buildroot/packages dir
source "package/rpclib/Config.in"
After executing make i received
./output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/lib/librpc.a
Working in my little beatle (https://gitlab.com/melviso1/beatle) I have a custom makefile for building rpclib without using cmake stuff (I apologize but I really hate cmake and similar tools). Maybe that can help.
Put it in the root of rpclib for building, clean or install. Please review tabs in the following script, because my pasting here can make some loses.
I used this to compile rpclib inside arm. For cross-compiling you could edit and change build tools.
CXXFLAGS=-std=c++0x -O3 -pthread -DASIO_STANDALONE -DRPCLIB_ASIO=clmdep_asio -DRPCLIB_FMT=clmdep_fmt -DRPCLIB_MSGPACK=clmdep_msgpack -Wall
INCLUDE=-Iinclude -I./dependencies/include
OBJS=obj/format.o obj/posix.o obj/client.o obj/client_error.o obj/response.o obj/server_session.o obj/dispatcher.o obj/optional.o obj/rpc_error.o obj/server.o obj/this_handler.o obj/this_server.o obj/this_session.o
all: obj librpc.a
obj:
mkdir -p obj
librpc.a: $(OBJS)
ar -r -s librpc.a $(OBJS)
obj/format.o: dependencies/src/format.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./dependencies/src/format.cc -o obj/format.o
obj/posix.o: dependencies/src/posix.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./dependencies/src/posix.cc -o obj/posix.o
obj/client.o: lib/rpc/client.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/client.cc -o obj/client.o
obj/client_error.o: lib/rpc/detail/client_error.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/client_error.cc -o obj/client_error.o
obj/response.o: lib/rpc/detail/response.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/response.cc -o obj/response.o
obj/server_session.o: lib/rpc/detail/server_session.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/server_session.cc -o obj/server_session.o
obj/dispatcher.o: lib/rpc/dispatcher.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/dispatcher.cc -o obj/dispatcher.o
obj/optional.o: lib/rpc/nonstd/optional.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/rpc_error.o: lib/rpc/rpc_error.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/server.o: lib/rpc/server.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_handler.o: ./lib/rpc/this_handler.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_server.o: lib/rpc/this_server.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_session.o: ./lib/rpc/this_session.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
install:
cp -rf include/rpc /usr/local/include/
cp librpc.a /usr/local/lib/
uninstall:
rm -rf /usr/local/include/rpc
rm /usr/local/lib/librpc.a
clean:
rm -f librpc.a
rm -f obj/*
.PHONY: obj clean install uninstall`

How to generate debug information in gcc/clang with separated compilation/link process in Makefile (-c -g)?

I had made a Makefile from Hilton Lipschitz's blog, and made little changes to it in order to generate debug information. Main parts are listed:
CC := clang -arch x86_64
CFLAGS := -c -O0
$(TARGET): $(OBJECTS)
#echo " Linking $(TARGET)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDLIST)
#echo "Compiling $<..."; $(CC) $(CFLAGS) $(INC) -o $# $<
debug: CFLAGS += -g
debug: $(TARGET)
Now make runs these commands (paths are summarized with ...):
clang -arch x86_64 -c -O0 -I... -o build/program.o src/program.c
clang -arch x86_64 build/program.o -o bin/program -L...
While make debug runs these commands:
clang -arch x86_64 -c -O0 -g -I... -o build/program.o src/program.c
clang -arch x86_64 build/program.o -o bin/program -L...
The problem is when I execute make or make debug, no program.dSYM subfolder will be made in bin folder. Instead, when I compile without -c argument:
clang -arch x86_64 -g -O0 -I... -L... -o bin/program.o src/program.c
both executable file and .dSYM are created in bin folder.
How can I add debugging information generation feature to this Makefile while separating compiling and linking process?
In which step (compiling/linking) debug information is produced?
UPDATE: I created a GitHub repo and uploaded related Makefile and source to it. To reproduce the problem, please run these commands in your terminal:
git clone https://github.com/hamid914/gdb-lldb-test.git
cd gdb-lldb-test
make debug
The last line, make debug executes these commands:
clang -arch x86_64 -c -O0 -std=c11 -g -I include -I include/libs -I /usr/local/include -o build/program.o src/program.c
clang -arch x86_64 build/program.o -o bin/program -L /usr/local/lib -lm -g
And content of bin folder is:
$ ls bin
program
While if I run clang without -c argument:
clang -arch x86_64 -O0 -std=c11 -g -I include -I include/libs -I /usr/local/include -L /usr/local/lib -lm -o bin/program src/program.c
Contents of bin folder are:
$ ls bin
program program.dSYM
You need to add -g to the linker recipe as well in order to generate .dSYM files, the standard way would be to add
debug: LDFLAGS += -g
but the example you're following defines its own variables for no good reason, it looks like LIB should work however.

adding shared library path to Makefile

I want to add the shared library path to my Makefile. I have put in the export command in the makefile, it even gets called, but I still have to manually export it again.
What is the correct approach?
Makefile:
SOURCES = kwest_main.c fusefunc.c dbfuse.c logging.c dbbasic.c dbinit.c dbkey.c metadata_extract.c plugins_extraction.c import.c
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
INCLUDE = ../include
LIB = ../lib
EXE = kwest
CC = gcc
CCFLAGS = -g -Wall -Wextra -std=gnu99 -pedantic-errors -I$(INCLUDE)
OFLAGS = -c
ARCH = $(shell getconf LONG_BIT)
X = -D_FILE_OFFSET_BITS=$(ARCH)
OBJECTS = $(SOURCES:.c=.o)
$(EXE) : $(OBJECTS)
$(CC) -o $(EXE) $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) $(OFLAGS) $(CCFLAGS) $<
fusefunc.o: fusefunc.c
$(CC) $(OFLAGS) $(CCFLAGS) $< $X
kwest_libs: kw_taglib
--->export LD_LIBRARY_PATH=$(LIB):$LD_LIBRARY_PATH
kw_taglib: plugin_taglib
plugin_taglib: plugin_taglib.o kwt_upd_meta.o
gcc -g -shared -I$(INCLUDE) -Wl,-soname,libkw_taglib.so -o $(LIB)/libkw_taglib.so -ltag -ltag_c plugin_taglib.o kwt_upd_meta.o
plugin_taglib.o:
gcc -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -std=gnu99 -fPIC -ltag_c -c plugin_taglib.c
kwt_upd_meta.o:
g++ -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -fPIC -ltag kwt_upd_meta.cpp
c: clean
clean:
rm -rf *.o
rm -rf *.db
ca: cleanall
cleanall: clean
rm -rf $(EXE)
ob: cleanall
rm -rf ~/.config/$(EXE)/
Execution:
$ ./kwest mnt
./kwest: error while loading shared libraries: libkw_taglib.so: cannot open shared object file: No such file or directory
$ export LD_LIBRARY_PATH=../lib:D_LIBRARY_PATH
$ ./kwest mnt
"executes correctly"
The usual way is to copy the dynamic library during the default make and to one of the standard library path
/usr/local/bin
or one of your project library path and add the library to executable using
-L/project/specific/path
during make install.
As already mentioned here, the thing you probably want is the linker option -rpath.
Like that, you can set a default search path for the binary. Looks like you even already use -rpath in your makefile, but you specify the wrong path:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
So the binary will search in the current directory for dyn-libraries.
However, you add ../lib to your LD_LIBRARY_PATH later, for execution of the binary, so the given path . seems to be wrong.
Please take a try for the following fix:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=../lib
Like that you should not need to specify a LD_LIBRARY_PATH for execution.

How should a very simple Makefile look like for Cuda compiling under linux

I want to compile a very basic hello world level Cuda program under Linux. I have three files:
the kernel: helloWorld.cu
main method: helloWorld.cpp
common header: helloWorld.h
Could you write me a simple Makefile to compile this with nvcc and g++?
Thanks,
Gabor
I've never heard of Cuda before, but from the online documentation it looks as if X.cu is supposed to be compiled into X.o, so having helloWorld.cu and helloWorld.cpp is not a good idea. With your permission I'll rename the "kernel" helloKernel.cu, then this should work:
NVCC = nvcc
helloWorld.o: helloWorld.cpp helloWorld.h
$(NVCC) -c %&lt -o $#
helloKernel.o: helloKernel.cu
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
(Note that those leading spaces are tabs.)
If that works, try a slicker version:
NVCC = nvcc
helloWorld.o: %.o : %.cpp %.h
helloKernel.o: %.o : %.cu
%.o:
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
Just in case, here's my variant. I use it to compile CUDA projects on Mac, but I think it will suit Linux too. It requires CUDA SDK.
BINDIR = ./ # places compiled binary in current directory
EXECUTABLE := helloWorld
CCFILES := helloWorld.cpp
CUFILES := helloWorld.cu
# an ugly part - setting rootdir for CUDA SDK makefile
# look for common.mk - I don't know where SDK installs it on Linux -
# and change ROOTDIR accordingly
ROOTDIR := /Developer/GPU\ Computing/C/common
include $(ROOTDIR)/../common/common.mk
My version, verbose but transparent:
myapp: myapp.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
myapp.o: myapp.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
matrixMul: matrixMul.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
# It MUST be named .cu or nvcc compiles as regular C !!! (no __global__)
matrixMul.o: matrixMul.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
Here is an example what my current project looks like. As you can see there is a few OpenGL libraries
ce : cudaExample.c cudaExample.h
cp cudaExample.c cudaExample.cu
/usr/local/cuda/bin/nvcc -arch=sm_20 -o ce -lglut -lGL -lGLU -lXext -lXmu -lX11 -lm cudaExample.cu
then run make ce
and ./ce

Resources