Objective-C on Windows using Clang and GNUstep.
This project comprises a collection of scripts to build a modern GNUstep toolchain for x64 or arm64 architectures using the Visual Studio toolchain and LLVM/Clang. The toolchain supports Objective-C 2.0 features like blocks and Automatic Reference Counting (ARC) and can be used to integrate Objective-C code in any native Windows app — including Visual Studio projects — using LLVM/Clang (without using MinGW).
The toolchain consists of the following libraries:
To install a pre-built release, download it from the releases on GitHub and unpack it into into C:\GNUstep
(this location is only required if you plan on using the gnustep-config
script, otherwise any location will work).
You should end up with the folders C:\GNUstep\x64\Debug
and C:\GNUstep\x64\Release
when using the x64 toolchain. The explanations below and the example project assume this installation location.
You also need a standard Windows release of Clang 16 or later, e.g. installed via WinGet (winget install LLVM.LLVM
) or the latest official release (download "LLVM-x.y.z-win64.exe" for x86_64 or "LLVM-x.y.z-woa64.exe" for ARM64). The explanations below expect that Clang is available in your PATH. Note that using Clang from MSYS2/MinGW packages is not supported as they contain MinGW-specific patches.
Building and linking Objective-C code using the toolchain and Clang requires a number of compiler and linker flags.
When building in a Bash environment (like an MSYS2 shell), the gnustep-config
tool can be used to query the necessary flags for building and linking:
# add gnustep-config directory to PATH (use Debug or Release version)
export PATH="$PATH:/c/GNUstep/x64/Debug/bin/"
# build test.m to produce an object file test.o
clang `gnustep-config --objc-flags` -c test.m
# link object file into executable
clang `gnustep-config --base-libs` -ldispatch -o test.exe test.o
Alternatively, clang-cl.exe
can be used to build Objective-C code directly in a Visual Studio environment like the "x64 Native Tools Command Prompt". Note that this requires prefixing some of the required compiler flags with -Xclang
to pass them directly to Clang:
# build test.m to produce an object file test.obj
clang-cl -I C:\GNUstep\x64\Debug\include -fobjc-runtime=gnustep-2.0 -Xclang -fexceptions -Xclang -fobjc-exceptions -fblocks -DGNUSTEP -DGNUSTEP_WITH_DLL -DGNUSTEP_RUNTIME=1 -D_NONFRAGILE_ABI=1 -D_NATIVE_OBJC_EXCEPTIONS /MDd /Z7 /c test.m
# link object file into executable using the LLD linker
clang-cl test.obj gnustep-base.lib objc.lib dispatch.lib -fuse-ld=lld /MDd /Z7 -o test.exe /link /LIBPATH:C:\GNUstep\x64\Debug\lib
Specify /MDd
for debug builds, and /MD
for release builds, in order to link against the same runtime libraries as the DLLs in C:\GNUstep\x64\Debug
and C:\GNUstep\x64\Release
respectively. Adding /Z7
adds full debug symbols.
Note that the GNUSTEP_WITH_DLL
definition is always required to enable annotation of the Objective-C objects defined in the GNUstep Base DLL with __declspec(dllexport)
.
The examples/ObjCWin32 folder contains a Visual Studio project that is set up with support for Objective-C.
Following are instructions to set up your own project, or add Objective-C support to an existing Win32 Visual Studio project.
Launch Visual Studio, select "Create a new project", and select a project template that is compatible with C++/Win32, e.g. Console App, Windows Desktop Application, Static Library, Dynamic-Link Library (DLL). In the following we assume we are building a Console App.
Choose a name for the project and create the project. In this example, we choose ObjCHello.
C:\GNUstep\$(LibrariesArchitecture)\$(Configuration)\include
C:\GNUstep\$(LibrariesArchitecture)\$(Configuration)\lib
GNUSTEP;GNUSTEP_WITH_DLL;GNUSTEP_RUNTIME=1;_NONFRAGILE_ABI=1;_NATIVE_OBJC_EXCEPTIONS
-fobjc-runtime=gnustep-2.0 -Xclang -fexceptions -Xclang -fobjc-exceptions -fblocks -Xclang -fobjc-arc
-Xclang -fobjc-arc
) if you don't want to use Automatic Reference Counting (ARC).gnustep-base.lib;objc.lib;dispatch.lib
</Project>
add the following to copy the GNUstep DLLs to the output directory.
<ItemGroup>
<Content Include="C:\GNUstep\$(LibrariesArchitecture)\$(Configuration)\bin\*.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</Content>
</ItemGroup>
ObjCHello.cpp
source file and rename it to ObjCHello.m
(or ObjCHello.mm
for Objective-C++)./TC
//TP
flags that otherwise cause the file to be built as C/C++ irrespective of its extension).Now you can start writing your Objective-C code in the ObjCHello.m
file. You can test the setup by replacing the content of the file with:
#include <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSLog(@"Hello Objective-C");
return 0;
}
Place a breakpoint at the line NSLog(@"Hello Objective-C");
and run from Visual Studio. You should see the breakpoint getting hit, and the log printed in the "Output" panel when you continue.
Older Clang releases had various issues with Objective-C code on Windows, most of which were fixed with Clang 16. It is therefore highly recommended to use Clang 16 or later.
@finally
crashing Clang (issue 1 and 2, not fixed)Support for x86 is broken due to a build error in libdispatch.
The compilation will fail if the Windows home folder contains whitespace, e.g. C:\Users\John Appleseed
.
When utilizing the built-in gnustep-make test suite's debug capabilities, the preferred debugger on Windows is LLDB. LLDB from the Chocolatey package manager links to python310.dll
, but is not found if Python 3.10.x is not installed and added to PATH. The error message is obscure and doesn't mention the missing dependency. Install Python3 manually using the official Python Installer. After downloading and executing the installer, select Add to PATH
and proceed with the installation. You can now use the LLDB debugger.
'Foundation/Foundation.h' file not found
Please ensure that you correctly set "Include Directories".
#import of type library is an unsupported Microsoft feature
Please ensure that you have cleared the "Compile As" property of the file.
cannot open input file 'gnustep-base.lib'
Please ensure that you correctly set "Library Directories".
unresolved external symbol __objc_load referenced in function .objcv2_load_function
Please ensure that you added the required linking options in Linker > Input > Additional Dependencies.
relocation against symbol in discarded section: __start_.objcrt$SEL
Please ensure that you include some Objective-C code in your project. This is currently required due to a compiler/linker issue when using the LLD linker.
The code execution cannot proceed because gnustep-base-1_28.dll was not found. Reinstalling the program may fix this problem.
Please ensure that DLLs are copied to the output folder.
Objective-C categories are not found at runtime
Linking static libraries containing Objective-C categories into an executable or shared library will strip the categories during the linking process. This can be worked around by linking with the WHOLEARCHIVE
linker option (e.g. /WHOLEARCHIVE:MyStaticLibrary.lib
), or by directly linking the object files from the library (e.g. by using "object libraries" when using CMake).
Building the toolchain require the following tools to be installed and available in the PATH. Their presence is verified when building the toolchain.
The MSYS2 installation is required to provide the Bash shell and Unix tools required to build some of the libraries, but no MinGW packages are needed. The Windows Clang installation is used to build all libraries.
Windows tools
winget install LLVM.LLVM
)winget install Kitware.CMake
)winget install Git.Git
)winget install Ninja-build.Ninja
)winget install MSYS2.MSYS2
)winget install NASM.NASM
)Unix tools
These can be installed via Pacman inside a MSYS2 shell:
pacman -S --needed make autoconf automake libtool pkg-config
Please make sure that you do not have gmake
installed in your MSYS2 environment, as it is not compatible but will be picked up by the project Makefiles. Running which gmake
in MSYS2 should print "which: no gmake in ...".
Run the build.bat script in a x86, x64, or arm64 Native Tools Command Prompt from Visual Studio to build the toolchain for x86/x64/arm64.
Usage: build.bat
--prefix INSTALL_ROOT Install toolchain into given directory (default: C:\GNUstep)
--type Debug/Release Build only the given build type (default: both)
--only PHASE Re-build only the given phase (e.g. "gnustep-base")
--only-dependencies Build only GNUstep dependencies
--patches DIR Apply additional patches from given directory
-h, --help, /? Print usage information and exit
For each of the libraries, the script automatically downloads the source via Git into the src
subdirectory, builds, and installs it.
The toolchain is installed into C:\GNUstep\[x86|x64|arm64]\[Debug|Release]
.