libtool and Windows DLLs - windows

I have an difficult relationship with the GNU autotools, especially libtool. But because they kick ass when it comes to portability and cross compilation I started using them again.
Unfortunately I can't get libtool to build proper windows DLLs. Yet with vanilla make gcc
will happily build the DLL for me.
For example:
LIBEXT = .dll
pkzo$(LIBEXT): $(patsubst %.cpp, %.o, $(pkzo_SOURCES)) resources.o
$(CXX) -shared -fPIC $(CXXFLAGS) $^ $(LDFLAGS) -Wl,--out-implib=libpkzo.lib -o $#
Will haily build a DLL and import library. (Even without any annoying decelspec).
Yet if I use libtool like so:
lib_LTLIBRARIES = libpkzo.la
libpkzo_la_CXXFALGS = ...
libpkzo_la_LDADD = ...
libpkzo_la_SOURCES = ...
Libtool comes complaining:
*** Warning: linker path does not have real file for library -lSDL2main.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libSDL2main and none of the candidates passed a file format test
*** using a file magic. Last file checked: /usr/local/lib/libSDL2main.a
*** Since this library must not contain undefined symbols,
*** because either the platform does not support them or
*** it was explicitly requested with -no-undefined,
*** libtool will only create a static version of it.
Well guess what libSDL2main.a is a static library and has no DLL.
It there a way to build a DLL with automake not using libtool or telling libtool to stop making a fuss about nothing?
PS: Before anyone mentions it, I am configuring libtool with LT_INIT([shared static win32-dll])

For the first problem, make sure you have a shared version of the SDL library installed.
If you absolutely must link your DLL to static libs, you can trick libtool into doing it by editing the libtool script. E.g., if you want all of the dependent libs statically linked to your DLL, you can do that by putting this at the end of your configure.ac:
sed -i '/^whole_archive_flag_spec=/s/"$/ \\${wl}-static"/' libtool
Now, this is a gross hack and relies on the particular way that libtool builds command lines right now, so there's no guarantee that it will continue to work---but it does work with libtool 2.4.2. Since you have just one library which you want statically linked, you could achieve that by applying sed a bit differently. Probably you'll want
sed -i '/^whole_archive_flag_spec=/s/"$/ \\${wl}-static \\${wl}-lSDL2main \\${wl}-shared"/' libtool
in order to keep shared linking with whatever other shared libs you have, and then you'll need to take -lSDL2main out of wherever else you have it. This is gimpy, but the thing you're trying to do is also gimpy and libtool isn't made for this.
For the second problem, add -no-undefined to libpkzo_la_LDFLAGS.

Related

ld: building for macOS-x86_64 but attempting to link with file built for macOS-x86_64

