Clang block in Linux? - c

Clang has a very cool extension named block bringing true lambda function mechanism to C. Compared to block, gcc's nested functions are quite limited. However, trying to compile a trivial program c.c:
#include <stdio.h>
int main() {
void (^hello)(void) = ^(void) {
printf("Hello, block!\n");
};
hello();
return 0;
}
with clang -fblocks c.c, I got
/usr/bin/ld.gold: /tmp/cc-NZ7tqa.o: in function __block_literal_global:c.c(.rodata+0x10): error: undefined reference to '_NSConcreteGlobalBlock'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
seems I should use clang -fblocks c.c -lBlocksRuntime, but then I got
/usr/bin/ld.gold: error: cannot find -lBlocksRuntime
(the rest is the same as above)
Any hints?

On Ubuntu Linux:
sudo apt-get install llvm
sudo apt-get install clang
sudo apt-get install libblocksruntime-dev
test.c:
#include <stdio.h>
int main() {
void (^hello)(void) = ^(void) {
printf("Hello, block!\n");
};
hello();
return 0;
}
compile:
clang test.c -fblocks -lBlocksRuntime -o test
./test
Hello, block!
works fine.

Technical background information:
Blocks themselves are language feature but they also require some runtime support. So either the compiler has to provide a runtime library and statically link it into the build product or the system must provide such a runtime library the build product can be linked against.
In case of macOS, the blocks runtime is part of libSystem and as all executable and dynamic libraries on macOS are linked against libSystem, they all do have blocks support.
On a Linux system, such runtime support would typically added to the libC library (glibc in most cases) if it was considered a core feature of the system or the language, yet as gcc currently has no support for blocks at all and its unknown if blocks will ever become an official C feature, Linux systems don't ship runtime support for blocks by default.
clang itself does offer a target-indepedent blocks runtime as part of the compiler runtime library, yet it is optional and many Linux systems don't seem to include in their clang install package. That's why the project blocksruntime has been created, that builds the clang blocks runtime support as an own library, which you can statically link into your projects or dynamically install onto your systems. The source code is available on GitHub.
Depending on your Linux distribution, a ready-to-use installer package may exist. Note that blocksruntime cannot just be compiled for Linux, it can also be compiled for FreeBSD or Windows (MinGW/Mingw-w64) or even for Mac if you don't want to use the runtime that Apple provides. Theoretically it should be portable to any platform that clang natively supports.

Judging from Which libraries do you need to link against for a clang program using blocks it appears there is no easy way of fixing this, at least as of early 2010.

Related

clang does not generate gdb symbols on windows [duplicate]

