I have this very simple piece of code that I'm trying to compile. I'm fairly new to GCC from the command line, so please forgive me. I've tried a quite few different things with GCC, but I'm still unable to get it to compile. I do have libusb installed. How can I get this piece of code to compile?
Libusb:
anything:usb mymac$ brew list libusb
/usr/local/Cellar/libusb/1.0.9/include/libusb-1.0/libusb.h
/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.0.dylib
/usr/local/Cellar/libusb/1.0.9/lib/pkgconfig/libusb-1.0.pc
/usr/local/Cellar/libusb/1.0.9/lib/ (2 other files)
anything:usb mymac$
GCC attempts (all failed):
gcc -o xout usbtest.c
gcc -o xout usbtest.c -lusb-1.0
gcc -L/usr/local/Cellar/libusb/1.0.9/lib -o xout usbtest.c -lusb-1.0
Error for all attempts:
usbtest.c:3:10: fatal error: 'libusb.h' file not found
#include <libusb.h>
Code:
#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>
int main(int argc, const char * argv[])
{
libusb_device **devs;
libusb_context *context = NULL;
size_t list;
//size_t i;
int ret;
ret = libusb_init(&context);
if(ret < 0)
{
perror("libusb_init");
exit(1);
}
list = libusb_get_device_list(context, &devs);
printf("There are %zd devices found\n", list);
return 0;
}
So I had a similar issue, for some reason gcc doesnt include /usr/local/lib in its default search path on OS X. The quick fix is to add:
-lusb-1.0
to the gcc commands and it should compile.
You are not telling gcc where to look for the header files. This is done by the -I option on the gcc command line for compiling.
e.g.
gcc -I /usr/local/include -o xout usbtest.c
I think Homebrew does provide a symbolic link frominside the Cellar to /usr/local
Related
I recently moved from Ubuntu 14.04 to Ubuntu 16.04 for working on code. This moved me from GCC 4.8.4/GNU ld 2.24 to GCC 5.3.1/GNU ld 2.26.
I've been writing test cases for code and someone decided to override the default time() function for testing but linking behavior seems to have changed between these two releases. Example code follows:
nothing.c:
#include <stdio.h>
#include <time.h>
void nothing( )
{
printf( "%lld\n", (long long)time( NULL ) );
}
something.c:
#include <stdio.h>
#include <time.h>
extern void nothing( void );
int main( )
{
printf( "%lld\n", (long long)time( NULL ) );
nothing( );
return 0;
}
faketime.c:
#include <time.h>
time_t time( time_t * ptr )
{
return 42;
}
Now, if I compile this code using the following:
gcc -fPIC -c -o nothing.lo nothing.c
gcc -shared -rdynamic -o libnothing.so nothing.lo
gcc -o something something.c faketime.c -Wl,-rpath=. -L. -lnothing
I get two different results on each of the environments upon which I attempt to run the executable.
Ubuntu 14.04 says the answer is "42/42" while Ubuntu 16.04 says the answer is "42/1464287587" (insert your current Unix timestamp).
I'm curious if this is a conscious change or whether I am doing something wrong here? I sort of assume the "new way" is actually more correct as it seems like a loophole for me to override a system call a library expects to make. However, maybe that's normal and maybe now this method of "linker substitution" is broken in the new compiler/linker?
I am compiling some asserts with -arch i386 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -mmacosx-version-min=10.4. Therefore, the assert code doesn't use __assert_rtn but __eprintf instead.
Relevant snippet from assert.h:
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
#define __assert(e, file, line) \
__eprintf ("%s:%u: failed assertion `%s'\n", file, line, e)
#else
/* 8462256: modified __assert_rtn() replaces deprecated __eprintf() */
#define __assert(e, file, line) \
__assert_rtn ((const char *)-1L, file, line, e)
#endif
So far so good, except when linking time arrives, it doesn't find __eprintf. In which library is this defined ?
A way to reproduce getting __eprintf into the assert:
cat <<EOF >/tmp/x.c
#include <assert.h>
#ifdef __clang__
# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
# warning "compiling for 10.4 (not __DARWIN_UNIX03), with __eprintf"
# endif
# endif
#endif
int xxx( int a)
{
assert( a);
return( a);
}
EOF
clang -E -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -o /tmp/x.txt /tmp/x.c
Using above, make a dylib and observe the problem:
clang -c -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -O0 -o /tmp/x.o /tmp/x.c
ld -arch i386 -macosx_version_min 10.4.0 -syslibroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -t -o /tmp/x.dylib -ldylib1.o /tmp/x.o -lSystem -lgcc_s.10.4
These calls are destilled down from what xcodebuild produces.
Thanks for the helpful responses.
The answer turns out to be /Applications/Xcode-7.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.2/lib/darwin/libclang_rt.10.4.a in my particular case.
This is a library that gets added by clang itself behind the scenes (DarwinClang::AddLinkRuntimeLibArgs). Note that this library is only for 10.4 code and seems to be tied to the compiler version.
I don't know by which magic (don't see it in the invocation) the linker decides which compiler version it needs to link for.
The easiest solution is to define ones own __eprintf, instead of messing around with the toolchain:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
__attribute__((visibility("hidden")))
void __eprintf( const char* format, const char* file,
unsigned line, const char *expr)
{
fprintf( stderr, format, file, line, expr);
abort();
}
# endif
#endif
int main( int argc, char *argv[])
{
assert( argc == 2);
return( 0);
}
On a Mac pro I have installed g++
brew install gcc --without-multilib
I have then g++-5 installed in /usr/local/bin
The compiler supports OpenMP and also c++11
The following code compiles and runs as expected:
#include <iostream>
int main(int argc, const char **argv)
{
auto i = 42;
int arr[] = {1,2,3,4,5};
for(int& e : arr)
{
e = e*e;
}
#pragma omp parallel
{
std::cout << "Hello OpenMP!\n";
}
return 0;
}
compiling:
g++-5 -fopenmp -std=c++11 omp_code.cpp -o omp_executable
However,
cmake -DCMAKE_CXX_COMPILER=g++-5 -DCMAKE_C_COMPILER=gcc-5 ..
tells me that Could NOT find OpenMP (missing: OpenMP_CXX_FLAGS)
and The compiler /usr/local/bin/g++-5 has no C++11 support
For OpenMP I use FIND_PACKAGE(OpenMP) and for c++11 I use
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
Any idea how to solve this? A workaround was just to put the c++11 and -fopenmp flags even if the checks fail. That worked fine. However, I would like to have a better solution.
I'm trying to run the following simple example from Xcode4:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
namespace mpi = boost::mpi;
int main(int argc, char* argv[])
{
mpi::environment env(argc, argv);
mpi::communicator world;
std::cout << "I am process " << world.rank() << " of " << world.size()
<< "." << std::endl;
return 0;
}
I've added libboost_mpi and libboost_serialization to Xcode, and compiling using the default LLVM returns :
/usr/local/include/boost/mpi/communicator.hpp:1329:9: error: call to
implicitly-deleted copy constructor of 'boost::mpi::communicator'
: comm(comm), source(source), tag(tag), ia(comm), value(value)
^ ~~~~
However, I can compile and run using
mpic++ -I/usr/local/include main.cpp -L/usr/local/lib
-lboost_mpi -lboost_serialization
Although mpic++ seems to be calling through to LLVM:
$ mpic++
i686-apple-darwin11-llvm-g++-4.2: no input files
Anyways, I tried adding mpic++ as a compiler option in Xcode 4. I can run
$ sudo opensnoop -n Xcode | grep mpicc.xcspec
and see that the spec file is being loaded by Xcode, but I don't see any MPICC option. My spec file is fairly simple:
/**
Xcode Compiler Specification for MPICC
*/
{ Type = Compiler;
Identifier = com.apple.compilers.mpicc;
BasedOn = com.apple.compilers.gcc.4_2;
Name = “MPICC”;
Version = “Default”;
Description = “MPI GNU C/C++ Compiler 4.0″;
ExecPath = “/usr/local/bin/mpicc”;
PrecompStyle = pch;
}
and it's stored in
/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/LLVM GCC 4.2.xcplugin/Contents/Resources/mpicc.xcspec
So this works:
link binary with:
libmpi_cxx.dylib
libmpi.dylib
libboost_mpi.dylib
libboost_serialization.dylib
Change compiler (under build options) to LLVM GCC 4.2 (hinted at by running mpic++ directly, which reports that it's using llvm gcc 4.2 internally)
Under targets, build phases, compile sources, add the compiler option "-lm" to report that you need to link with libm. Credit to #pyCthon for pointing out mpic++ --showme:link which revealed the final library that was allowing it to build successfully from the command line
I'm trying to compile a binary file into a MACH_O object file so that it can be linked it into a dylib. The dylib is written in c/c++.
On linux the following command is used:
ld -r -b binary -o foo.o foo.bin
I have tried various option on OSX but to no avail:
ld -r foo.bin -o foo.o
gives:
ld: warning: -arch not specified
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)
An empty .o file is created
ld -arch x86_64 -r foo.bin -o foo.o
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)
Again and empty .o file is created. Checking the files with nm gives:
nm foo.o
nm: no name list
The binary file is actually, firmware that will be downloaded to an external device.
Thanks for looking
Here's the closest translation to the Linux linker command to perform binary embedding with the OSX linker:
touch stub.c
gcc -o stub.o -c stub.c
ld -r -o foo.o -sectcreate binary foo_bin foo.bin stub.o
foo.bin will be stored in segment binary, section foo_bin (both names are arbitrary but chosen to mimic GNU ld for ELF on Linux) of the foo.o object.
stub is necessary because ld refuses to create just a custom segment/section. You don't need it if you link directly with a real code object.
To get data back from the section, use getsectbyname (struct is defined in mach-o/loader.h):
#include <mach-o/getsect.h>
const struct section_64 *sect = getsectbyname("binary", "foo_bin");
char *buffer = calloc(1, sect->size+1);
memcpy(buffer, sect->addr, sect->size); // whatever
or getsectdata:
#include <mach-o/getsect.h>
size_t size;
char *data = getsectdata("binary", "foo_bin", &size);
char *buffer = calloc(1, size+1);
memcpy(buffer, data, size); // whatever
(I used it to store text data, hence the stringification via calloc zeroing of size+1 plus blob copying)
Warning: Since 10.7, ASLR got stronger and messes badly with getsect* functions, resulting in segfaults. set disable-aslr off in GDB before running to reproduce EXC_BAD_ACCESS (SIGSEGV) in debug conditions. People had to jump through inordinate hoops to find the real address and get this working again.
A simple workaround is to get the offset and size, open the binary and read the data straight from disk. Here is a working example:
// main.c, build with gcc -o main main.c foo.o
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <mach-o/getsect.h>
int main() {
// finding the filename of the running binary is left as an exercise to the reader
char *filename = "main";
const struct section_64 *sect = getsectbyname("binary", "foo_bin");
if (sect == NULL) {
exit(1);
}
char *buffer = calloc(1, sect->size+1);
int fd = open(filename, O_RDONLY);
if (fd < 0) {
exit(1);
}
lseek(fd, sect->offset, SEEK_SET);
if (read(fd, buffer, sect->size) != sect->size) {
close(fd);
exit(1);
}
printf("%s", buffer);
}