Building RabbitMQ-C on Windows using MinGW - c

Pretty much what the title says. I have been trying to build RabbitMQ under Windows using MinGW with no success. Judging by the amount of people I see asking questions about how to use it, I suspect I am making a silly mistake, but I don't know what it is. I'm on Win7-64 and I'm extracting the repo, creating a build directory in it, and running
cmake -G "MinGW Makefiles" ..
which seems to work, and then
cmake --build .
which throws a bunch of function re declaration errors. Does anybody know what I'm botching here?
Just for good measure, a small sampling of the errors:
Linking C shared library librabbitmq.1.dll
CMakeFiles\rabbitmq.dir/objects.a(amqp_api.c.obj):amqp_api.c:(.rdata+0x3c): mult
iple definition of `amqp_empty_array'
CMakeFiles\rabbitmq.dir/objects.a(amqp_framing.c.obj):amqp_framing.c:(.bss+0x0):
first defined here
CMakeFiles\rabbitmq.dir/objects.a(amqp_api.c.obj):amqp_api.c:(.rdata+0x44): mult
iple definition of `amqp_empty_table'
CMakeFiles\rabbitmq.dir/objects.a(amqp_framing.c.obj):amqp_framing.c:(.bss+0x8):
first defined here
CMakeFiles\rabbitmq.dir/objects.a(amqp_api.c.obj):amqp_api.c:(.rdata+0x4c): mult
iple definition of `amqp_empty_bytes'
CMakeFiles\rabbitmq.dir/objects.a(amqp_framing.c.obj):amqp_framing.c:(.bss+0x10)
: first defined here
CMakeFiles\rabbitmq.dir/objects.a(amqp_connection.c.obj):amqp_connection.c:(.bss
+0x0): multiple definition of `amqp_empty_array'
CMakeFiles\rabbitmq.dir/objects.a(amqp_framing.c.obj):amqp_framing.c:(.bss+0x0):
first defined here
CMakeFiles\rabbitmq.dir/objects.a(amqp_connection.c.obj):amqp_connection.c:(.bss
+0x8): multiple definition of `amqp_empty_table'
CMakeFiles\rlibrabbitmq\CMakeFiles\rabbitmq.dir\build.make:271: recipe for targe
t 'librabbitmq/librabbitmq.1.dll' failed
EDIT:
After some time, I have determined that the problem is that the pre-processor directives have some errors in the way they are written. I'm not going to close this for now, and if I ever get the time to fix the whole thing, I will come back here and leave an answer with a solution.

I've been analyzing macros defined in amqp.h file and I've added the extern modifier to the AMQP_PUBLIC_VARIABLE macro when build a non static library.
78 #elif defined(_WIN32) && defined(__MINGW32__)
79 # if defined(AMQP_BUILD) && !defined(AMQP_STATIC)
80 # define AMQP_PUBLIC_FUNCTION __declspec(dllexport)
81 # define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern
Another thing was, that I've had to modify the WINVER macro on file '/MinGW/include/windef.h' inside MinGW environment to fit with new windows versions.
11 #ifndef WINVER
12 #define WINVER 0x0501
After that, I've built the librabbitmq.1.dll library without problems using cmake -G "MinGW Makefiles" .. && cmake --build . commands

Related

stdint.h include_next'd from stdint.h not found

I have been putting together a m68k cross compile "environment/toolchain" of sorts for some upcoming projects I have planned, and I'm having an issue when using it on macOS (my native environment) specifically.
If I follow my own instructions to install on Linux (https://github.com/tomstorey/m68k_bare_metal/blob/master/INSTALL-Debian-Ubuntu.md), then in my code I am able to use types such as uint8_t etc through #include <stdint.h>.
But if I install on macOS and attempt to do the same thing I am greeted with this error:
In file included from main.c:1:
/Users/tstorey/m68k/m68k-unknown-elf/lib/gcc/m68k-unknown-elf/9.3.0/include/stdint.h:9:16: fatal error: stdint.h: No such file or directory
9 | # include_next <stdint.h>
| ^~~~~~~~~~
compilation terminated.
make: *** [main.o] Error 1
I've done a little searching around, but I'm not having much luck finding an answer, perhaps because I don't really know what to search for other than "stdint.h not found".
One topic I did find suggested that include_next shouldnt really be used, but that same person wouldnt recommended modifying the original stdint.h file to work around it. Presumably since in that case it is including <stdint.h> then this file should be located somewhere "system wise", and gcc should know where to look to find it? But presumably that location doesnt exist.
In the same directory where the the stdint.h file I am trying to include is located there is a stdint-gcc.h file which, if I include this in my code, it will compile fine, no worries.
The original stdint.h file does seem to attempt to include this file, but only if __STDC_HOSTED__ is not defined:
$ cat stdint.h
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
Sorry if this post is a bit wofty, but I am not experienced enough with gcc etc to really be able to work this out and I'm still learning a lot about setting all of this up, so I'm wondering if anyone knows what I have missed.
Thanks
When your particular version of gcc has been built, it was apparently not built for a hosted environment (i.e. full availability of a standard C library, for example newlib). When this is the case, you cannot expect standard library support and are on your own.
You probably want to re-build gcc with newlib support.

autoconf configure results in C std lib header related compile errors

I am attempting to build a project that comes with an automake/autoconf build system. This is a well-used project, so I'm skeptical about a problem with the configure scripts, makefiles, or code as I received them. It is likely some kind of environment, path, flag, etc problem - something on my end with simply running the right commands with the right parameters.
The configuration step seems to complete in a satisfactory way. When I run make, I'm shown a set of errors primarily of these types:
error: ‘TRUE’ undeclared here (not in a function)
error: ‘struct work’ has no member named ‘version’
error: expected ‘)’ before ‘PRIu64’
Let's focus on the last one, which I have spent time researching - and I suspect all the errors are related to missing definitions. Apparently the print-friendly extended definitions from the C standard library header file inttypes.h is not being found. However, in the configure step everything is claimed to be in order:
configure:4930: checking for inttypes.h
configure:4930: /usr/bin/x86_64-linux-gnu-gcc -c -g -O2 conftest.c >&5
configure:4930: $? = 0
configure:4930: result: yes
All the INTTYPES flags are set correctly if I look in confdefs.h, config.h, config.log Output Variables, etc:
HAVE_INTTYPES_H='1'
#define HAVE_INTTYPES_H 1
The problem is the same whether doing a native build, or cross-compiling (for arm-linux-gnueabihf, aka armhf).
The source .c file in question does have config.h included as you'd expect, which by my understanding via the m4 macros mechanic should be adding an
#include <inttypes.h>
line. Yes, as you may be inclined to ask, if I enter this line myself into the .c file it appears to work and the PRIu64 errors go away.
I'm left with wondering how to debug this type of problem - essentially, everything I am aware of tells me I've done the configure properly, but I'm left with a bogus make process. Aside from trying every ./configure tweak and trick I can find, I've started looking at the auto-generated Makefile.in itself, but nothing so far. Also looking into how I can get the C pre-processor to tell me which header files it's actually inserting.
EDIT: I've confirmed that the -DHAVE_CONFIG_H mechanic looks good through configure, config.log, Makefile, etc.
autoconf does not automatically produce #include directives. You need to do that on your own based on the HAVE_* macros. So you'll have to add something like this:
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
If these lines show up in confdefs.h, a temporary header file used by configure scripts, this does excuse your application from performing these #includes. If configure writes them to confdefs.h, this is solely for the benefit of other configure tests, and not for application use.
First, run make -n for the target that failed. This is probably some .o file; you may need some tweaking to get its path correctly.
Now you have the command used to compile your file. If you don't find the problem by meditating on this command, try to run it, adding the -E to force preprocessor output text instead of invoking the compiler.
Note that now the .o file will be text, and you must rebuild it without -E later.
You may find some preprocessor flags useful to get more details: -dM or -dD, or others.

Compiling a Linux program under Mac OS X

I am trying to use make under Mac OS X (El Capitan) to compile a program which I know to work under Linux. The program makes use of USB libraries. I had to modify the config.mk file for these libraries to be found, but now I end up with errors in the compilation (undeclared identifiers).
Link to source: https://github.com/pali/0xFFFF
It requires usb.h, which seems to be part of usblib-compat. I installed the latter by brew install usblib-compat. But still usb.h couldn't be seen, although I knew where it was: specifically, symbolic link to usb.h and to the library may be found under /usr/local/include and under /usr/local/lib, respectively.
After many trials, I progressed somehow. Namely, the file config.mk is clearly read during the make'ing process, although I have to admit that it is not clear to me how this is done; anyway, I noticed two lines commented:
CPPFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib -Wl,-R/usr/local/lib
(for the sake of precision, in the original config.mk the local dir was replaced by a pkg dir. I replaced it in these lines.)
I uncommented them and now something happens: the usb.h is found. I think the first of these variable definitions tells the compiler where to look tor header files, and the second tells the linker where to look for libraries - but again it is not completely clear to me.
In any case, I have still problems. Namely, the make'ing process outputs two warnings and an error, and then stops:
usb-device.c:90:57: warning: unused parameter 'udev' [-Wunused-parameter]
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
^
usb-device.c:90:67: warning: unused parameter 'interface' [-Wunused-parameter]
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
usb-device.c:324:13: error: use of undeclared identifier 'RTLD_DEFAULT' if ( dlsym(RTLD_DEFAULT, "libusb_init") )
Seems this program is difficult to port from Linux to Mac, although I think it should be portable. If anyone has any idea about what to do (apart from running a Linux distribution...), it would be much appreciated.
EDIT
dlfcn.h has the following:
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define RTLD_NOLOAD 0x10
#define RTLD_NODELETE 0x80
#define RTLD_FIRST 0x100 /* Mac OS X 10.5 and later */
/*
* Special handle arguments for dlsym().
*/
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
#define RTLD_SELF ((void *) -3) /* Search this and subsequent objects (Mac OS X 10.5 and later) */
#endif /* not POSIX */
Ok, finally I have been successful. I think it be worth publishing my solution - maybe others could find it useful.
So, the first point is: if I run make in the program's main folder, usb.h is not found. Then, we have to install the corresponding library.
There are two possibilities for this to be done. The first and more obvious would be to install, through home brew, libusb-1.0 and libusb-compat (the latter provides a compatibility interface for programs that use libusb-0.1, which is the first version of libusb, and is not compatible with libusb-1.0. usb.h is included in libusb-compat):
brew install libusb
brew install libusb-compat
However, this leads to other problems, as reported in the other answer. I had worked around them, but eventually found out that my program got angry when using libusb-compat (if I understand correctly, interfacing the usb port through two layers of libraries is too slow for a flasher).
So, the other possibility: installing the actual libusb-0.1. This is not available through home brew. It is however available through ports, with the name of libusb-legacy. So, I had to install ports, install the X-code command line utilities (which required first going to Apples' website to accept their legal things...) and run
sudo port install libusb-legacy
Ok, now calling make would not do the trick since the compiler is not able to find the library yet. For that, I had to edit the config.mk file which is included in the main directory of the program, uncommenting the last two lines, and editing them somewhat in order to point to the directory where libusb-legacy is stored:
CPPFLAGS += -I/opt/local/include/libusb-legacy -D_DARWIN_C_SOURCE
LDFLAGS += -L/opt/local/lib/libusb-legacy
(the -D_DARWIN_C_SOURCE defines the environmental variable required for other variables to be defined by the libraries. In the Makefile in the src directory, in fact, _POSIX_C_SOURCE is defined.)
Do you think all this did the job? No. In fact at this point I ended up with another error: the linker not being able to find some library called -lusb. I don't know why this syntax, but after some thought I realised that -lusb is somewhat a short for libusb. And the libusb I am using is actually called libusb-legacy... So I went into the Makefile in the src directory, where -lusb is introduced, and changed -lusb to -lusb-compat. Tah-dah! Compiled. A few warnings about non-used variables and a comparison between two different types of integers, but nothing more. And the program runs - after a few trials, I have been able to reflash my bricked phone, which now is alive again! Very happy!!! :)
Looking at the dlfcn.h source code, it seems that the identifier is defined only if _POSIX_C_SOURCE is not defined, or _DARWIN_C_SOURCE is defined. Thus I'd just add #define _DARWIN_C_SOURCE;
Or you could add the corresponding -D switch in the config.mk:
CPPFLAGS += -I/usr/local/include -D_DARWIN_C_SOURCE

CLion fails to index C preprocessor macros when -std=gnuXX is set (Linux Kernel Headers)

I am trying to write a Linux kernel module with CLion. This is the cmake file:
cmake_minimum_required(VERSION 3.5)
project(labs)
set(KERNEL_HEADERS
/home/alex/Developer/linux/include
/home/alex/Developer/linux/arch/x86/include
/home/alex/Developer/linux/arch/x86/include/generated
/home/alex/Developer/linux/include/uapi
/home/alex/Developer/linux/include/generated/uapi
/home/alex/Developer/linux/arch/x86/include/uapi
/home/alex/Developer/linux/arch/x86/include/generated/uapi
)
set(MY_MODULE_SOURCES
chapter_03/lab_01/hello.c
)
add_definitions(-imacros /home/alex/Developer/linux/include/linux/kconfig.h)
add_definitions(-D__KERNEL__)
add_definitions(-DMODULE)
add_definitions(-std=gnu89)
include_directories(${KERNEL_HEADERS})
add_custom_target(labs COMMAND $(MAKE) -C ${labs_SOURCE_DIR}
PWD=${labs_SOURCE_DIR})
add_library(dummylib ${MY_MODULE_SOURCES})
The actual building of the kernel module is done with the externally called makefile using "add_custom_target". The "dummylib" is only there so that CLion actually starts to parse the header files and gives me auto completion. With my supplied definitions it does even compile the "dummylib" successfully (look at the screenshot). It is no kernel module though, but that does not matter ;)
My problem is the error you see in the screenshot. Somehow it says that it can't resolve all the macros defined in the kernel headers. Functions, structs and plain defines ( "MODULE_SIG_STRING ") do work (as you see). I do not understand why the editor says it cannot resolve the macro but can still build it. What is more strange is that I can even jump to the declaration using STRG+B of the marked macros. Clearly something is going wrong. The macros are really defined within linux/module.h.
Update
When I set -std=c89 instead of -std=gnu89 the editor recognizes the macros but the "dummylib" of course fails to build since the kernel needs the gnu extensions. I guess this is a bug in CLion. I posted it at the Jetbrains Bugtracker: https://youtrack.jetbrains.com/issue/CPP-6875

Creating a DLL in GCC or Cygwin?

I need help to compile a script ("iterator.c") into a DLL. I can't use VS2010 since it does not support the features added to C in the C99 standard (I'm using "complex.h" but VB doesn't support it).
I've been looking for a substitute but all I've found is GCC which I don't know how to install/use (really, I've spent like half an hour reading through the documentation and I don't even understand how am I supposed to install it), and Cygwin, which I've already installed but I don't know how to use either. Also, I've installed MinGW but I think it's the same as Cygwin more or less, and I still don't know how to make a DLL.
It's not like I've been all lazy and haven't even tried it, it's just that these compilers aren't like nothing I've ever used before (mostly Python IDLE and Visual Studio, which make things pretty easy for you). I'm kind of lost.
Could someone give me some advice on how to use this tools to make a DLL that I can access from another script? It is really important.
Thank you in advance.
You must place __declspec(dllexport) in front of the method you wish to export such as, you could #define this to max it easier
EXPORT_DLL void hello() { ... }
To compile the dll use
gcc -c -mno-cygwin mydll.c
gcc -shared -o mydll.dll mydll.o -Wl,--out-implib,libmylib.dll.a
then to attach
gcc -o myexe.exe test.o mydll.dll
EDIT: Forgot the most important piece, you need to make a mydll.h file to include your method definition so the compiler knows to reserve a spot for the linker to fill in later on. It's as simple as
#ifndef MYDLL_H
#define MYDLL_H
extern "C" __declspec(dllexport)
#define EXPORT_DLL __declspec(dllexport)
EXPORT_DLL void hello();
#endif

Resources