Im trying to compile/link .o file(s) into a .dll file under Ubuntu...
i get it nearly to work but i have a problem with static linking these .o file(s) ...
Here is what ive done:
First i installed all dependencies ... then i build the following application:
https://github.com/Zeranoe/mingw-w64-build
On my Ubuntu.
After that i create the .o files from the application with normal "sudo make" command...
Now i had all .o file(s) ready ... then i modified the .o files with "dlltool" so now i have the opportunity to link them to a .dll file with "mingw" ... it works only in "shared mode" ... not in "static mode" ...
this is the working command:
sudo /home/robert/Downloads/mingw-32/x86_64/i686/bin/i686-w64-mingw32-g++ -shared -lmsvcrt -Wl,-subsystem,windows *.o -o phpcppdll.dll
and this is not working:
sudo /home/robert/Downloads/mingw-32/x86_64/i686/bin/i686-w64-mingw32-g++ -static -lmsvcrt -Wl,-subsystem,windows *.o -o phpcppdll.dll
and then i get the following error - with this command:
/home/robert/Downloads/mingw-32/x86_64/i686/bin/../lib/gcc/i686-w64-mingw32/11.2.1/../../../../i686-w64-mingw32/bin/ld: /home/robert/Downloads/mingw-32/x86_64/i686/bin/../lib/gcc/i686-w64-mingw32/11.2.1/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text+0x3c): undefined reference to `WinMain#16'
collect2: error: ld returned 1 exit status
but i dont get further maybe you have an idea ...
Okay - i got it to work with the -nostartfiles flag ... but it dont make sense because all .dlls are not static ... but shared ...
Related
I am trying to compile the mosquitto library with my custom c program. So WHat I have done is wrote a hello.c file, git cloned the latest mosquitto library from the below repository:
https://github.com/eclipse/mosquitto.git
and compiled it with the make command as below:
make
I had to remove the doc target as it was asking for some dependancy library. I don't have admin rights on this machine, hence don't want to be blocked by any dependancy lib. After the compilation what I have is the below:
src/mosquitto
./lib/libmosquitto.so.1
The I copied the libmosquitto.so.1 shared lib into a local folder called ~/hello/:
~/hello$ cp ~/mosquitto/lib/libmosquitto.so.1 .
then wrote a hello.c inside ~/hello/ which is as below:
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
I can compile the hello.c and run it as below:
gcc -o hello hello.c
./hello
Hello World
But if I try to link the binary with the mosquitto library I get an error like the below:
gcc -o hello hello.c -lmosquitto
/usr/bin/ld: cannot find -lmosquitto
collect2: error: ld returned 1 exit status
The libmosquitto.so.1 lives in the same folder as the hello.c. I don't want to install the mosquitto library, rather would like to keep in a local folder and be able to link it. I have also tried the below with the hope that the -L. would point the linker to the present directory for the shared lib file but still get the same error:
gcc -o hello hello.c -L. -lmosquitto
/usr/bin/ld: cannot find -lmosquitto
collect2: error: ld returned 1 exit status
My ultimate objective is to cross compile the library for an arm target. So really need to understand how the linking of the shared library is failing so that I can use the same experience while cross compiling and link for the target. At the moment I am doing this on a x86 platform.
Can anyone please help?
/usr/bin/ld: cannot find -lmosquitto
The linker doesn't look for libmosquitto.so.1 -- it only looks for libmosquitto.a or libmosquitto.so.
Solution: ln -s libmosquitto.so.1 libmosquitto.so
./pub: error while loading shared libraries: libmosquitto.so.1: cannot open shared object file: No such file or directory
The problem here is that the runtime loader doesn't look in the current directory for libmosquitto.so.1 -- it only looks in system-configured directories.
You could fix this by adding export LD_LIBRARY_PATH=$HOME/mosquitto/lib, but this is suboptimal -- your binary will work or not depending on the environment.
A better solution is to change your link command like so:
gcc -o hello hello.c -L. -lmosquitto -Wl,-rpath=$HOME/mosquitto/lib
I have no trouble building my application under Visual Studio's environment, but due to lack of experience, I am having trouble under Linux/GCC. Although GCC compiles my app successfully, but it reports linker errors.
The first thing I did was to build a shared library using CMakeLists.txt. The file has no ‘make install’ so I manually copied the shared library file to a global location as follows:
sudo cp libibpp.a /usr/local/lib/
Since applications built with the IBPP library require you to include a single header file, I copied it to a global location:
sudo cp ibpp.h /usr/local/include/
So far, so good but when I run CMake for my application, I am getting linker errors such as:
undefined reference to ‘isc_create_database’
I am successfully using many ‘shared libraries’ in my application (such as Boost Regex/Filesystem/Chrono/DateTime/Thread). The only ‘static library’ that I am using is IBPP (libibpp.a).
I suspect that I am missing something in my application’s CMakeListst.txt:
cmake_minimum_required(VERSION 3.10.2)
project(myapp)
file(GLOB src "*.h" "*.cpp")
add_executable(myapp ${src})
target_link_libraries(myapp ibpp icuuc icudata boost_regex boost_system boost_filesystem
boost_chrono boost_date_time boost_thread pthread)
add_definitions(-DIBPP_LINUX)
Can someone provide me with some hints as to why I get linker errors related to IBPP?
UPDATED:
User n.m. asked me to build using the VERBOSE option, so here is the output:
/usr/bin/cmake -E cmake_link_script CMakeFiles/myapp.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/myapp.dir/appServer.cpp.o CMakeFiles/myapp.dir/app_env.cpp.o CMakeFiles/myapp.dir/app_setting.cpp.o CMakeFiles/myapp.dir/authenticationServer.cpp.o CMakeFiles/myapp.dir/bustacheTestStencil.cpp.o CMakeFiles/myapp.dir/commonKeys.cpp.o CMakeFiles/myapp.dir/dataFetcher.cpp.o CMakeFiles/myapp.dir/fighterKeys.cpp.o CMakeFiles/myapp.dir/fighterProfileJsonGenerator.cpp.o CMakeFiles/myapp.dir/fighterProfileMarkupGenerator.cpp.o CMakeFiles/myapp.dir/fighterStorage.cpp.o CMakeFiles/myapp.dir/forwardProxyServer.cpp.o CMakeFiles/myapp.dir/headerProcessor.cpp.o CMakeFiles/myapp.dir/homepageStencil.cpp.o CMakeFiles/myapp.dir/httpUtils.cpp.o CMakeFiles/myapp.dir/locale.cpp.o CMakeFiles/myapp.dir/main.cpp.o CMakeFiles/myapp.dir/markupServer.cpp.o CMakeFiles/myapp.dir/myTools.cpp.o CMakeFiles/myapp.dir/stdafx.cpp.o CMakeFiles/myapp.dir/unicodeFunctions.cpp.o CMakeFiles/myapp.dir/utils.cpp.o -o myapp -libpp -licutu -licutest -licuio -licui18n -licuuc -licudata -lboost_regex -lboost_system -lboost_filesystem -lboost_chrono -lboost_date_time -lbustache -lboost_thread -lpthread
//usr/local/lib/libibpp.a(_ibpp.cpp.o): In function `ibpp_internals::GDS::Call()':
_ibpp.cpp:(.text+0x2c): undefined reference to `isc_create_database'
_ibpp.cpp:(.text+0x3b): undefined reference to `isc_attach_database'
....
_ibpp.cpp:(.text+0x2bd): undefined reference to `isc_service_start'
_ibpp.cpp:(.text+0x2cf): undefined reference to `isc_service_query'
collect2: error: ld returned 1 exit status
CMakeFiles/myapp.dir/build.make:640: recipe for target 'myapp' failed
make[2]: *** [myapp] Error 1
make[2]: Leaving directory '/home/carol/Documents/vm_shared/AppServer/build'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/myapp.dir/all' failed
make[1]: *** [CMakeFiles/myapp.dir/all] Error 2
make[1]: Leaving directory '/home/carol/Documents/vm_shared/AppServer/build'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Problem solved thanks to comment by n.m. above. Since I was not including libfbclient, I was getting the "undefined references to 'isc_create_database', and other 'isc_...' messages.
Using the settings below, I am now able to use my precompiled/built IBPP library instead of having to include the source code into my application!
Here is a simplified, very barebones CMakeLists.txt that demonstrates what is required to get your IBPP.a implemented into your app without having to include the IBPP source into your app:
file(GLOB src "*.cpp")
add_executable(myapp ${src})
target_link_libraries(myapp ibpp fbclient)
Make note of the order, libibpp must be before libfbclient.
I'm using the Visual C++ for Linux plugin. I can run a basic Hello world without problems. My actual project uses a .lib. It compiles fine but I get an error during linking (this is copied from Visual Studio's output pane):
ClCompile:
Starting remote build
Compiling sources:
Invoking g++
g++ -c -x c++ /home/devbox/projects/LinuxProgServ/LinuxProgServ/main.cpp -I /home/devbox/projects/LinuxProgServ/include/libuv -I /home/devbox/projects/LinuxProgServ/../include/lubuntu -I "/home/devbox/projects/LinuxProgServ/../include/lubuntu/x86_64-linux-gnu" -g2 -gdwarf-2 -o "/home/devbox/projects/LinuxProgServ/obj/x64/Debug/main.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O0 -fno-strict-aliasing -fno-omit-frame-pointer -fthreadsafe-statics -fexceptions -frtti -std=c++11
main.cpp
Done compiling '/home/devbox/projects/LinuxProgServ/LinuxProgServ/main.cpp'
Link:
Linking objects
Invoking ld
g++ -o "/home/devbox/projects/LinuxProgServ/bin/x64/Debug/LinuxProgServ.out" -Wl,--no-undefined /home/devbox/projects/LinuxProgServ/obj/x64/Debug/main.o -llibuv.lib
/usr/bin/ld: cannot find -llibuv.lib
collect2: error: ld returned 1 exit status
libuv.lib is specified in Project Properties>Linker>Input>Library Dependencies. I tried the following without success:
Copy the lib to /home/devbox/projects/lib and add that directory to
the linker command with -L, both using Visual Studio's additional
library folder field and directly in the Additional command line
options field. This results in the same final command.
Copy the lib to the output directory and set it to be copied
Add the local Windows path to Visual Studio's additional library folders
Add the linux path from #1 to Visual Studio's additional library folders
Try with another library
I made the same project but for Windows just to be sure and it works.
Am I missing something? Obviously I could just run the commands myself or use any variant of *make but that's not the point.
When you pass a library to g++ with -l, g++ helpfully prefixes the name you give with lib then looks for a file of that name with a .so or .a extension on the library search path. By convention, shared libraries (dlls) have the .so extension and static libraries the .a extension.
The route of least resistance would be to build your library with the .a extension, i.e. libuv.a then specify it to the VCLinux project library dependencies as uv. And specify the library search path with -L, as you do in your step 1.
Alternatively, you can put the full path of the library on the g++ link command line, without -l prefix, i.e. /home/devbox/projects/lib/libuv.lib and g++ will use it in the same way it uses other object files. Set via Linker/All Options/Additional Options.
Update: on reflection, this second approach won't work. Although g++ (gcc) will accept the library as an input when specified with its fully qualified path, the library must appear after the program object files for references to be resolved. Unfortunately there is no control over positioning of Additional Options in VCLinux which always puts them at the front of the parameter list on the g++ command line, i.e. before the object file(s). :(
And, at the risk of stating the obvious, the library must be built on Linux with g++ and be located on a path visible to g++ when linking your program.
I'm playing with shared library linking and loading procedures, and trying to learn about different ways to tackle the loading error:
error while loading shared libraries: ... : cannot open shared object file: No such file or directory
I managed to solve it by using LD_LIBRARY_PATH and by using rpath. I now try to comprehend the usage of ldconfig and how it can solve it, too [some of my web sources: 1, 2, 3 ]
So, I've got the following source files: test.c func1.c func2.c. Here's what I do:
Compiling them into PIC .obj files:
$ gcc -Wall -fPIC -c *.c
Creating a shared library from the object files, naming it 'libshared.so', and using 'soname':
$ gcc -shared -Wl,-soname,libshared.so -o libshared.so *.o
Linking with a shared library by telling GCC where to find the shared library (the ... is just an abbreviation for my personal shared library path):
$ gcc -L/home/.../my_shared_library -Wall -o mytest test.c -lshared
Now, I try running it, and get the loading error:
./mytest: error while loading shared libraries: libshared.so: cannot open shared object file: No such file or directory
So I try telling the loader to search my private directory for the shared library file:
ldconfig -n home/.../my_shared_library
(I also tried it with: ldconfig -n .-L when my working directory is home/.../my_shared_library)
and tried running it once again, but I still get the same error. What am I doing wrong?
Use GNU Libtool to simplify the process and avoid such errors.
Also use -fPIC option when you build your library.
Read Program Library HowTo & Drepper's paper: How to Write Shared Libraries
You probably want to set the rpath. See this question.
You might load your plugin at runtime with dlopen(3). Notice that shared object paths without any / are handled specially.
I trying to get a cmake build system working on linux. The project contains a bunch of executables and two libraries. One of the executables is first built as a library, then that library is linked with the object file containing the man subroutine. This was done because the rest of the executables depend on that library. The tricky part is that the main subroutine is defined inside a module that the rest of sources depend on so this needs to be compiled before the rest of the sources. The effect is that the main subroutine gets added to the resulting library. This seems to work fine on Mac OS X but, the linking state fails on Linux.
The cmake file for the failing part looks like
cmake_minimum_required (VERSION 2.8)
# Create an empty variable to hold all the source files.
set (vmec_sources "")
# Add subdirectory for all the sources.
add_subdirectory (Sources)
add_library (vmec STATIC ${vmec_sources})
add_dependencies (vmec stell)
# Define an executable and link all libraries.
add_executable (xvmec ${CMAKE_CURRENT_SOURCE_DIR}/Sources/General/vmec_main.f)
add_dependencies (xvmec vmec)
target_link_libraries (xvmec vmec stell)
if ((NOT ${NETCDF_C} STREQUAL "") AND (NOT ${NETCDF_F} STREQUAL ""))
target_link_libraries (xvmec ${NETCDF_C} ${NETCDF_F})
endif ()
When running cmake, everything configures fine and generates a make file when I run make Mac OS X everything works fine. When I run make on Linux it fails.
The output from the make VERBOSE=1 On Linux produces
Linking Fortran executable ../build/bin/xvmec
cd /home/user/reconstruction/VMEC2000 && /usr/bin/cmake -E cmake_link_script CMakeFiles/xvmec.dir/link.txt --verbose=1
/usr/bin/gfortran -cpp -D NETCDF -I /usr/include CMakeFiles/xvmec.dir/Sources/General/vmec_main.f.o -o ../build/bin/xvmec -rdynamic ../build/lib/libvmec.a ../build/lib/libstell.a /usr/lib/libnetcdf.so /usr/lib/libnetcdff.so
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/libgfortranbegin.a(fmain.o): In function `main':
(.text+0x26): undefined reference to `MAIN__'
collect2: ld returned 1 exit status
make[2]: *** [build/bin/xvmec] Error 1
make[2]: Leaving directory `/home/user/reconstruction'
make[1]: *** [VMEC2000/CMakeFiles/xvmec.dir/all] Error 2
make[1]: Leaving directory `/home/user/reconstruction'
make: *** [all] Error 2
On Mac OS X, I get
Linking Fortran executable ../build/bin/xvmec
cd /Users/user/repo/trunk/VMEC2000 && "/Applications/CMake 2.8-8.app/Contents/bin/cmake" -E cmake_link_script CMakeFiles/xvmec.dir/link.txt --verbose=1
/usr/local/bin/gfortran -framework Accelerate -cpp -D DARWIN -D NETCDF -I /Users/user/NetCDF/include -O3 -ftree-vectorize -m64 -march=native -fomit-frame-pointer -falign-functions -mfpmath=sse CMakeFiles/xvmec.dir/Sources/General/vmec_main.f.o -o ../build/bin/xvmec ../build/lib/libvmec.a ../build/lib/libstell.a /Users/user/NetCDF/lib/libnetcdf.dylib /Users/user/NetCDF/lib/libnetcdff.dylib
"/Applications/CMake 2.8-8.app/Contents/bin/cmake" -E cmake_progress_report /Users/user/repo/trunk/CMakeFiles 100
[100%] Built target xvmec
The link line looks like it is linking all the same stuff in the correct order so I don't understand why this is failing on Linux.
Turns out I had the wrong file listed as containing the main method. It seems that later versions of gfortran can link 'MAIN__' from a inside a library while gfortran-4.4 cannot.