I have this strange issue where creating / using a static library works in my Ubuntu VM but not on macOS:
ld: warning: ignoring file ./dist/libXXXX.a, building for macOS-x86_64 but attempting to link with file built for macOS-x86_64
Command to create the static library is:
ar rcs libtest.a obj1.o obj2.o ...
Compiler invocation:
gcc -g -Wall -Wextra main.c -L./dist -lXXXX -o main
Searching on google didn't yield any usable results except for this (maybe) related question on SO:
Possible related question
I realize this is an old post and you found your fix, but let me post this here for anyone else who runs into this problem for whom these answers don't provide a solution.
You might be using two different toolchains unknowingly, one from Apple (installed via Xcode) and one from GNU (installed via Home-brew or MacPorts). If you type ranlib --version and see version info showing that ranlib is GNU, this is likely the case.
Make sure that /usr/bin comes in your $PATH before /usr/local/bin and /opt/local/bin. When you run which -a ranlib, the first result in the list should be /usr/bin/ranlib. Same for which -a ar-- the first result should be /usr/bin/ar. If it is not so, you need to fix your $PATH.
Once you fix your path and clean your project, try building again and things should work.
The issue was solved when I directly put those object files rather than gathering them into a static library, i.e.,
gcc -g -Wall -Wextra main.c obj1.o obj2.o -o main
After that, I got many warnings like ld: warning: object file (obj1.o) was built for newer macOS version (11.0) than being linked (10.14), but it is a warning, and the object is linked, so the problem is solved.
The root cause is that some library passes -mmacosx-version-min=10.14 to gcc, so the object file is built for 10.14, but my macos is now 11.0.
If you want to make things work, try directly using object files rather than creating a static library.
If you want to resolve all the warnings, find ``-mmacosx-version-min` and comment it.
After looking at my script that automatically creates the static library I've found the culprit:
For some reason my tool created object files for header files (resulting in files like header.h.o).
Removing those fixed the issue.

mingw32-make tries to create subfolder .lib an illegal name

I am trying to compile a project that required freetype library so I was figuring out how to install freetype to mingw32 and the more safer way is to compile it.
Anyway the problem was compiling freetype-2.4.11
I went into bash provided in msys
I did ./configure within freetype's main dir and everything looks fine
next I did mingw32-make which created the problem
libtool: compile: gcc -pedantic -ansi -Ig:/Downloads/freetype-2.4.11/objs -I./b
uilds/unix -Ig:/Downloads/freetype-2.4.11/include -c -Wall -g -O2 "-DFT_CONFIG_C
ONFIG_H=<ftconfig.h>" -DFT2_BUILD_LIBRARY "-DFT_CONFIG_MODULES_H=<ftmodule.h>" g
:/Downloads/freetype-2.4.11/src/base/ftsystem.c -DDLL_EXPORT -DPIC -o g:/Downlo
ads/freetype-2.4.11/objs/.libs/ftsystem.o
Assembler messages:
Fatal error: can't create g:/Downloads/freetype-2.4.11/objs/.libs/ftsystem.o: No
such file or directory
g:/Downloads/freetype-2.4.11/builds/freetype.mk:198: recipe for target 'g:/Downl
oads/freetype-2.4.11/objs/ftsystem.lo' failed
mingw32-make[4]: *** [g:/Downloads/freetype-2.4.11/objs/ftsystem.lo] Error 1
g:/Downloads/freetype-2.4.11/objs/.libs/ftsystem.o seemed like it is trying to use a directory that is illegal in windows.
Thanks in advance
Try to use make instead (i.e. the one from MSYS distribution), and avoid using mingw32-make (from MinGW distribution) in the future to save yourself time and nerves. Extract from MinGW Wiki:
What's the difference between make and mingw32-make?
The "native" (i.e.: MSVCRT dependent) port of make is lacking in some functionality and has modified functionality due to the lack of POSIX on Win32. There also exists a version of make in the MSYS distribution that is dependent on the MSYS runtime. This port operates more as make was intended to operate and gives less headaches during execution. Based on this, the MinGW developers/maintainers/packagers decided it would be best to rename the native version so that both the "native" version and the MSYS version could be present at the same time without file name collision.

checking for suffix of object files... configure: error: cannot compute suffix of object files: cannot compile

While building ARM toolchain , I got the following error
checking for suffix of object files... configure: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details.
make[1]: *** [configure-target-libgcc] Error 1
make[1]: Leaving directory `<path>/gcc-4.3.2-arm-elf'
make: *** [all] Error 2
what might be the problem?
Did you read http://gcc.gnu.org/wiki/FAQ#configure_suffix ?
Have you installed GMP, MPFR and MPC? Are they in your library search path?
See http://gcc.gnu.org/wiki/InstallingGCC and make sure you've followed the basic instructions. By far the simplest way to build GCC (including as a cross compiler) is to follow these instructions:
Alternatively, after extracting the GCC source archive, simply run the ./contrib/download_prerequisites script in the GCC source directory. That will download the support libraries and create symlinks, causing them to be built automatically as part of the GCC build process.
"*Building GCC is not trivial, but is not difficult if you follow the instructions carefully.
Many people rush into trying to build it without reading the installation docs properly and make one or more of these common mistakes:
1) do not run ./configure from gcc src dir (this is not supported) => you need to run configure from outside the gcc source directory
2) Note: if GCC links dynamically to the prerequisite libs (GMP/MPFR/MPC) then the shared libraries must be in the dynamic linker's path (LD_LIBRARY_PATH), both when building gcc and when using the installed compiler.*"
Simple example (without dynamic link to GMP/MPFR/MPC):
tar xzf gcc-4.8.0.tar.gz
cd gcc-4.8.0
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
$PWD/../gcc-4.8.0/configure --prefix=/opt/gcc-4.8.0
make
make install
Sources:
Advogato Doc -
GNU Doc
export LD_LIBRARY_PATH=/path/for/libraries:$LD_LIBRARY_PATH
path/for/libraries is where the GMP MPFR and MPC libraries are present.
I was compiling GCC on ubuntu 12.04 and these linraries present in the path /usr/local/lib

configure.in: AM_DISABLE_SHARED doesn't change my Makefile

