Skip to content

Commit 934cd13

Browse files
committed
Initial pass at Windows support.
All tests now pass with the new ABI on x86-64, with the new ABI. Some of the code is ugly and other platforms are probably broken.
1 parent f352f62 commit 934cd13

33 files changed

+522
-200
lines changed

CMakeLists.txt

+81-46
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
cmake_minimum_required(VERSION 3.1)
22

3-
project(libobjc)
4-
enable_language(ASM)
3+
project(libobjc C ASM CXX)
54

65
INCLUDE (CheckCXXSourceCompiles)
76

@@ -10,13 +9,15 @@ macro(install_symlink filepath sympath)
109
install(CODE "message(\"-- Symlinking: ${sympath} -> ${filepath}\")")
1110
endmacro(install_symlink)
1211

13-
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -fno-inline ${CMAKE_C_FLAGS_DEBUG}")
12+
set(CMAKE_C_FLAGS_DEBUG "/Z7 -O0 -Xclang -fno-inline ${CMAKE_C_FLAGS_DEBUG}")
13+
set(CMAKE_SHARED_LINKER_FLAGS "/DEBUG /INCREMENTAL:NO ${CMAKE_SHARED_LINKER_FLAGS}")
1414
set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}")
15-
set(CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")
15+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
1616

1717
set(libobjc_VERSION 4.6)
1818

19-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions")
19+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /EHas -Xclang -fexceptions -Xclang -fobjc-exceptions")
20+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHas")
2021
# Build configuration
2122
add_definitions( -DGNUSTEP -D__OBJC_RUNTIME_INTERNAL__=1)
2223

@@ -37,7 +38,6 @@ set(libobjc_C_SRCS
3738
category_loader.c
3839
class_table.c
3940
dtable.c
40-
eh_personality.c
4141
encoding2.c
4242
hooks.c
4343
ivar.c
@@ -68,10 +68,16 @@ set(libobjc_HDRS
6868
objc/objc.h
6969
objc/runtime-deprecated.h
7070
objc/runtime.h
71-
objc/slot.h
72-
)
71+
objc/slot.h)
72+
73+
# Windows does not use DWARF EH
74+
if (WIN32)
75+
list(APPEND libobjc_CXX_SRCS eh_win32_msvc.cc)
76+
else ()
77+
list(APPEND libobjc_C_SRCS eh_personality.c)
78+
set(libobjcxx_CXX_SRCS objcxx_eh.cc)
79+
endif (WIN32)
7380

74-
set(libobjcxx_CXX_SRCS objcxx_eh.cc)
7581

7682
# For release builds, we disable spamming the terminal with warnings about
7783
# selector type mismatches
@@ -154,10 +160,26 @@ endif ()
154160

155161
set(INSTALL_TARGETS objc)
156162

163+
# On Windows, CMake adds /TC to the clang-cl flags and doesn't provide a way to
164+
# tell it not to. We fix this by telling clang do disregard that option,
165+
# unconditionally (which means that it still defaults to C for .c files).
166+
set(ENV{CCC_OVERRIDE_OPTIONS} "x/TC x/Gm-")
167+
168+
set_source_files_properties(
169+
${libobjc_ASM_SRCS}
170+
LANGUAGE C
171+
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS} -Xclang -x -Xclang assembler-with-cpp"
172+
)
173+
174+
set_source_files_properties(
175+
${libobjc_CXX_SRCS}
176+
LANGUAGE CXX
177+
COMPILE_FLAGS "${CMAKE_CXX_FLAGS}"
178+
)
179+
157180
set_source_files_properties(
158181
${libobjc_OBJC_SRCS}
159-
PROPERTIES LANGUAGE C
160-
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS}"
182+
COMPILE_FLAGS "${CMAKE_OBJC_FLAGS} -Xclang -x -Xclang objective-c"
161183
)
162184

