從this answer我發現我的問題可能是我沒有使用「現代」的Objective-C運行時。
Instance variable declarations inside the @implementation { }
block is a relatively recent Objective-C feature. . . . you also need to be eligible for the "Modern" Objective-C runtime . . .
從this thread我發現,
Providing -fobjc-nonfragile-abi will also make some changes to the runtime. On Darwin it will use Apple's 'Modern' runtime, while not specifying it will generate code for the 'Legacy' runtime. If you specify -fobjc-nonfragile-abi and -fgnu-runtime, then clang will generate code for the GNUstep runtime, which you can find in GNUstep svn as libobjc2. This provides all of the ObjC 2 features except for GC, and a few others not found in the Mac runtimes.
所以,我嘗試添加以下到我的GNUmakefile:
Main_OBJCFLAGS = -fobjc-nonfragile-abi
但是,當我試圖編譯,我得到了錯誤:
fatal error: 'objc/blocks_runtime.h' file not found
Fr在那裏,我找到了this thread,並得出結論說我可能需要「libobjc2」。
令人失望的是,我找不到Debian的「libobjc2」軟件包,所以我試圖從源代碼編譯它。首先我必須安裝一些編譯依賴:
sudo apt-get install cmake llvm-dev
然後,我不得不申請this patch向LLVM-3。5-dev軟件包,因爲它是造成libobjc2編譯失敗:
wget -qO- https://launchpadlibrarian.net/221945609/fix-llvm-3.5-dev-debian.bash | bash
所以後來我就能夠編譯libobjc2用下面的命令:
wget http://download.gna.org/gnustep/libobjc2-1.7.tar.bz2
tar jxf libobjc2-1.7.tar.bz2
cd libobjc2-1.7
mkdir Build
cd Build
CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_LIBDIR=lib ..
make -j8
sudo -E make install
在那之後,我試圖編譯代碼再次從教程。編譯成功(沒有進行任何我不想做的更改)!然而,抱怨我的一個「.so」文件(我不記得確切的錯誤)和我運行我的程序(用./obj/Main
)之間的「潛在衝突」,我在程序輸出中看到以下內容:
$ ./obj/Main
Loading two versions of Protocol. The class that will be used is undefined
Loading two versions of Object. The class that will be used is undefined
2016-11-19 16:43:24.012 Main[10166] Created a Toyota Corolla
2016-11-19 16:43:24.017 Main[10166] Changed the car to a Toyota Camry
2016-11-19 16:43:24.017 Main[10166] Driving a Toyota Camry. Vrooom!
顯然,編譯libobjc2和現場讓它旁邊的Debian的軟件包GNUstep的可能沒有「好」。所以,我接受了各種在線資源的建議,着手從源代碼編譯GNUstep。
首先我卸載Debian軟件包:
sudo apt-get uninstall gnustep-devel && sudo apt-get autoremove
然後我安裝了下列建立依賴關係:
sudo apt-get install libffi-dev libicu-dev libgnutls28-dev libxml2-dev libxslt1-dev libtiff5-dev libjpeg-dev libpng-dev libgif-dev libaspell-dev libcups2-dev libaudiofile-dev portaudio19-dev libdispatch-dev
(我不能保證這是依賴的完整列表,只有那些我可以找到記錄;我可能有一些更多必要的庫已經安裝在我的電腦上,因此編譯了不相關的程序)
使用foll由於兩個教程(1)(2),稍微調整它們(可能不必要),我設法編譯GNUstep。
wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-make-2.6.8.tar.gz | tar xz
wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-base-1.24.9.tar.gz | tar xz
wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-gui-0.25.0.tar.gz | tar xz
wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-back-0.25.0.tar.gz | tar xz
cd gnustep-make-2.6.8
CC=clang ./configure --enable-objc-nonfragile-abi
sudo make install
cd ..
cd gnustep-base-1.24.9
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" ./configure
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" make
sudo make install
cd ..
cd gnustep-gui-0.25.0
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" ./configure
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" make
sudo make install
cd ..
cd gnustep-back-0.25.0
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" ./configure
CC=clang OBJCFLAGS="-fblocks -fobjc-nonfragile-abi" make
sudo make install
cd ..
在那之後,我再編譯我的教程文件,這次使用:
. /usr/local/share/GNUstep/Makefiles/GNUstep.sh && make -k
最後,我無法再獲得任何「衝突」的錯誤,當我運行該程序,我不再看到「加載兩個版本......」格式的錯誤。
$ ./obj/Main
2016-11-19 19:56:07.450 Main[10822:10822] Created a Toyota Corolla
2016-11-19 19:56:07.451 Main[10822:10822] Changed the car to a Toyota Camry
2016-11-19 19:56:07.451 Main[10822:10822] Driving a Toyota Camry. Vrooom!
成功!
我也將這個解決方案稍微重構成a script。這可能有點「更清潔」,更易於使用。我要「以防萬一:」在這裏貼上最新版本
#!/usr/bin/env bash
# It seems that many modern Objective-C features aren't available without
# libobjc2, which doesn't seem to be available as a Debian package. Also,
# compiling and using it alongside the Debian GNUstep packages doesn't work too
# well (it seems like they may each provide their own definition of the Protocol
# and Object classes). Basically, to get a fully-functioning Objective-C
# compilation environment on Debian 8, run this script.
# Please ensure any Debian GNUstep packages are uninstalled before running this
# script.
# Slightly adapted from
# http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux for Debian 8.
# Also, uses the latest stable versions of source packages as of this writing
# (hopefully to improve reproducability of success; but feel free to upgrade
# them if you want).
# If this script is successful, you should be able to compile a "main.m" program
# by running "make" in a directory with a "GNUmakefile" with these contents:
#
# include $(GNUSTEP_MAKEFILES)/common.make
# TOOL_NAME = Main
# Main_OBJC_FILES = main.m
# include $(GNUSTEP_MAKEFILES)/tool.make
# 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 pause after each build to verify successful build and installation
PROMPT=true
# Install Requirements
sudo apt update
echo -e "\n\n${GREEN}Installing dependencies...${NC}"
sudo apt -y install clang ninja cmake libffi-dev libxml2-dev \
libgnutls28-dev libicu-dev libblocksruntime-dev libkqueue-dev libpthread-workqueue-dev autoconf libtool \
libjpeg-dev libtiff5-dev libffi-dev libcairo2-dev libx11-dev libxt-dev libxft-dev \
llvm-dev libdispatch-dev
# https://bugs.launchpad.net/ubuntu/+source/llvm/+bug/1387011/comments/17
wget -qO- https://launchpadlibrarian.net/221945609/fix-llvm-3.5-dev-debian.bash | bash
# 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}Downloading sources...${NC}"
mkdir -p libobjc2 && wget -qO- https://github.com/gnustep/libobjc2/archive/v1.8.1.tar.gz | tar xz -C libobjc2 --strip-components=1
mkdir -p make && wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-make-2.6.8.tar.gz | tar xz -C make --strip-components=1
mkdir -p base && wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-base-1.24.9.tar.gz | tar xz -C base --strip-components=1
mkdir -p gui && wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-gui-0.25.0.tar.gz | tar xz -C gui --strip-components=1
mkdir -p back && wget -qO- ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-back-0.25.0.tar.gz | tar xz -C back --strip-components=1
showPrompt
# Build GNUstep make first time
echo -e "\n\n"
echo -e "${GREEN}Building GNUstep-make for the first time...${NC}"
cd make
./configure --enable-debug-by-default --with-layout=gnustep --enable-objc-nonfragile-abi --enable-objc-arc
make -j8
sudo -E make install
. /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
echo ". /usr/GNUstep/System/Library/Makefiles/GNUstep.sh" >> ~/.bashrc
# 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-1.8.1"
# Build GNUstep make second time
echo -e "\n\n"
echo -e "${GREEN}Building GNUstep-make for the second time...${NC}"
cd ../../make
./configure --enable-debug-by-default --with-layout=gnustep --enable-objc-nonfragile-abi --enable-objc-arc
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 ../base/
./configure
make -j8
sudo -E make install
showPrompt
# Build GNUstep GUI
echo -e "\n\n"
echo -e "${GREEN} Building GNUstep-gui...${NC}"
cd ../gui
./configure
make -j8
sudo -E make install
showPrompt
# Build GNUstep back
echo -e "\n\n"
echo -e "${GREEN}Building GNUstep-back...${NC}"
cd ../back
./configure
make -j8
sudo -E make install
showPrompt
. /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
echo -e "\n\n"
echo -e "${GREEN}Install is done. Open a new terminal to start using.${NC}"
Re和代碼塊「@property語法之前」,我的記憶是不完美這一點,但加入在實現部分高德的聲明大約與宣佈的財產同時發生,我相信它與/依賴於非脆弱性的變化。 –
@JoshCaswell我認爲你是對的 - 現在改變。 –