|
|
(10 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
− | Objective-C under Ubuntu Linux
| + | Usually it is a good a idea to just use the package manager of your distribution to get a stable and well integrated GNUstep environment: |
| | | |
− | == Compiling Everything from Scratch ==
| + | sudo apt-get install gnustep gnustep-devel |
| | | |
− | The following scripts compiles and installs everything needed for Objective-C 2.0 from scratch. The script uses clang and libobjc2 for all the awesome new features like ARC, blocks, etc.
| + | If you want to develop new apps and try the newest features consider the approach described below. |
| | | |
− | Reference manuals for GNUStep, including available APIs, etc, are available at http://www.gnustep.org/developers/documentation.html
| + | = Compiling Everything from Scratch = |
| | | |
− | NOTE: Unless you have a need for the above features, its recommended to install from the default repos as often the scripts below have issues.
| + | The following repo contains scripts that compile and install everything needed for GNUstep Objective-C 2.0. The script uses clang and libobjc2 for all the awesome new features like ARC, blocks/Grand Central Dispatch, etc. |
| | | |
− | <pre>sudo apt install gnustep</pre>
| + | For example, to build GNUstep under Ubuntu 19.04, do: |
| | | |
| + | git clone https://github.com/plaurent/gnustep-build |
| + | cd gnustep-build/ubuntu-19.04-clang-8.0-runtime-2.0/ |
| + | ./GNUstep-buildon-ubuntu1904.sh |
| | | |
− | === Ubuntu 19.04 ===
| + | The demo.sh and demo-gui.sh scripts show example code and compilation examples (using command line as well as the recommended GNUmakefile approach.) |
| | | |
− | In addition to building everything, this script also provides the ability to build the most recent version of four apps: Project Center, Gorm, GWorkspace, and System Preferences.
| + | Reference manuals for GNUStep, including available APIs, etc, are available at http://www.gnustep.org/developers/documentation.html |
− | | |
− | <pre>
| |
− | #!/bin/bash
| |
− | | |
− | # Show prompt function
| |
− | function showPrompt()
| |
− | {
| |
− | if [ "$PROMPT" = true ] ; then
| |
− | echo -e "\n\n"
| |
− | read -p "${GREEN}Press enter to continue...${NC}"
| |
− | fi
| |
− | }
| |
− | | |
− | # Set colors
| |
− | GREEN=`tput setaf 2`
| |
− | NC=`tput sgr0` # No Color
| |
− | | |
− | # Set to true to also build and install apps
| |
− | APPS=true
| |
− | | |
− | # Set to true to pause after each build to verify successful build and installation
| |
− | PROMPT=false
| |
− | | |
− | # Install Requirements
| |
− | sudo apt update
| |
− | | |
− | echo -e "\n\n${GREEN}Installing dependencies...${NC}"
| |
− | | |
− | sudo dpkg --add-architecture i386 # Enable 32-bit repos for libx11-dev:i386
| |
− | sudo apt-get update
| |
− | sudo apt -y install clang git cmake libffi-dev libxml2-dev \
| |
− | libgnutls28-dev libicu-dev libblocksruntime-dev libkqueue-dev libpthread-workqueue-dev autoconf libtool \
| |
− | libjpeg-dev libtiff-dev libffi-dev libcairo-dev libx11-dev:i386 libxt-dev libxft-dev
| |
− | | |
− | if [ "$APPS" = true ] ; then
| |
− | sudo apt -y install curl
| |
− | fi
| |
− | | |
− | # Create build directory
| |
− | mkdir GNUstep-build
| |
− | cd GNUstep-build
| |
− | | |
− | # Set clang as compiler
| |
− | export CC=clang
| |
− | export CXX=clang++
| |
− | | |
− | # Checkout sources
| |
− | echo -e "\n\n${GREEN}Checking out sources...${NC}"
| |
− | #git clone https://github.com/nickhutchinson/libdispatch.git
| |
− | git clone https://github.com/plaurent/libdispatch.git
| |
− | cd libdispatch
| |
− | git checkout fix_major_missing_symbol_for_ubuntu1904
| |
− | cd ..
| |
− | git clone https://github.com/gnustep/libobjc2.git
| |
− | git clone https://github.com/gnustep/tools-make.git
| |
− | git clone https://github.com/gnustep/libs-base.git
| |
− | git clone https://github.com/gnustep/libs-gui.git
| |
− | git clone https://github.com/gnustep/libs-back.git
| |
− | | |
− | if [ "$APPS" = true ] ; then
| |
− | git clone https://github.com/gnustep/apps-projectcenter.git
| |
− | git clone https://github.com/gnustep/apps-gorm.git
| |
− | git clone https://github.com/gnustep/apps-gworkspace.git
| |
− | git clone https://github.com/gnustep/apps-systempreferences.git
| |
− | fi
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build GNUstep make first time
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building GNUstep-make for the first time...${NC}"
| |
− | cd tools-make
| |
− | # git checkout `git rev-list -1 --first-parent --before=2017-04-06 master` # fixes segfault, should probably be looked at.
| |
− | ./configure --enable-debug-by-default --with-layout=gnustep --enable-objc-arc --with-library-combo=ng-gnu-gnu
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
| |
− | echo ". /usr/GNUstep/System/Library/Makefiles/GNUstep.sh" >> ~/.bashrc
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build libdispatch
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building libdispatch...${NC}"
| |
− | cd ../libdispatch
| |
− | rm -Rf build
| |
− | mkdir build && cd build
| |
− | ../configure --prefix=/usr
| |
− | make
| |
− | sudo make install
| |
− | sudo ldconfig
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build libobjc2
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building libobjc2...${NC}"
| |
− | cd ../../libobjc2
| |
− | rm -Rf build
| |
− | mkdir build && cd build
| |
− | cmake ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang -DCMAKE_ASM_COMPILER=clang -DTESTS=OFF
| |
− | cmake --build .
| |
− | sudo -E make install
| |
− | sudo ldconfig
| |
− | | |
− | export LDFLAGS=-ldispatch
| |
− | | |
− | showPrompt
| |
− | | |
− | OBJCFLAGS="-fblocks -fobjc-runtime=gnustep-2.0"
| |
− | | |
− | # Build GNUstep make second time
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building GNUstep-make for the second time...${NC}"
| |
− | cd ../../tools-make
| |
− | ./configure --enable-debug-by-default --with-layout=gnustep --enable-objc-arc --with-library-combo=ng-gnu-gnu
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build GNUstep base
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building GNUstep-base...${NC}"
| |
− | cd ../libs-base/
| |
− | ./configure
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build GNUstep GUI
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN} Building GNUstep-gui...${NC}"
| |
− | cd ../libs-gui
| |
− | ./configure
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | # Build GNUstep back
| |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building GNUstep-back...${NC}"
| |
− | cd ../libs-back
| |
− | ./configure
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
| |
− | | |
− | if [ "$APPS" = true ] ; then
| |
− | echo -e "${GREEN}Building ProjectCenter...${NC}"
| |
− | cd ../apps-projectcenter/
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | echo -e "${GREEN}Building Gorm...${NC}"
| |
− | cd ../apps-gorm/
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building GWorkspace...${NC}"
| |
− | cd ../apps-gworkspace/
| |
− | ./configure
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | showPrompt
| |
− | | |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Building SystemPreferences...${NC}"
| |
− | cd ../apps-systempreferences/
| |
− | make -j8
| |
− | sudo -E make install
| |
− | | |
− | fi
| |
− | | |
− | echo -e "\n\n"
| |
− | echo -e "${GREEN}Install is done. Open a new terminal to start using.${NC}"
| |
− | </pre>
| |
− | | |
− | === Older versions of Ubuntu (18.04 or earlier) ===
| |
− | | |
− | On older versions of Ubuntu (including 18.04) you won't have a recent enough clang. If you want to build on an older Ubuntu (like 18.04) you should:
| |
− | | |
− | (1) Set OBJCFLAGS="-fblocks -fobjc-runtime=gnustep-1.9" in the script above
| |
− | (2) git checkout 1.9 on libobjc2
| |
− | (3) Build a new clang manually (instead of apt install clang):
| |
− | | |
− | <pre>
| |
− | svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
| |
− | cd llvm/tools
| |
− | svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
| |
− | svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
| |
− | cd ~/llvm
| |
− | rm -rf build
| |
− | mkdir build
| |
− | cd build
| |
− | cmake -D CMAKE_BUILD_TYPE:STRING=Release .. # If you don't choose Release, it defaults to Debug which takes lots more space
| |
− | make -j8 # 8=your number of build CPUs
| |
− | echo "export PATH=\$PATH:~/llvm/build/bin" >> ~/.bashrc
| |
− | echo "export CC=clang" >> ~/.bashrc
| |
− | echo "export CXX=clang++" >> ~/.bashrc
| |
− | export PATH=$PATH:~/llvm/build/bin
| |
− | . ~/.bashrc
| |
− | | |
− | export CC=clang
| |
− | export CXX=clang++
| |
− | </pre>
| |
− | | |
− | == Test Code ==
| |
− | | |
− | The following is some Objective-C source code from the internet.
| |
− | It demonstrates blocks, Grand Central Dispatch, and the use of GNUStep GUI.
| |
− | | |
− | <pre>
| |
− | #!/bin/bash
| |
− | | |
− | cat > blocktest.m << EOF
| |
− | #include <stdio.h>
| |
− | | |
− | int main() {
| |
− | void (^hello)(void) = ^(void) {
| |
− | printf("Hello, block!\n");
| |
− | };
| |
− | hello();
| |
− | return 0;
| |
− | }
| |
− | EOF
| |
− | | |
− | cat > helloGCD_objc.m << EOF
| |
− | | |
− | #include <dispatch/dispatch.h>
| |
− | #import <stdio.h>
| |
− | #import "Fraction.h"
| |
− | | |
− | int main( int argc, const char *argv[] ) {
| |
− | dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
| |
− | Fraction *frac = [[Fraction alloc] init];
| |
− | | |
− | [frac setNumerator: 1];
| |
− | [frac setDenominator: 3];
| |
− | | |
− | // print it
| |
− | dispatch_sync(queue, ^{
| |
− | printf( "The fraction is: " );
| |
− | [frac print];
| |
− | printf( "\n" );
| |
− | });
| |
− | dispatch_release(queue);
| |
− | | |
− | return 0;
| |
− | }
| |
− | | |
− | EOF
| |
− | | |
− | cat > Fraction.h << EOF
| |
− | | |
− | #import <Foundation/NSObject.h>
| |
− | | |
− | @interface Fraction: NSObject {
| |
− | int numerator;
| |
− | int denominator;
| |
− | }
| |
− | | |
− | -(void) print;
| |
− | -(void) setNumerator: (int) n;
| |
− | -(void) setDenominator: (int) d;
| |
− | -(int) numerator;
| |
− | -(int) denominator;
| |
− | @end
| |
− | | |
− | EOF
| |
− | | |
− | | |
− | cat > Fraction.m << EOF
| |
− | #import "Fraction.h"
| |
− | #import <stdio.h>
| |
− | | |
− | @implementation Fraction
| |
− | -(void) print {
| |
− | printf( "%i/%i", numerator, denominator );
| |
− | }
| |
− | | |
− | -(void) setNumerator: (int) n {
| |
− | numerator = n;
| |
− | }
| |
− | | |
− | -(void) setDenominator: (int) d {
| |
− | denominator = d;
| |
− | }
| |
− | | |
− | -(int) denominator {
| |
− | return denominator;
| |
− | }
| |
− | | |
− | -(int) numerator {
| |
− | return numerator;
| |
− | }
| |
− | @end
| |
− | | |
− | EOF
| |
− | | |
− | | |
− | | |
− | cat > guitest.m << EOF
| |
− | #import <AppKit/AppKit.h>
| |
− | | |
− | int main()
| |
− | {
| |
− | NSApplication *app; // Without these 2 lines, seg fault may occur
| |
− | app = [NSApplication sharedApplication];
| |
− | | |
− | NSAlert * alert = [[NSAlert alloc] init];
| |
− | [alert setMessageText:@"Hello alert"];
| |
− | [alert addButtonWithTitle:@"All done"];
| |
− | int result = [alert runModal];
| |
− | if (result == NSAlertFirstButtonReturn) {
| |
− | NSLog(@"First button pressed");
| |
− | }
| |
− | }
| |
− | EOF
| |
− | | |
− | # ======================================================================
| |
− | # COMPILE USING THE FOLLOWING COMMAND LINES, OR CREATE A MAKEFILE
| |
− | # ======================================================================
| |
− | | |
− | # Using COMMAND LINE
| |
− | | |
− | clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` -lobjc blocktest.m
| |
− | ./a.out
| |
− | | |
− | clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` -lobjc -ldispatch -lgnustep-base Fraction.m helloGCD_objc.m
| |
− | ./a.out
| |
− | | |
− | clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` -lobjc -fobjc-arc -ldispatch -lgnustep-base -lgnustep-gui guitest.m
| |
− | ./a.out
| |
− | | |
− | # Using MAKEFILE
| |
− | | |
− | cat > GNUmakefile << EOF
| |
− | include \$(GNUSTEP_MAKEFILES)/common.make
| |
− | | |
− | APP_NAME = GUITest
| |
− | GUITest_OBJC_FILES = guitest.m
| |
− | | |
− | include \$(GNUSTEP_MAKEFILES)/application.make
| |
− | EOF
| |
− | | |
− | make
| |
− | openapp ./GUITest.app
| |
− | </pre>
| |
| | | |
| General Note: When compiling your own code, it is generally good to tell clang both the family and version of the runtime: -fobjc-runtime=gnustep-2.0 | | General Note: When compiling your own code, it is generally good to tell clang both the family and version of the runtime: -fobjc-runtime=gnustep-2.0 |
| (The current version number can be had by looking at the latest ANNOUNCE filename in https://github.com/gnustep/libobjc2 (e.g., ANNOUNCE.1.8.1)) | | (The current version number can be had by looking at the latest ANNOUNCE filename in https://github.com/gnustep/libobjc2 (e.g., ANNOUNCE.1.8.1)) |