How to compile a program for distribution on Mac - macos

I am developing a program on OSX 10.6.4 (Snow Leopard), and I want to be able to run the compiled product on other Intel Macs, some of whom may not have XCode isntalled.
To simplify things, I first wrote a Hello World program.
#include<stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
If I compile it as
gcc -static prog.c
I get the folllowing error:
ld: library not found for -lcrt0.o
I don't know where to find this library. Now, some people have mentioned that I should not compile statically on macs since the system shared libraries should be available everywhere (third party libraries can be manually linked). However, when I try to run this Hello World program on another mac, I get the folowing error:
dyld: unknown required load command 0x80000022
Trace/BPT trap
So, how do you compile a program on mac so that it can be distributed? I am not having architecture issues, as most computers I am interested in are Intel Macs.

Don't use -static. Your executable will run fine on other 10.6.x x86 Macs. If you want to deploy on pre-10.6 Macs then you'll need to use the appropriate SDK but apart from that it should "just work", regardless of whether the developer tools are installed.

It might be worth using XCode to create your executable, using the Command Line program template (basic Unix executables), simply because it will manage a lot of the compiler options for you (including which SDK you are compiling against / which versions you are targeting).
My guess is that a default commmand-line compilation is going to compile against the current system libraries (10.6.4).

Related

MacOS assembly linker throws error while linking

I'm trying to compile and link an assembly file to an executable with NASM and the standard LD linker on my MacBook Air M1. I have no problems with getting the .o file, but if I want to link it with LD, it throws that error:
ld: file not found: elf_i386
Command:
ld -m elf_i386 -s -o hello hello.o
What do I have to change?
Those are options for GNU ld on x86 Linux. (Note the ELF part of the target object-file format, and the i386). MacOS uses the MachO object-file format, not ELF, and apparently their ld takes different options.
Also, MacOS hasn't supported 32-bit x86 for a few versions now, so an M1 mac with an AArch64 CPU definitely can't run 32-bit x86 executables natively.
So get an emulator for a 32-bit Linux environment if you want to follow a tutorial for that environment, or find a tutorial for AArch64 MacOS. Or possibly x86-64 MacOS which should still work transparently thanks to Rosetta, but make sure single-step debugging actually works. That's an essential part of a development environment for learning asm.
Assembly language is not portable at all, you need a tutorial for the OS, CPU-architecture, and mode (32-bit vs. 64-bit) that you're going to built in. Don't waste your time trying to port a tutorial at the same time you're learning the basics it's trying to teach. You'd have to already know both systems to know which parts of the code and build commands need to change.

powerpc compiler on windows gives "c++ compiler not installed on this system error"

I am trying to use msys powerpc-eabispe-gcc compiler on windows to compile a simple helloworld.cpp program, inorder to generate an elf for powerpc architecture, but I am getting "c++ compiler not installed on this system" error. The bin folder of powerpc-eabispe contains all the exe's, I dont understand why then I get this error??
I used MinGW command prompt to run this command: powerpc-eabispe-gcc.exe -o hello hello.cpp
You need to install the toolchain for the architecture you are targeting.
Search for "cctools" / "binutils" / "crosstools" or "ppc cross-compile environment".
You can also take a look at:
Building and Testing gcc/glibc cross toolchains (This will probably work)
Host/Target specific installation notes for GCC (search powerpc in the page)
However, I would encourage you to try this on a linux or on a mac computer. There are far more resources & docs available on the web for cross-compilation on these platforms.

mac ports 32/64 bit error

I'm consistently getting errors across the board related to the following problem, on Mac osx 10.7.4 via a 2011 mac book pro.
these errors are mostly from mathematical related dev libs that compile and run example code without error on various linux machines, while using similar make files
the error i get is usually something on the lines of
ld: symbol(s) not found for architecture x86_64
this also occurs with various compilers and no matter how i compile the lib I link, clang, various versions of gcc even haskell's ghc
some libs that give me errors are
PETSC(which i compiled from source and none of the examples compile
with make test)
GSL(from macports) gives same error
FFTW... and the list goes on
I believe the culprit is that some where along the line something (maybe a compiler) was compiled via macports improperly,
for instance gcc -v states it was compiled Target: i686-apple-darwin11
--build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.11~28/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11
while every other compiler, clang , g++-mp-4.7 exc, says Target: x86_64-apple-darwin11
is there any solution to this problem?
is there a way to recompile everything enforcing 64 bit? Would that fix the above problem?
Mac OS X has its own build toolchain, so this probably is a path issue.
Check
which gcc
and compare the path with any library you know comes from mac ports (probably in /opt/bin).
As a solution, putting the /opt/bin path at the beginning of your $PATH should work out.

seg fault when running arm-elf-gcc compiled code