163185
#
@@ -186,40 +208,55 @@ set(ENABLE_OBJCXX true CACHE BOOL
186208

187209
set(CXXRT_IS_STDLIB false)
188210

189-
add_library(objc SHARED ${libobjc_C_SRCS} ${libobjc_ASM_SRCS} ${libobjc_OBJC_SRCS})
211+
add_custom_command(OUTPUT block_trampolines.obj
212+
COMMAND ${CMAKE_C_COMPILER} -c "${CMAKE_SOURCE_DIR}/block_trampolines.S" -o "${CMAKE_BINARY_DIR}/block_trampolines.obj"
213+
MAIN_DEPENDENCY block_trampolines.S
214+
)
215+
add_custom_command(OUTPUT objc_msgSend.obj
216+
COMMAND ${CMAKE_C_COMPILER} -c "${CMAKE_SOURCE_DIR}/objc_msgSend.S" -o "${CMAKE_BINARY_DIR}/objc_msgSend.obj"
217+
MAIN_DEPENDENCY objc_msgSend.S
218+
DEPENDS objc_msgSend.aarch64.S objc_msgSend.arm.S objc_msgSend.mips.S objc_msgSend.x86-32.S objc_msgSend.x86-64.S
219+
)
220+
221+
222+
add_library(objc SHARED ${libobjc_C_SRCS} ${libobjc_ASM_SRCS} ${libobjc_OBJC_SRCS} block_trampolines.obj objc_msgSend.obj)
190223

191224
if (ENABLE_OBJCXX)
192-
message(STATUS "Testing C++ interop")
193-
# Try to find libcxxrt.so. We can link to this to provide the C++ ABI
194-
# layer, if it exists.
195-
test_cxx(cxxrt false)
196-
# If it doesn't, then look for GNU libsupc++.so instead (either works,
197-
# they're ABI compatible).
198-
if (NOT CXX_RUNTIME)
199-
test_cxx(supc++ false)
200-
endif (NOT CXX_RUNTIME)
201-
if (NOT CXX_RUNTIME)
202-
test_cxx(c++abi false)
203-
endif (NOT CXX_RUNTIME)
204-
205-
# If we have a C++ ABI library, then we can produce a single libobjc that
206-
# works for Objective-C and Objective-C++. If not, then we need to provide
207-
# a separate libobjcxx.
208-
if (CXX_RUNTIME)
209-
message(STATUS "Using ${CXX_RUNTIME} as the C++ runtime library")
210-
else()
211-
message(STATUS "Testing C++ standard library")
212-
try_compile(USERUNTIME
213-
"${CMAKE_BINARY_DIR}/CMake"
214-
"${CMAKE_SOURCE_DIR}/CMake"
215-
test_cxx_runtime)
216-
if (${USERUNTIME})
217-
message(STATUS "libobjc will depend on C++ standard library")
218-
set(CXXRT_IS_STDLIB true)
225+
if (WIN32)
226+
message(STATUS "Using MSVC-compatible exception model")
227+
else ()
228+
message(STATUS "Testing C++ interop")
229+
# Try to find libcxxrt.so. We can link to this to provide the C++ ABI
230+
# layer, if it exists.
231+
test_cxx(cxxrt false)
232+
# If it doesn't, then look for GNU libsupc++.so instead (either works,
233+
# they're ABI compatible).
234+
if (NOT CXX_RUNTIME)
235+
test_cxx(supc++ false)
236+
endif (NOT CXX_RUNTIME)
237+
if (NOT CXX_RUNTIME)
238+
test_cxx(c++abi false)
239+
endif (NOT CXX_RUNTIME)
240+
241+
# If we have a C++ ABI library, then we can produce a single libobjc that
242+
# works for Objective-C and Objective-C++. If not, then we need to provide
243+
# a separate libobjcxx.
244+
if (CXX_RUNTIME)
245+
message(STATUS "Using ${CXX_RUNTIME} as the C++ runtime library")
219246
else()
220-
message(STATUS "No useable C++ runtime found")
221-
set(ENABLE_OBJCXX false)
222-
endif()
247+
message(STATUS "Testing C++ standard library")
248+
try_compile(USERUNTIME
249+
"${CMAKE_BINARY_DIR}/CMake"
250+
"${CMAKE_SOURCE_DIR}/CMake"
251+
test_cxx_runtime)
252+
if (${USERUNTIME})
253+
message(STATUS "libobjc will depend on C++ standard library")
254+
set(CXXRT_IS_STDLIB true)
255+
else()
256+
message(STATUS "No useable C++ runtime found")
257+
set(ENABLE_OBJCXX false)
258+
endif()
259+
endif ()
223260
endif ()
224261
endif (ENABLE_OBJCXX)
225262

@@ -231,8 +268,8 @@ if (ENABLE_OBJCXX)
231268
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
232269
target_link_libraries(objc ${CXX_RUNTIME})
233270
endif()
234-
set(libobjc_CXX_SRCS ${libobjcxx_CXX_SRCS})
235-
target_sources(objc PRIVATE ${libobjcxx_CXX_SRCS})
271+
list(APPEND libobjc_CXX_SRCS ${libobjcxx_CXX_SRCS})
272+
target_sources(objc PRIVATE ${libobjc_CXX_SRCS})
236273
endif()
237274

238275

@@ -264,8 +301,6 @@ if (BUILD_STATIC_LIBOBJC)
264301
list(APPEND INSTALL_TARGETS objc-static)
265302
endif ()
266303

267-
268-
269304
# Explicitly link libgc if we are compiling with gc support.
270305
if (LIBGC)
271306
target_link_libraries(objc ${LIBGC})

NSBlocks.m

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#import "objc/runtime.h"
2-
#import "class.h"
3-
#import "loader.h"
4-
#import "lock.h"
5-
#import "objc/blocks_runtime.h"
6-
#import "dtable.h"
1+
#include "objc/runtime.h"
2+
#include "class.h"
3+
#include "loader.h"
4+
#include "lock.h"
5+
#include "objc/blocks_runtime.h"
6+
#include "dtable.h"
77
#include <assert.h>
88

9-
struct objc_class _NSConcreteGlobalBlock;
10-
struct objc_class _NSConcreteStackBlock;
11-
struct objc_class _NSConcreteMallocBlock;
9+
PUBLIC struct objc_class _NSConcreteGlobalBlock;
10+
PUBLIC struct objc_class _NSConcreteStackBlock;
11+
PUBLIC struct objc_class _NSConcreteMallocBlock;
1212

1313
static struct objc_class _NSConcreteGlobalBlockMeta;
1414
static struct objc_class _NSConcreteStackBlockMeta;
@@ -40,6 +40,7 @@ static void createNSBlockSubclass(Class superclass, Class newClass,
4040
#define NEW_CLASS(super, sub) \
4141
createNSBlockSubclass(super, &sub, &sub ## Meta, #sub)
4242

43+
PUBLIC
4344
BOOL objc_create_block_classes_as_subclasses_of(Class super)
4445
{
4546
if (_NSBlock.super_class != NULL) { return NO; }

Test/CMakeLists.txt

+24-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
# the installed version
44

55

6+
# On Windows, CMake adds /TC to the clang-cl flags and doesn't provide a way to
7+
# tell it not to. We fix this by telling clang do disregard that option,
8+
# unconditionally (which means that it still defaults to C for .c files).
9+
set(ENV{CCC_OVERRIDE_OPTIONS} "x/TC x/TP")
10+
set(INCREMENTAL " ")
11+
if (MSVC)
12+
set(CMAKE_EXE_LINKER_FLAGS "/DEBUG /INCREMENTAL:NO ${CMAKE_EXE_LINKER_FLAGS}")
13+
set(INCREMENTAL "/INCREMENTAL:NO")
14+
endif ()
15+
616
# List of single-file tests.
717
set(TESTS
818
alias.m
@@ -14,10 +24,8 @@ set(TESTS
1424
BlockImpTest.m
1525
BlockTest_arc.m
1626
ConstantString.m
17-
BoxedForeignException.m
1827
Category.m
1928
ExceptionTest.m
20-
ForeignException.m
2129
Forward.m
2230
ManyManySelectors.m
2331
NestedExceptions.m
@@ -43,24 +51,33 @@ set(TESTS
4351
setSuperclass.m
4452
)
4553

54+
if (WIN32)
55+
else ()
56+
list(APPEND TESTS
57+
BoxedForeignException.m
58+
ForeignException.m
59+
)
60+
endif ()
61+
4662
# List of single-file tests that won't work with the legacy ABI and so
4763
# shouldn't be run in legacy mode.
4864
set(NEW_TESTS
4965
category_properties.m
5066
)
5167

68+
remove_definitions(-D__OBJC_RUNTIME_INTERNAL__=1)
5269

5370
add_library(test_runtime_legacy OBJECT Test.m)
5471
set_target_properties(test_runtime_legacy PROPERTIES
5572
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
56-
COMPILE_FLAGS "-fblocks -fobjc-runtime=gnustep-1.7"
73+
COMPILE_FLAGS "-Xclang -fblocks -fobjc-runtime=gnustep-1.7"
5774
LINKER_LANGUAGE C
5875
)
5976

6077
add_library(test_runtime OBJECT Test.m)
6178
set_target_properties(test_runtime PROPERTIES
6279
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
63-
COMPILE_FLAGS "-fblocks -fobjc-runtime=gnustep-2.0"
80+
COMPILE_FLAGS "-Xclang -fblocks -fobjc-runtime=gnustep-2.0"
6481
LINKER_LANGUAGE C
6582
)
6683

@@ -71,14 +88,14 @@ function(addtest_flags TEST_NAME FLAGS TEST_SOURCE)
7188
if (${TEST_NAME} MATCHES ".*_arc")
7289
# Only compile the main file with ARC
7390
set_source_files_properties(${TEST_SOURCE}
74-
COMPILE_FLAGS "-fobjc-arc")
91+
COMPILE_FLAGS "-Xclang -fobjc-arc")
7592
endif()
7693
add_executable(${TEST_NAME} ${TEST_SOURCE})
7794
add_test(${TEST_NAME} ${TEST_NAME})
7895
set(ARC "")
7996
set_target_properties(${TEST_NAME} PROPERTIES
8097
INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
81-
COMPILE_FLAGS "-fblocks ${FLAGS}"
98+
COMPILE_FLAGS "-Xclang -fblocks ${FLAGS}"
8299
LINKER_LANGUAGE C
83100
)
84101
set_property(TEST ${TEST_NAME} PROPERTY
@@ -114,5 +131,5 @@ endforeach()
114131
addtest_variants("CXXExceptions" "CXXException.m;CXXException.cc" true)
115132
addtest_variants("ForwardDeclareProtocolAccess" "ForwardDeclareProtocolAccess.m;ForwardDeclareProtocol.m" true)
116133
if (ENABLE_OBJCXX)
117-
addtest_variants(ObjCXXEHInterop "ObjCXXEHInterop.mm;ObjCXXEHInterop.m" true)
134+
addtest_variants(ObjCXXEHInterop "ObjCXXEHInterop.mm;ObjCXXEHInterop.m" true)
118135
endif()

Test/ManyManySelectors.m

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#include <string.h>
55

66
#include <sys/types.h>
7-
#include <sys/time.h>
8-
#include <sys/resource.h>
97

108

119
static BOOL methodCalled = NO;

Test/NestedExceptions.m

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int main(void)
2626
assert(x == e1);
2727
@try {
2828
a = e2;
29+
@throw a;
2930
}
3031
@catch (id y)
3132
{

Test/PropertyAttributeTest.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ int main()
3939
assert(strcmp(property_getAttributes(property), "Ti,VvarName") == 0);
4040
free(properties);
4141

42-
objc_property_t *clsproperties = class_copyPropertyList(object_getClass([helloclass class]), &outCount);
42+
properties = class_copyPropertyList(object_getClass([helloclass class]), &outCount);
4343
assert(outCount == 1);
4444
property = properties[0];
4545
assert(strcmp(property_getName(property), "clsProp") == 0);

Test/RuntimeTest.m

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
#include "Test.h"
22
#include <stdio.h>
33
#include <string.h>
4-
#include <unistd.h>
4+
#ifdef _WIN32
5+
# define sleep Sleep
6+
#else
7+
# include <unistd.h>
8+
#endif
59

610
static int exitStatus = 0;
711

@@ -125,10 +129,11 @@ - (BOOL) basicThrowAndCatchException
125129
@catch (id e)
126130
{
127131
test(e == exceptionObj);
132+
return YES;
128133
}
129-
@finally
134+
@catch(...)
130135
{
131-
return YES;
136+
return NO;
132137
}
133138
return NO;
134139
}

Test/objc_msgSend.m

+5-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
//#define assert(x) if (!(x)) { printf("Failed %d\n", __LINE__); }
1212

13-
id objc_msgSend(id, SEL, ...);
1413

1514
typedef struct { int a,b,c,d,e; } s;
1615
@interface Fake
@@ -81,13 +80,14 @@ - (s)sret
8180
+ (void)printf: (const char*)str, ...
8281
{
8382
va_list ap;
84-
char *s;
83+
char s[100];
8584

8685
va_start(ap, str);
8786

88-
vasprintf(&s, str, ap);
87+
vsnprintf(&s, 100, str, ap);
8988
va_end(ap);
90-
//fprintf(stderr, "String: '%s'\n", s);
89+
fprintf(stderr, "String: '%s'\n", s);
90+
vfprintf(stderr, s, ap);
9191
assert(strcmp(s, "Format string 42 42.000000\n") ==0);
9292
}
9393
+ (void)initialize
@@ -174,6 +174,7 @@ IMP forward(id o, SEL s)
174174
}
175175

176176

177+
177178
int main(void)
178179
{
179180
__objc_msg_forward2 = forward;

0 commit comments

Comments
 (0)