Cross Compiling from XCode on the Mac to Windows - c

So, as far as I can tell, there wasn't another issue for this that was recent enough to be compatible with new major updates.
I am programing on a Mac using XCode 4.
I need to write a program for Windows.
How would I do this, and is it the same exact code just compiled differently?!?
Any and all help would be appreciated, I have no idea what I'm doing here.
Thanks!

If you stick strictly to the subset of POSIX C supported by both Mac and Windows (which implicitly limits you to console applications), you can possibly get a Windows cross-compiler for OS X and build applications that way.
However, you will likely find your life vastly simplified if you just run Windows in a VM (or via Boot Camp) and develop your application in Visual Studio or any other Windows development environment. This is the only way to make a Windows GUI app, and realistically the only good way to write a Windows console app.

While the systems are very different, it's possible to write code that compiles on both, just not any code, you'll need to design it carefully; this is called "portable code".
Say you already have your code written; then you can use MINGW (e.g. brew install mingw-w64) for cross-compiling for Windows, you can even test the resulting .exe on Mac OS X using WINE; also clang can be used to compile for Windows, but I never tried that.
Here's an example Makefile from a real project:
toolchain = mingw
#toolchain = wine
mingw- = i586-mingw32msvc-
mingw-cc := ${mingw-}gcc
mingw-cxx := ${mingw-}c++
mingw-rc := ${mingw-}windres
wine-cc = winegcc
wine-cxx = wineg++
wine-rc = wrc
CC := ${${toolchain}-cc}
CXX := ${${toolchain}-cxx}
RC := ${${toolchain}-rc}
LDFLAGS = -mwindows -mno-cygwin
LIBS = -lodbc32 -lole32 -loleaut32 -lwinspool -luuid
app-objs = app.o \
app_resources.o \
input.o \
user_manual.o \
hints.o
all: app.exe
clean:
${RM} ${app-objs} app.exe
app.exe: ${app-objs}
${CC} ${LDFLAGS} -o $# ${app-objs} ${LIBS}
.c.o:
${CC} -c ${CFLAGS} -o $# $<
.rc.o:
${RC} ${RCFLAGS} -o $# $<
.SUFFIXES: .rc .res
.PHONY: all clean
BTW, the example comes from a project originally built with MS Visual Studio by someone else, then years later ported by me to MINGW and cross-compiled from Debian GNU/Linux (but would be identical for Mac OS X). It's just an example, but most languages do have some way to cross-compile which is more or less equivalent to that.
Now, the really tricky part is the code base, a way to develop an application natively in your Mac and have it also compile for Windows is to use a well-supported portable framework, like Qt, which guarantees you the same API across many OSes.
Still, some bits about the target platforms might be slightly different and may need to be corrected, but tend to be minor changes.
So, in short, by using portable frameworks, it becomes just a matter of setting up your existing build system, whatever it is, to use the right cross-compiling tools, providing said frameworks, and it will compile more or less in the same way as it does for a native build.

Related

How to cross compile a C SDL program for Windows on Linux?

I have a perfectly working C program using SDL that I can compile with
gcc main.c -o program `sdl-config --libs` -lSDL
The program is simple, it comes up with a black window and waits for the user to close it. No problems or errors. I have MinGW installed and I'm trying to use x86_64-w64-mingw32-gcc to cross-compile it; I would like to know how to cross-compile this for Windows on Linux and include the necessary libraries.
You can invoke MinGW’s GCC like your Linux version, but you might need to replacesdl-config with some manual configuration like so:
x86_64-w64-mingw32-gcc -Ipath/to/SDL/headers \
-Lpath/to/SDL/libs \
-o program main.o \
-lSDL -lSDLmain
You will need to download SDL.lib and SDLmain.lib. I believe they are part of the development zip. (Edit: as noted in the comments, you might not need to use the libs but can just use the DLLs.)
This might pop up a console window when running. Pass in the -mwindows flag to target the Windows subsystem instead.