Using MacPorts i have just installed arm-elf-gcc on to my MacBook Pro. This worked flawlessly and all seems to run fine.
However, after compiling a simple hello world test program in C and C++ and trying to run either on the target board (an ARM9 based board running Debian Linux) they immediately seg fault.
I'm a bit stuck as how to go about debugging this, as the target board has limited tools available and no gdb. I have successfully built and run other code using a Linux hosted cross compiler so it should work.
Any ideas?
Following the suggestion I have built and run gdbserver, I get the following in gdb on the host:
Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
I thought it may be a problem with the standard c libs so I removed any calls and have just an empty main that return 0, it is compiled with -Wall -g hello-arm.cpp -static. As a test I compiled the same source with a Linux hosted cross compiler and it runs and exits fine. The only difference I can see is the that Linux compiled version is over twice the size and the difference in output from the file command:
arm-elf-gcc: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped
arm-*-linux: ELF 32-bit LSB executable, ARM, version 1, statically linked, for GNU/Linux 2.4.18, not stripped
The usual method of debugging in this situation is to run gdbserver on the target board, and connect to it (via ethernet) with gdb running on a host computer.
Alternately, you could try comparing the assembly in a Mac-compiled "Hello World" program and a (working) Linux-compiled one to see what's different.
After digging around for a couple of days I am starting to understand a bit more about embedded compilers. I wasn't really sure of the difference between arm-elf-gcc installed via MacPorts and the arm-unknown-linux toolchain I had installed on my Linux box. I just came across a pdf titled "An introduction to the GNU compiler" which contains the following paragraph:
Important: Using the GNU Compiler to
create your executable is not quite
the same as using the GNU Linker,
arm-elf-ld, yourself. The reason is
that the GNU Compiler automatically
links a number of standard system
libraries into your executable. These
libraries allow your program to
interact with an operating system, to
use the standard C library functions,
to use certain language features and
operations (such as division), and so
on. If you wish to see exactly which
libraries are being linked into the
executable, you should pass the
verbose flag
-v to the compiler.
This has important implications for
embedded systems! Such systems do not
usually have an operating system.
This means that linking in the system
libraries is almost always
meaningless: if there is no operating
system, for example, then calling the
standard printf function does not make
much sense.
So when I get back to my dev machine later I will determine the libraries linked in with the Linux build and add them to the arm-elf-gcc build.
I'll update this when I have more information but I just want to document my findings in case any one else has these problems.

Problems compiling TCC on OS X

Has anyone successfully compiled TCC on OS X?
From what I know it should be possible but when I run make I get the following error:
$ make
gcc -o tcc tcc.c -DTCC_TARGET_I386 -O2 -g -Wall -fno-strict-aliasing -mpreferred-stack- boundary=2 -march=i386 -falign-functions=0 -Wno-pointer-sign -Wno-sign-compare -D_FORTIFY_SOURCE=0 -lm -ldl
tcc.c:1: error: CPU you selected does not support x86-64 instruction set
tcc.c:1: error: CPU you selected does not support x86-64 instruction set
tcc.c:1: error: -mpreferred-stack-boundary=2 is not between 4 and 12
make: *** [tcc] Error 1
./configure runs fine and gives the following output:
$ ./configure
Binary directory /usr/local/bin
TinyCC directory /usr/local/lib/tcc
Library directory /usr/local/lib
Include directory /usr/local/include
Manual directory /usr/local/man
Doc directory /usr/local/share/doc/tcc
Target root prefix
Source path /Users/aaron/Downloads/tcc-0.9.25
C compiler gcc
CPU x86
Big Endian no
gprof enabled no
cross compilers no
use libgcc no
Creating config.mak and config.h
I'm pretty sure the issue is something simple, but I haven't compiled enough programs on OS X to be aware of the pratfalls...
The primary purpose for installing TCC was to get libtcc so I could start experimenting with dynamic code generation from Ruby (in case that makes a difference :-p)
Thanks!
I have just spent some serious time trying to make tcc run on osx. I have included several fixes, including the one from the answer above, and now they are all in the development repository at http://repo.or.cz/w/tinycc.git. Building, some tests and all examples should work.
I am not sure if you are aware, but http://bellard.org/tcc/ site that belongs to Fabrice Bellard who started this project, is not being updated very regularly. Mostly because there are not many 'official' tcc releases. tcc is one of those projects that mostly lives off of live sources and updates. So if you want to give this another try, please go to http://repo.or.cz/w/tinycc.git and get the 'mob' branch (not 'master'). Please see http://repo.or.cz/w/tinycc.git for details, and do join the mailing list to get involved.
I'll consolidate my comments now.
There seem to be several issues.
There has been a change in the naming scheme for the x86 register access as of Mac OS 10.5. See Access EIP and EBP via ucontext on OS X. This will require hacking the source until the maintainer can be convinced to support Mac OS X.
The executable formats supported by tcc do not overlap with those that Mac OS X will run natively. However, XBinary may address this. (I didn't find either a fink package or a MacPorts package, however and don't have it installed yet. Not sure that I will--this is deep magic, and could in theory do very bad things indeed.) Ah... this was already on SO too: Possibility of loading/executing ELF files on OSX.
The errors can be fixed by edit configure script of TCC package (ver 0.9.25).
In the configure script, line 36 says
cpu=uname -m
If you run uname -m in the console of Mac OS X, it prints "i386" even if it is a 64-bit system.
A solution is to comment off this line, and replace it with cpu=x86_64,
Then some compiling errors will show up because of the register naming conventions in Mac OS X, as mentioned by dmckee in this thread.
My fix is to add a few lines to libtcc.c around line 1512.
Finally it will look like
#ifdef __DARWIN_UNIX03
*paddr = uc->uc_mcontext->__ss.__rip;
#else
*paddr = uc->uc_mcontext.gregs[REG_RIP];
#endif
return 0;
} else {
#ifdef __DARWIN_UNIX03
fp = uc->uc_mcontext->__ss.__rbp;
#else
fp = uc->uc_mcontext.gregs[REG_RBP];
#endif
It compiles then.

Resources