When using clang v8.0.0 on Windows (from llvm prebuilt binaries) with -g or -gline-tables-only source map tables are not being picked up by gdb or lldb debuggers.
Upon including -g flag file grows in size (which is to be expected) yet neither gdb nor lldb pickes the source up
When compiled with gcc though (with -g flag) source files are detected by debugger.
I have tried running the same command (clang -g <codefile>) on macOS High Sierra (clang -v says it is Apple LLVM version 10.0.0 (clang-1000/10.44.4)) where there source files are being picked up by lldb. So I guessed it is localized to my windows instance or llvm for windows build.
P.S. output of clang -v on windows:
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
On Windows, Clang is not self-sufficient (at least not the official binaries). You need to have either GCC or MSVC installed for it to function.
As Target: x86_64-pc-windows-msvc indicates, by default your Clang is operating in some kind of MSVC-compatible mode. From what I gathered, it means using the standard library and other libraries provided by your MSVC installation, and presumably generating debug info in some MSVC-specific format.
Add --target=x86_64-w64-windows-gnu to build in GCC-compatible mode. (If you're building for 32 bits rather than 64, replace x86_64 with i686). This will make Clang use headers & libraries provided by your GCC installation, and debug info should be generated in a GCC-compatible way. I'm able to debug resulting binaries with MSYS2's GDB (and that's also where my GCC installation comes from).
If you only have GCC installed and not MSVC, you still must use this flag.
How do I know this is the right --target? This is what MSYS2's Clang uses, and I assume they know what they're doing. If you don't want to type this flag every time, you can replace the official Clang with MSYS2's one, but I'm not sure if it's the best idea.
(I think they used to provide some patches to increase compatibility with MinGW, but now the official binaries work equally well, except for the need to specify the target. Also, last time I checked their binary distribution was several GB larger, due to their inability to get dynamic linking to work. Also some of the versions they provided were prone to crashing. All those problems come from them building their Clang with MinGW, which Clang doesn't seem to support very well out of the box. In their defence, they're actively maintaining their distribution, and I think they even ship libc++ for Windows, which the official distribution doesn't do.)

memmem() in Mingw-w64 gcc

I'm trying to build a C program with Windows gcc using Mingw-w64 installation (gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0).
I get undefined reference to `memmem' error. Isn't memmem() a standard glibc function that should be available in all gcc versions?
As this post explains
"MinGW does not build against glibc, it builds against msvcrt. As
such, it uses libmsvcrtXX.a instead." "gcc and glibc are two separate
products."
So, yep, no memmem on Windows and here's the implementation.

How to get linker to report where it is linking to for a given function

I have an issue trying to cross build win32 and win64 exes on a linux host.
I am using the mingw cross build toolchains
my .c file includes time.h in order to use clock_gettime() in main()
now this is a POSIX thing so no guarantee it is windows portable
however, on another laptop with a similar (but obviously not identical) setup it does compile and link no problem
on this laptop (a new one I am migrating to) I get a linker error:
undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
what I would like to be able to do is somehow have the linker on the other machine tell me where it is finding the .dll with clock_gettime() in it
In order for me to see whether the similar .dll is present on the new laptop and whether the clock_gettime() symbol is avaiable in it
Is it possible to get the linker to report this info, some sort of verbose mode perhaps. I've gone down the GIYF route but drawn a blank thus far.
Compile with -lrt which is needed for for glibc version < 2.17.
What probably happens on the other laptop is that it has a recent version of glibc >=2.17 in which the the clock_gettime() is part of the libc. But older in glibcs, it's a separate library. Hence, you needed to link it yourself.
To use clock_gettime() as defined in <time.h> when cross building for windows using mingw toolchain on a linux host you must link to pthread not rt
for example:
source code, example.c, looks like this:
#include <time.h>
...
struct timespec t1;
...
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
native build looks like this:
gcc example.o -lrt -o example
win32 cross-build looks like this:
i686-w64-mingw32-gcc -I/usr/local/i686-w64-mingw32/include example.o -L/usr/local/i686-w64-mingw32/bin -lpthread -lws2_32 -o example.exe
Unfortunately, I am none the wiser on how to get the linker to tell me in which library it has found a function that it has successfully linked to
i.e. if I could have somehow got the linker to inform me that it had found clock_gettime() in libpthread on my other machine that was successfully linking, I could have saved a lot of messing about fixing the link error issue on this machine.

Compiling C programs with GLUT headers for Windows (in Linux)

I can currently compile C programs with stdio.h and such like for Windows with the command i586-mingw32msvc-gcc, however I cannot do this for a GLUT program. When compiling it for Linux I use:
gcc main.c -lglut -lGLU
(I know, bad practice as it comes out with a.out)
Yet I am unsure of how I could do it for Windows using mingw32. When I run
i586-mingw32msvc -lglut -lGLU
it returns:
test.c:3:21: error: GL/glut.h: No such file or directory
The included header files are:
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
And I am unsure of how to make it able to compile. Any ideas?
Essentially that error tells you, that your MinGW GCC does not find the required headers. That is, because you're cross-compiling to another OS, and header files may contain OS specific things. Unfortunately OpenGL is one of those. So you have to install the required libraries in a Windows version as well.
However you should not just download some precompiled binaries from the web; you need libraries matching MinGW. You can of course install MinGW built libraries, that will work. However I suggest something different: Crosscompile and locally install all the libraries you require in your MinGW environment yourself. You do this, by passing the right compiler, linker and prefixes into the build configuration of each library. For example for autoconf based configure (on my system)
CC=i686-mingw32-gcc CXX=i686-mingw32-g++ ./configure --prefix=/usr/i686-mingw
make ; make install will then build and install the libraries and their headers in the MinGW environment, where you can use them as any other regular installed library.

How can I mimic the GNU/linux C development environment on OSX Lion?

I just tried to write a simple C program on OSX Lion
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
Compiling with gcc
$ gcc hello.c
test.c:1:19: error: stdio.h: No such file or directory
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
Ok...fine
$ gcc -I /Developer/SDKs/MacOSX10.6.sdk/usr/include
ld: library not found for -lcrt1.10.6.o
collect2: ld returned 1 exit status
What? Let's see...
$ gcc -I /Developer/SDKs/MacOSX10.6.sdk/usr/include -L/Developer/SDKs/MacOSX10.6.sdk/usr/lib test.c
$ ./a.out
hello world
Finally!
That seems like a lot of effort just to get a hello world working, how do I make gcc find libraries and header files in the MacOSX10.6.sdk directory by default like it does on linux? On linux I find ldd and ldconfig quite useful, they don't seem to exist on OSX...is there an equivalent? What other useful tools are there for developing C on OSX?
Yes, I know xcode makes this easier, but suppose I wanted to use vim and the command line to work on an opensource c project.
I can think of three possibilities:
You had 10.6 installed and upgraded to 10.7. You need to install the new version of Xcode (4.1, get it from the app store) to get back the developer tools.
you installed Xcode, did a custom install, and unchecked "UNIX development" or something. Rerun the installer and install the missing parts.
You installed a broken third-party version of gcc. Try which gcc and see what you get.
On OS X 10.7, if you have downloaded Xcode 4.1 from the Mac App Store and then run the installer that it downloads (in /Applications), your first attempt should have worked just fine assuming you have not set some environment variables that are looked at and influence Apple's gcc tool chain. The object file that is produced in this case would be using the default 10.7 ABI (include files and libs). If you want to produce something that would be compatible with OS X 10.6, then you need to tell the tool chain to use the 10.6 SDK ABI, which is what you did in the third attempt. A standalone project typically handles this by setting up a Makefile to automate building. But, unless you are trying to build something on a version of OS X (10.7 here) that will also run on earlier versions of OS X (say 10.6), there is generally no need to use an SDK.

Resources