I'm extremely new to using Makefiles and autoconf. I'm using the Camellia image library and trying to statically link my code against their libraries. When I run "make" on the Camellia image library, I get libCamellia.a, .so, .la, and .so.0.0.0 files inside my /usr/local/lib directory. This is the command I use to compile my code with their libraries:
gcc -L/usr/local/lib -lCamellia -o myprogram myprogram.c
This works fine, but when I try to statically link, this is what I get:
gcc -static -L/usr/local/lib -lCamellia -o myprogram myprogram.c
/tmp/cck0pw70.o: In function `main':
myprogram.c:(.text+0x23): undefined reference to `camLoadPGM'
myprogram.c:(.text+0x55): undefined reference to `camAllocateImage'
myprogram.c:(.text+0x97): undefined reference to `camZoom2x'
myprogram.c:(.text+0x104): undefined reference to `camSavePGM'
collect2: ld returned 1 exit status
I want to statically link because I'm trying to modify the Camellia source code and I want to compare my version against theirs. So after some googling, I tried adding AM_DISABLE_SHARED into the configure.in file. But after running ./configure, I still get the exact same Makefile. After I "make install", I still get the same results above.
What is an easy way to get two versions of my code, one with the original Camellia source code compiled and one with my modified version? I think static libraries should work. There is an easy way to get static libraries working or are there other simple solutions to my problem? I just don't want to re-"make" and re-"make install" everytime I want to compare my version against the original.
Did you re-run autoconf after adding AM_DISABLE_SHARED and before configure, make, make install? You also can just use configure --disable-dynamic to stop it building the shared libraries. Make sure you delete any previously installed ones - make uninstall should do that. I can't see anything else obviously wrong. Try being explicit:
gcc -static -o myprogram myprogram.c /usr/local/lib/libCamellia.a
or break it down into two steps and check the symbols in myprogram.o are what you expect with nm myprogram.o.
I am not skillful with autoconf and I don't know why your attempt to link statically fails, but if linking dynamically works I think using shared libraries would actually solve your problem a little better.
Just make two shared libraries, one with the original Camellia code and one with your modified version. Put them in two different directories, and when you run myprogram you can choose between them either by switching LD_LIBRARY_PATH (or whatever you're using to find libraries) or by keeping a symbolic link in /usr/local/lib and switching it between libraries. The advantage of this over static libraries (apart from the fact that this works) is that you can tinker with your modified code, rebuild the shared library and run without having to rebuild myprogram (as long as you don't modify the signatures).
P.S. An experiment: try removing the shared libraries from /usr/local/lib and rebuilding without the -static flag, just as if you were using the shared libraries. In theory this should cause gcc to use the static libraries instead. The results may give a clue to why the static link is failing.

Building GCC cross compiler (from "Linux" to "Windows")

I want to build "gcc cross-compiler" to compile "c/c++" applications on "Linux" environment but for "Windows" target.
I have made this so far:
Installed the necessary tools and packages for building GCC listed on "Prerequisites for GCC" page.
Downloaded required sources:
"gcc-core-4.4.1", "gcc-g++-4.4.1", "binutils-2.19.1", "w32api-3.13-mingw32", "mingwrt-3.16-mingw32"
Created this directory hierarchy:
"${HOME}/gcc/" - for final cross-compiler
"${HOME}/src/" - for sources
"${HOME}/src/build-binutils/i386-mingw32/" - for building binutils to "i386-mingw32" target
"${HOME}/src/build-gcc/i386-mingw32/" - for building gcc to "i386-mingw32" target
Builded binutils package:
cd "${HOME}/src/build-binutils/i386-mingw32/"
../../binutils-2.19.1/configure --prefix="${HOME}/gcc" --target=i386-mingw32 --disable-nls
make
make install
Copied "w32api" and "mingwrt" headers to the install directory:
cp -R "${HOME}/src/w32api-3.13-mingw32/include" "${HOME}/gcc/i386-mingw32"
cp -R "${HOME}/src/mingwrt-3.16-mingw32/include" "${HOME}/gcc/i386-mingw32"
And now when I am trying to build the "c (only) cross-compiler":
cd "${HOME}/src/build-gcc/i386-mingw32/"
../../gcc-4.4.1/configure --prefix="${HOME}/gcc" --target=i386-mingw32 --enable-languages=c --with-headers="${HOME}/gcc/i386-mingw32/include" --disable-nls
make<br>
it was building something about 4 minutes and then gives me these errors:
${HOME}/gcc/i386-mingw32/bin/ld: dllcrt2.o: No such file: No such file or directory
collect2: ld returned 1 exit status
make[2]: *** [libgcc_s.dll] Error 1
make[2]: Leaving directory `${HOME}/src/build-gcc/i386-mingw32/i386-mingw32/libgcc'
make[1]: *** [all-target-libgcc] Error 2
make[1]: Leaving directory `${HOME}/src/build-gcc/i386-mingw32'
make: *** [all] Error 2
From that error message I really don't know what to do now :-((( .
Does anybody know where is the problem?
Thanks.
That's actually OK: the way things go, you need to
build binutils
install headers
build the a partial C compiler: enough to create object files, but not enough to link
build the win32api and mingw runtime (which includes your missing dllcrt2.o)
build a complete C compiler (and other front-ends, such as C++, Fortran, Ada, whatever, if you want them)
You have successful performed step 3 above; it fails building libgcc (which is a GCC support library), but that means the C compiler core is functionnal (although it won't be able to link, it can still create valid object files). You can check that by looking at the gcc/xgcc file in your GCC build directory.
So, you need to go to the next step, not worrying about your current failure.
(To actuall install the partial C compiler, you should run make with the -k option, to have it do it best, even in the face of errors. For example, use make -k install.)
There are precompiled cross-compilers of MinGW-w64 available.
This allows to compile native 32- and 64-bit Windows binaries from Linux, a two minute tutorial is available at http://www.blogcompiler.com/2010/07/11/compile-for-windows-on-linux/
Just in case you don't want to spend a lot of time trying to build it yourself.
I grepped through the MinGW sources, and found that dllcrt2.o is something built off the mingwrt package. I assume you have to compile and install that, not just copy the headers?

Resources