Makefile for C code

I inherited a code which has a makefile, but so far I was unable to run it on a linux server. The main complain of the compiler is that it is unable to load libgmp.so.3 : error while loading shared libraries: libgmp.so.3. I know that libgmp.so.10 exists on this server, but I was wondering which part of the makefile needs to be changed so the compiler looks for libgmp.so.10 rather than libgmp.so.3.
OPTFLAG = -O2 -Wall -fPIC -fexceptions -DNDEBUG
LDFLAGS = -O2 -Wl,-no_compact_unwind -DNDEBUG -lm -pthread
COMPILER = gcc ${OPTFLAG}
LINKER = gcc ${LDFLAGS}
# CPLEX directory
CPLEX_HOME = /opt/ibm/ILOG/CPLEX_Studio1263/cplex
CPLEX_INC = ${CPLEX_HOME}/include/
CPLEX_LIB = ${CPLEX_HOME}/lib/x86-64_linux/static_pic/ -lcplex
# Compile the main file
code: code.c
${COMPILER} -c code.c -o code.o -I${CPLEX_INC}
${LINKER} -o code code.o -L${CPLEX_LIB}
clean::
rm -f *.o
rm -f ${LIB}/*.o
rm -f *~
rm -f ${SRC}/*~ ${INCLUDE}/*~
You need to rebuild whatever program or library uses libgmp.so.3 from source code. Could you provide the exact command run by make and the error message it produces?
EDIT The problem here is that the system has installed a version of the IBM CPLEX software which comes with its own GCC binary, and that GCC binary uses libgmp.so.3. The easiest way to fix this would be to upgrade the CPLEX software to a version which supports the operating system being used, or use the software on the operating system for which it was written (i.e., something really old that actually ships libgmp.so.3).
The most easy way it to install libgmp-dev package, from your linux distribution. GMP is a package library to do multiple precision calculations on large integers, which is probably needed by your program. As you put in some comments, adding -L/usr/lib64/libgmp.so.10 is an error, as -L option allows to add a directory to search for libraries, and not a specific library.
If only the library is needed and no header file is missing in your compilation (this is something strange, but sometimes happen) then you can still link with only the libgmp.so.10 object, but you have to do in a something nasty way. Just add /usr/lib64/libgmp.so.10 as an object file (not a library, with -l option) to your link command.
EDIT
From looking more closely your Makefile I see no reference to the libgmp.so.3 library, so I only can assume this is a indirect reference from some other already compiled library that comes from outside with your package. Just use
ldd lib<nameOfLibrary>.so.x.x
with all the libraries needed by your final executable, so see which shared objetc is the one that requests libgmp.so.3 soname, and then recompile it, reinstall it, or use your system's libraries ONLY, and not mesh anymore with libraries coming from another system. For example you can try (this is an expensive command, but it will get the answer)
find / -name "lib*.so.*" -print | xargs ldd > all_libs.lddout
and then find all_libs.lddout to see which library uses libgmp.so.3 (this will be the outdated library) You'll need to deinstall it or upgrade it, to be able to continue.
Linux systems have a library version system that allows an executable to be able to load different versions of the same library and allow them to live together in the same system. One of two: or you are able to locate the sources of version 3 of the shared libgmp.so.3 library and install it on your system, or you'll need to update the libraries your program uses to be able to link with the libgmp.so.10 already installed on your system.
2ND EDIT
As I see in the comments, you have changed the default compiler on your system by another coming possibly from other linux distribution (as your installed library is libgmp.so.10 while the one cc1 requests is libgmp.so.3, which is not installed on your system.
Installing a different compiler from the one you have installed, and doing that without previously deinstalling the other compiler, can lead you to this kind of problems.
The most reliable thing you can do is to reinstall the compiler from your distribution, or better, reinstall the whole linux system, as you have probably broken many things that will be emerging as you use your system. There's very poor info on what you have done to go further in your problem. Anyway, my recommendation is to not use the comment parts to add new information about your problem, just edit your question and add all those new information to it.

Makefiles and cross platform development

I have been trying to figure out how to create a C program that can be compiled for all of the major operating systems. I have considered using makefiles so I would just have to change the target OS, but I have a few problems. My first problem is that I cannot figure out how to change the target OS so I can compile on one OS but use the application on all OS's. My second issue is that I cannot figure out how to make it automatically compile all .c files in the src directory, so I do not have to modify the makefile every time I add a new file. Does anybody know how to do this stuff?
My current makefile (currently unmodified from here)
CC=gcc
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#q2
The GNU Autoconf is a good place to start. I can't give you a complete answer because I don't know what you'd do for Windows except maintain a set of nmake scripts. While there's a learning curve they make it possible to write make files and c-code that work across platforms. It will not only handle multiple source files for you but help you define target such as 'all', 'install,' 'clean,' etc. If you're familiar with downloading a project and then typing './configure' and then 'make install' then you've probably been a user of an Autoconf generated project.
There are other reasons to use Autoconf than just handling multiple source files.
What makes C/C++ development across flavors of Unix difficult is the definition of 'Unix' and C. Different flavors of Unix have slightly different library or system calls depending on what flavor of standards they support. The same is true of C. So, when writing code you'll see #defines specifying a group of preprocessor symbols that define a version of Unix and C that you'd like to use. Going from GCC to HP C or some other vendor's C compiler may include different 'default' levels of behavior, so you need to make the expected behavior explicit.
Second, you need to define what libraries are required. In your build you might need to probe for mysql libraries and decide what to do if those libraries are not installed. In some cases you might need to not build at all or in some cases you might just substitute for another library (like libdb). Having tried writing complex makefiles to support even two operating systems (Solaris and Linux), I would not want to re-invent this wheel.

Cross compiling source from windows to linux

This is my make file
EXE = signsrch
CFLAGS += -s -O2
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
SRC = $(EXE).c
all:
$(CC) $(CFLAGS) -c disasm.c
$(CC) $(CFLAGS) -c asmserv.c
$(CC) $(SRC) $(CFLAGS) -o $(EXE) *.o
install:
install -m 755 -d $(BINDIR)
install -m 755 $(EXE) $(BINDIR)/$(EXE)
.PHONY:
install
I want to cross compile it for my ubuntu and I tried:
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
but I get unknown type name errors with a bunch of âDWORDâ
Help?
We also need to see some code, but....
Windows has its own types for basic things above the vanilla C ones, as does Linux. It sounds like DWORD as a type is not known in Linux (likely). You'll probably have to create a mytypes.h file that redefines Windows standards like DWORD into Linux speak when building for a Linux platform. Linux has types.h that defines things like int32_t which is the equivalent. See this thread for more about this.
I've assumed you have a working cross compiler set up and you're fighting just with the port. If you haven't, that's your first job. You could have a windows based compiler that targets Linux (the cygwin option, mentioned in another post) or go for a Linux based compiler and targetting windows (crosstool will help here). Though since you seem to be targetting arm, I'm expecting that that Ubuntu install isn't the place you wish to build! :-)
to cross compile you need a toolchain for the target platform, not just a Makefile. Check this tutorial and also Cygwin

Compiling 32-bit GTK+ Applications of 64 bit Linux

I am having some trouble compiling 32-bit GTK+ applications on 64-bit Linux, specifically Ubuntu 10.04. Compiling 64-bit GTK+ applications works fine, and everything is set up to compile 32-bit apps as well, but it doesn't work with GTK+
I have a very simple test program that I am using for trouble shooting that is simply a gtk_init and a gtk_main, which compiles fine as -m64. I am compiling with gcc 4.6.2, calling it with:
gcc -m32 gtktest.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
These are the two different kinds of error messages I get:
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libXext.so.6, needed by /usr/lib/../lib32/libgtk-x11-2.0.so, not found (try using -rpath or -rpath-link)
and
/usr/lib/../lib32/libgdk-x11-2.0.so: undefined reference to `XmbSetWMProperties'
Keep in mind that these aren't the only errors, I just included the two specific types for reference and to keep it short, I get errors for the whole stack of GTK+ libraries.
I do have all of the proper 32-bit versions of the libraries in my lib32 folders.
Hopefull someone has had this problem before and can help me, this is really causing me quite the headaches, and I can't fine much help any where on the net.
Please ask if there is any other information you need me to provide to help with diagnosing this problem.
Note: I do have the ia32-libs and gcc-multilib packages. Ubuntu 10.04 does not have a separate ia32-libs-gtk packages, but I think these are wrapped in to the ia32-libs packages. They all are present on my system.
I think this must be some sort of linker config problem. I've recently built the new Free Pascal compiler and a 32 bit cross compiler, and I also upgraded GCC to 4.6.2 to take advantage of some of the new C++ features and fixes to C99 support. The default 4.4.3 GCC still exists on my system. Where I think the problem has been introduced is when I installed a new binutils because I've been experimenting with Clang and LLVM as a toolchain, and I wanted and ld with plug-in capabilities, so I figured might as well upgrade them all.
Everything works fine compiling 64 bit programs, there hasn't been a single problem with the new tools at all, and I can compile 32-bit programs but when it comes time to explicitly link something in I have problems.
I know my current set of libs is appropriate, and I have Free Basic installed which only emits 32 bit code, and I was able to build 32-bit GTK+ programs no problem before this upgrade.
Just wondering if anyone has any ideas what configs might have been changed in this upgrade or has had this happen to them before? I really should upgrade to a newer distro so I can take advantage of all the new software with out have to hack up all of my packages, but unfortunatly there is a bug in the newer kernels that prevents my computer from coming back from standby, and this is a laptop I use for personal side projects, so proper power management is pretty important, and it's not a huge loss if I bork the system, other than I have it set up pretty much perfect for my workflow.
You may tell pkg-config to search for the 32-bit libraries with the environment variable PKG_CONFIG_PATH.
For Ubuntu:
export PKG_CONFIG_PATH=/usr/lib32/pkgconfig:$PKG_CONFIG_PATH
For Redhat:
export PKG_CONFIG_PATH=/usr/lib/pkgconfig:$PKG_CONFIG_PATH
I think you need to install the ia32-libs-gtk & gcc-multilib packages, and you need to compile and link with gcc -m32 as you already do.
The GTK package in 12.04 doesn't seem to work correctly with multiarch. You can work around this on Ubuntu 12.04 by creating the following symlinks:
sudo ln -s /lib/i386-linux-gnu/libglib-2.0.so.0 /usr/lib32/libglib-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0 /usr/lib32/libgtk-x11-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0 /usr/lib32/libgdk-x11-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libatk-1.0.so.0 /usr/lib32/libatk-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libpangox-1.0.so.0 /usr/lib32/libpangox-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libpango-1.0.so.0 /usr/lib32/libpango-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgmodule-2.0.so.0 /usr/lib32/libgmodule-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 /usr/lib32/libgobject-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgdk_pixbuf-2.0.so.0 /usr/lib32/libgdk_pixbuf-2.0.so
I found the answer in this thread: http://www.blitzbasic.com/Community/posts.php?topic=101357
Alternatively (probably better), you can leave the base system untouched and update your link to search by file name instead of library name. Something like:
gcc -m32 gtktest.c `pkg-config --cflags gtk+-2.0` -L/usr/lib/i386-linux-gnu -l:libgio-2.0.so.0 ...
This isn't great. You'll have to add a -l: for each library that the linker can't find and your build will break if the library file name ever changes.

Resources