Back to home

Compiling Code::Blocks from source on Mac

Finally, after trying like 100 times to get a working installation/build script for the latest CodeBlocks version I managed to get it working! Now, I've got a script which I can simply run and which compiles the latest Code::Blocks version (from svn) into a application bundle for the Mac. Below I'll describe the steps I had to make to get it all working. First some of the things which are important

● I've been using the wxWidgets 2.8 branch and Code::Blocks revision 6135
● I first installed XCode on my MacOS 10.6 (xcode probably sets up the developer tools you need, but I'm not sure)
● take care of the dynamic libraries and their locations
● some paths and files need to be copied to the bundle location which is not described anywhere (untill now)

Compiling and configuring
There wasn't really something special while compiling Code::Blocks, the only thing you should know, is that you run "./bootstrap" before you can configure it. (See the script below that I used).

Creating a bundle
When you've compiled Code::Blocks and wxWidgets using shared/dynamic libraries you need to tell the libraries and executables where they can find these. Normally they try to find the libraries in /usr/local/lib for example. This information is stored in the libraries and executables. Using "otool -L [file]" you can check which libraries are used by that file. With another util, called intall_name_tool you can change the paths to the dynamic libraries that a file uses. As you're creating an application bundle, it's wise to put all the necessary libraries in the bundle directory. If you don't know what an application bundle is, here is a quick summary. MacOS has a nice system to manage applications. When you open the Application directory in Finder you see all the applications with an icon. Though, under the hood, on the file system, these applications (or at least 99% of them), are named "Application.app", so with the ".app" extension. Finder removes these and creates a clickable application. Under this Application.app are a couple of other directories (Google for MacOS application bundle directories for more info). So, back to the libraries. It's wise to put the libraries you've compiled into the application bundle director and tell them about eachother so they will use the local libs instead of the system libs. See the script where we use install_name_tool for this. install_name_tool, works like this: install_name_tool [/path/to/library/which/is/used/now] [change/to/other/path] [change for this file]. When all paths have changed, the libraries and executables are set to go. When I did this I could run Code::Blocks but the plugins weren't installed which is something that must be done to use Code::Blocks (i.e. the project wizard is based on a plugin). For this I had to copy the [plugin].so files to the application bundle. At the bottom of the script you can see which files I had to copy as well. But here is a short list BTW: you need to bundle CodeBlocks into an application because else you can't focus or activate CodeBlocks, this is a wxWidgets thingie

● The icons can be found in C::B (svn dir)/src/src/resources/icons/*.icns and need to be moved to ${application_dir}/Contents/Resources
● The Info.plist file should be created, this can be found in the C::B build directory (so after compiling), named codeblocks.plist
● Make sure you use the --with-contribs=all flag when you compile Code::Blocks as it needs the plugins
● The plugin shared libraries should be copied to your application.app directory (see script for the location)
● Change the paths to the dynamic libraries that are used by your plugins (see the loop at the bottom of the script where we use install_name_tool)
● Make sure you configure with the CC/GCC etc.. flags set to "-arch 386": CFLAGS="-arch i386" CXXFLAGS="-arch i386" CPPFLAGS="-arch i386" LDFLAGS="-arch i386" OBJCFLAGS="-arch i386" OBJCXXFLAGS="-arch i386"

The script to create a CodeBlocks application on Mac form source
This script downloads the latest SVN version of Code::Blocks, the 2.8 branch of wxWidgets, creates some directories, configures wxWidgets/Code::Blocks and creates the CodeBlocks.app application bundle. The directories that are created:

● ./app: here you'll find your CodeBlocks.app
● ./codeblocks_svn
● ./wxwidgets_svn

The script will ask you a couple of questions, answer them by entering only a 'y' and make sure that you at least configured and compiled wxWidgets and C::B using the script at least once, before you answer something different than 'y'.

I hope this will help you to build a custom CodeBlocks application for Mac!

#!/bin/sh
#set -x
root_dir=${PWD}
 
if [ -d wxwidgets_svn ]
then
    read -p "Remove wxWidgets 2.8 directory to start clean install? [y/n]: " continue
    if test "${continue}" == "y" ;    then
        rm -r wxwidgets_svn
        mkdir wxwidgets_svn
    fi
else
    mkdir wxwidgets_svn
fi
 
if [ -d codeblocks_svn ]
then
    read -p "Remove CodeBlocks directory to start clean install? [y/n]: " continue
        if test "${continue}" == "y";  then
                rm -r codeblocks_svn
                mkdir codeblocks_svn
        fi
else
    mkdir codeblocks_svn
fi 
 
read -p "Download CodeBlocks from svn? [y/n]: " continue
if test "${continue}" == "y"; then
    cd codeblocks_svn
    svn co http://svn.berlios.de/svnroot/repos/codeblocks/trunk .
    cd ..
fi
 
read -p "Download wxWidgets 2.8 from svn? [y/n]: " continue
if test "${continue}" == "y"; then
    cd wxwidgets_svn
    svn co http://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH .
fi
 
 
#------------------------- wxWidgets ---------------------------------------
read -p "Configure wxWidgets 2.8? [y/n]: " continue
if test "${continue}" == "y"; then
    if [ ! -d ${root_dir}/wxwidgets_svn ]; then
        echo "No wxWidgets directory found"
        exit
    fi
 
    cd ${root_dir}/wxwidgets_svn
    if [ -d build_custom ]; then
        rm -r build_custom
    fi
 
    mkdir build_custom
    cd build_custom
    ./../configure --enable-shared \
     --enable-monolithic \
     --enable-unicode \
     --with-png=builtin \
     --with-jpeg=builtin \
     --with-tiff=builtin \
     --with-expat=builtin/configure \
     --enable-shared \
     --enable-monolithic \
     --enable-unicode \
     --with-mac \
     --with-expat=builtin \
     CFLAGS="-arch i386" CXXFLAGS="-arch i386" CPPFLAGS="-arch i386" \
     LDFLAGS="-arch i386" OBJCFLAGS="-arch i386" OBJCXXFLAGS="-arch i386"
fi
 
read -p "Compile wxWidgets 2.8 [y/n]: " continue
if test "${continue}" == "y"; then
    cd ${root_dir}/wxwidgets_svn/build_custom
    make
fi
 
read -p "Bootstrap Code::Blocks [y/n]: " continue
if test "${continue}" == "y"; then
    cd ${root_dir}/codeblocks_svn
    ./bootstrap
fi
 
read -p "Configure Code::Blocks [y/n]: " continue
if test "${continue}" == "y"; then
    if [ ! -d ${root_dir}/codeblocks_svn ]; then
        echo "No CodeBlocks directory found"
        exit
    fi
 
    cd ${root_dir}/codeblocks_svn
 
    if [ -d custom_build ]; then
        rm -r custom_build
    fi
 
    mkdir custom_build
    cd custom_build
    ./../configure \
        --prefix=${root_dir}/codeblocks_svn/custom_build/ \
        --with-wxdir=./../../wxwidgets28_from_svn/custom_build/ \
        CFLAGS="-arch i386" CXXFLAGS="-arch i386" \
        CPPFLAGS="-arch i386" LDFLAGS="-arch i386" \
        OBJCFLAGS="-arch i386" \
        OBJCXXFLAGS="-arch i386" \
        --with-contrib-plugins=all \
        --enable-static \
        --enable-debug \
        --with-macosx \
        --with-wxdir=${root_dir}/wxwidgets_svn/build_custom/ \
        --with-wx-config=${root_dir}/wxwidgets_svn/build_custom/wx-config \
        --with-wx-prefix=${root_dir}/wxwidgets_svn/build_custom/ 
fi
 
read -p "Compile and make Code::Blocks [y/n]: " continue
if test "${continue}" == "y"; then
    cd ${root_dir}/codeblocks_svn/custom_build
    make
fi
 
read -p "Create CodeBlocks.app bundle? [y/n]: " continue
if test "${continue}" == "y"; then
    if [ -d ${root_dir}/app/CodeBlocks.app ]; then
        read -p "An Codeblocks.app bundle already exists, remove first? [y/n]: " continue
        if test "${continue}" == "y"; then
            rm -r ${root_dir}/app/CodeBlocks.app
        fi
    fi
 
    app_dir=${root_dir}/app/CodeBlocks.app
    cb_dir=${root_dir}/codeblocks_svn
    wx_dir=${root_dir}/wxwidgets_svn
 
    mkdir -p ${app_dir}/Contents/MacOS
    mkdir -p ${app_dir}/Contents/Resources/share/codeblocks
    cp ${cb_dir}/custom_build/codeblocks.plist ${app_dir}/Contents/Info.plist
    cp ${cb_dir}/src/src/resources/icons/*.icns ${app_dir}/Contents/Resources/
    cp -r ${cb_dir}/custom_build/share/codeblocks/* ${app_dir}/Contents/Resources/share/codeblocks/
    cp ${cb_dir}/custom_build/bin/codeblocks ${app_dir}/Contents/MacOS/CodeBlocks
    cp ${cb_dir}/custom_build/lib/libcodeblocks.0.dylib ${app_dir}/Contents/MacOS/
    cp ${cb_dir}/custom_build/lib/libwxsmithlib.0.dylib ${app_dir}/Contents/MacOS/
    cp ${wx_dir}/build_custom/lib/libwx_macu-2.8.0.dylib ${app_dir}/Contents/MacOS/
    chmod 777 ${app_dir}/Contents/MacOS/CodeBlocks  
fi
 
read -p "Change dynamic lib paths? [y/n]: " continue
if test "${continue}" == "y"; then
 
    # copy the plugins (original version)
    cd ${root_dir}/codeblocks_svn/custom_build/src/plugins
    mkdir -p ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/plugins/
    for dir in `find -type d . -mindepth 1 -maxdepth 1`; do
        name=${dir##*/}
        plugin_libs=${root_dir}/codeblocks_svn/custom_build/src/plugins/${name}/.libs/
        for plugin_lib in ${plugin_libs}*.so; do
                if [ -f ${plugin_lib} ]; then    
                    cp ${plugin_lib} ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/
                fi
        done
    done
 
    # copy the other plugins (which one do I need to choose)
    #cb_plugin_dir=${root_dir}/codeblocks_svn/custom_build/lib/codeblocks/plugins
    #for dir in ${cb_plugin_dir}/*.so; do
    # cp ${dir} ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/
    #done
    for dir in `find --type d ${root_dir}/codeblocks_svn/custom_build/src/plugins/contrib -mindepth 1 -maxdepth 1`; do
            name=${dir##*/}
            libdir=${dir}/.libs
            if [ -d ${libdir} ]; then
                so_file=$(ls ${libdir}/*.so)
                    #if [ -f ${so_file} ]; then
                        #echo ${so_file}
                        #cp ${so_file} ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/
                    #fi
                #echo ${libdir}
            fi
            #plugin=${root_dir}/codeblocks_svn/custom_build/src/plugins/contrib/${name}/.libs/lib${name}.so
        # if [ -f ${plugin} ]; then
            #        cp ${plugin} ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/
            #fi
    done
    #cp /Users/diederickhuijbers/Documents/programming/_tests/cb1/codeblocks_svn/custom_build/src/plugins/compilergcc/.libs/libcompiler.so ${root_dir}/app/CodeBlocks.app/Contents/Resources/share/codeblocks/ 
 
 
    cd ${root_dir}/app/CodeBlocks.app/Contents
    install_name_tool -id @executable_path/libcodeblocks.0.dylib MacOS/libcodeblocks.0.dylib
    install_name_tool -id @executable_path/libwxsmith.0.dylib MacOS/libwxsmithlib.0.dylib
 
    install_name_tool -change ${root_dir}/codeblocks_svn/custom_build/lib/libcodeblocks.0.dylib @executable_path/libcodeblocks.0.dylib MacOS/CodeBlocks    
    install_name_tool -change ${root_dir}/codeblocks_svn/custom_build//lib/libcodeblocks.0.dylib @executable_path/libcodeblocks.0.dylib MacOS/CodeBlocks
    install_name_tool -change /usr/local/lib/libcodeblocks.0.dylib @executable_path/libcodeblocks.0.dylib MacOS/libwxsmithlib.0.dylib
    install_name_tool -change /usr/local/lib/libwx_macu-2.8.0.dylib @executable_path/libwx_macu-2.8.0.dylib MacOS/CodeBlocks
    install_name_tool -change /usr/local/lib/libwx_macu-2.8.0.dylib @executable_path/libwx_macu-2.8.0.dylib MacOS/libcodeblocks.0.dylib 
    install_name_tool -change /usr/local/lib/libwx_macu-2.8.0.dylib @executable_path/libwx_macu-2.8.0.dylib MacOS/libwxsmithlib.0.dylib
 
    for so in Resources/share/codeblocks/*.so; do
        libcodeblocks=$(otool -L ${so} | grep libcodeblocks)
        libcodeblocks=${libcodeblocks%%(*}
        install_name_tool -change ${libcodeblocks} @executable_path/libcodeblocks.0.dylib ${so}
 
        libwxsmith=$(otool -L ${so} | grep libwxsmithlib)
        libwxsmith=${libwxsmith%%(*}
        if test "${libwxsmith}" != ""; then
            install_name_tool -change ${libwxsmith} @executable_path/libwxsmithlib.0.dylib ${so}
        fi
 
        libwx=$(otool -L ${so} | grep libwx_macu)
        libwx=${libwx%%(*}
        if test "${libwx}" != ""}; then
            install_name_tool -change ${libwx} @executable_path/libwx_macu-2.8.0.dylib ${so}
        fi
 
        #install_name_tool -change /usr/local/lib/libcodeblocks.0.dylib @executable_path/libcodeblocks.0.dylib ${so}
        #install_name_tool -change /usr/local/lib/libwxsmithlib.0.dylib @executable_path/libwxsmithlib.0.dylib ${so}
        #install_name_tool -change /usr/local/lib/libwx_macu-2.8.0.dylib @executable_path/libwx_macu-2.8.0.dylib ${so}
    done
fi