Skip to content

Commit bfd8c38

Browse files
committed
Add support for building with ClangCL on Windows
Since ClangCL is compatible with MSVC this should get us almost there. Ref: https://clang.llvm.org/docs/MSVCCompatibility.html
1 parent 3f10651 commit bfd8c38

File tree

12 files changed

+1993
-60
lines changed

12 files changed

+1993
-60
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,28 @@ jobs:
249249
run: |
250250
make test
251251
252+
windows-clang:
253+
runs-on: windows-latest
254+
steps:
255+
- uses: actions/checkout@v3
256+
- name: build
257+
run: |
258+
cmake -B build -G "Visual Studio 17 2022" -T ClangCL
259+
cmake --build build --target qjs_exe
260+
- name: stats
261+
run: |
262+
cmd /r build\Debug\qjs.exe -qd
263+
- name: test
264+
run: |
265+
cmd /r build\Debug\qjs.exe tests\test_bigint.js
266+
cmd /r build\Debug\qjs.exe tests\test_closure.js
267+
cmd /r build\Debug\qjs.exe tests\test_language.js
268+
cmd /r build\Debug\qjs.exe tests\test_builtin.js
269+
cmd /r build\Debug\qjs.exe tests\test_loop.js
270+
cmd /r build\Debug\qjs.exe tests\test_std.js
271+
cmd /r build\Debug\qjs.exe tests\test_worker.js
272+
cmd /r build\Debug\qjs.exe tests\test_queue_microtask.js
273+
252274
windows-mingw:
253275
runs-on: windows-latest
254276
strategy:

CMakeLists.txt

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ macro(xcheck_add_c_compiler_flag FLAG)
3030
endmacro()
3131

3232
xcheck_add_c_compiler_flag(-Wall)
33-
xcheck_add_c_compiler_flag(-Werror)
34-
xcheck_add_c_compiler_flag(-Wextra)
33+
if(NOT MSVC)
34+
xcheck_add_c_compiler_flag(-Werror)
35+
xcheck_add_c_compiler_flag(-Wextra)
36+
endif()
3537
xcheck_add_c_compiler_flag(-Wno-implicit-fallthrough)
3638
xcheck_add_c_compiler_flag(-Wno-sign-compare)
3739
xcheck_add_c_compiler_flag(-Wno-missing-field-initializers)
@@ -42,6 +44,19 @@ xcheck_add_c_compiler_flag(-Wno-array-bounds)
4244
xcheck_add_c_compiler_flag(-Wno-format-truncation)
4345
xcheck_add_c_compiler_flag(-funsigned-char)
4446

47+
# ClangCL is command line compatible with MSVC, so 'MSVC' is set.
48+
if(MSVC)
49+
xcheck_add_c_compiler_flag(-Wno-unsafe-buffer-usage)
50+
xcheck_add_c_compiler_flag(-Wno-sign-conversion)
51+
xcheck_add_c_compiler_flag(-Wno-nonportable-system-include-path)
52+
xcheck_add_c_compiler_flag(-Wno-implicit-int-conversion)
53+
xcheck_add_c_compiler_flag(-Wno-shorten-64-to-32)
54+
xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier)
55+
xcheck_add_c_compiler_flag(-Wno-reserved-identifier)
56+
xcheck_add_c_compiler_flag(-Wdeprecated-declarations)
57+
add_compile_definitions(WIN32_LEAN_AND_MEAN)
58+
endif()
59+
4560
if(CMAKE_BUILD_TYPE MATCHES "Debug")
4661
add_compile_options(-O0)
4762
xcheck_add_c_compiler_flag(-ggdb)
@@ -130,12 +145,12 @@ if(BUILD_QJS_LIBC)
130145
list(APPEND qjs_sources quickjs-libc.c)
131146
endif()
132147
list(APPEND qjs_defines _GNU_SOURCE)
133-
list(APPEND qjs_libs qjs m)
148+
list(APPEND qjs_libs qjs)
134149
if(NOT WIN32)
135150
list(APPEND qjs_libs dl)
136151
endif()
137152
if(NOT MSVC)
138-
list(APPEND qjs_libs pthread)
153+
list(APPEND qjs_libs m pthread)
139154
endif()
140155

141156
add_library(qjs ${qjs_sources})
@@ -167,7 +182,7 @@ target_link_libraries(qjsc ${qjs_libs})
167182

168183
add_custom_command(
169184
OUTPUT repl.c
170-
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/qjsc" -o ./repl.c -m ${CMAKE_CURRENT_SOURCE_DIR}/repl.js
185+
COMMAND qjsc -o ./repl.c -m ${CMAKE_CURRENT_SOURCE_DIR}/repl.js
171186
DEPENDS qjsc
172187
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
173188
COMMENT "Compile repl.js to bytecode"
@@ -190,21 +205,23 @@ if(BUILD_STATIC_QJS_EXE OR MINGW)
190205
target_link_options(qjs_exe PRIVATE -static-libgcc)
191206
endif()
192207
endif()
193-
if(NOT MINGW)
208+
if(NOT WIN32)
194209
set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE)
195210
endif()
196211

197212

198213
# Test262 runner
199214
#
200215

201-
add_executable(run-test262
202-
quickjs-libc.c
203-
run-test262.c
204-
)
205-
target_compile_definitions(run-test262 PRIVATE ${qjs_defines})
206-
target_link_libraries(run-test262 ${qjs_libs})
207-
216+
# run-test262 uses pthreads.
217+
if(NOT WIN32)
218+
add_executable(run-test262
219+
quickjs-libc.c
220+
run-test262.c
221+
)
222+
target_compile_definitions(run-test262 PRIVATE ${qjs_defines})
223+
target_link_libraries(run-test262 ${qjs_libs})
224+
endif()
208225

209226
# Unicode generator
210227
#
@@ -220,10 +237,10 @@ target_compile_definitions(unicode_gen PRIVATE ${qjs_defines})
220237
# Examples
221238
#
222239

223-
if(BUILD_EXAMPLES AND NOT MINGW)
240+
if(BUILD_EXAMPLES AND NOT WIN32)
224241
add_custom_command(
225242
OUTPUT hello.c
226-
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/qjsc" -e -o hello.c ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
243+
COMMAND qjsc -e -o hello.c ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
227244
DEPENDS qjsc
228245
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
229246
COMMENT "Compile hello.js to a C file with bytecode embeddee"
@@ -239,7 +256,7 @@ if(BUILD_EXAMPLES AND NOT MINGW)
239256

240257
add_custom_command(
241258
OUTPUT hello_module.c
242-
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/qjsc" -e -o hello_module.c -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
259+
COMMAND qjsc -e -o hello_module.c -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
243260
DEPENDS qjsc
244261
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
245262
COMMENT "Compile hello_module.js to a C file with bytecode embeddee"
@@ -253,7 +270,7 @@ if(BUILD_EXAMPLES AND NOT MINGW)
253270
target_compile_definitions(hello_module PRIVATE ${qjs_defines})
254271
target_link_libraries(hello_module ${qjs_libs})
255272

256-
if(NOT MINGW)
273+
if(NOT WIN32)
257274
add_library(fib MODULE examples/fib.c)
258275
set_target_properties(fib PROPERTIES
259276
PREFIX ""
@@ -287,7 +304,7 @@ if(BUILD_EXAMPLES AND NOT MINGW)
287304

288305
add_custom_command(
289306
OUTPUT test_fib.c
290-
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/qjsc" -e -o test_fib.c -M ${CMAKE_CURRENT_SOURCE_DIR}/examples/fib.so,fib -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/test_fib.js
307+
COMMAND qjsc -e -o test_fib.c -M ${CMAKE_CURRENT_SOURCE_DIR}/examples/fib.so,fib -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/test_fib.js
291308
DEPENDS qjsc
292309
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
293310
COMMENT "Compile test_fib.js to a C file with bytecode embedded"

cutils.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,15 @@
2222
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323
* THE SOFTWARE.
2424
*/
25+
#include <assert.h>
2526
#include <stdlib.h>
2627
#include <stdio.h>
2728
#include <stdarg.h>
2829
#include <string.h>
30+
#include <time.h>
31+
#if !defined(_MSC_VER)
32+
#include <sys/time.h>
33+
#endif
2934

3035
#include "cutils.h"
3136

@@ -606,4 +611,67 @@ void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
606611
}
607612
}
608613

614+
#if defined(_MSC_VER)
615+
// From: https://stackoverflow.com/a/26085827
616+
static int gettimeofday_msvc(struct timeval *tp, struct timezone *tzp)
617+
{
618+
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
619+
620+
SYSTEMTIME system_time;
621+
FILETIME file_time;
622+
uint64_t time;
623+
624+
GetSystemTime(&system_time);
625+
SystemTimeToFileTime(&system_time, &file_time);
626+
time = ((uint64_t)file_time.dwLowDateTime);
627+
time += ((uint64_t)file_time.dwHighDateTime) << 32;
628+
629+
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
630+
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
631+
632+
return 0;
633+
}
634+
635+
uint64_t js__hrtime_ns(void) {
636+
LARGE_INTEGER counter, frequency;
637+
double scaled_freq;
638+
double result;
639+
640+
if (!QueryPerformanceFrequency(&frequency))
641+
abort();
642+
assert(frequency.QuadPart != 0);
643+
644+
if (!QueryPerformanceCounter(&counter))
645+
abort();
646+
assert(counter.QuadPart != 0);
647+
648+
/* Because we have no guarantee about the order of magnitude of the
649+
* performance counter interval, integer math could cause this computation
650+
* to overflow. Therefore we resort to floating point math.
651+
*/
652+
scaled_freq = (double) frequency.QuadPart / 1e9;
653+
result = (double) counter.QuadPart / scaled_freq;
654+
return (uint64_t) result;
655+
}
656+
#else
657+
uint64_t js__hrtime_ns(void) {
658+
struct timespec t;
659+
660+
if (clock_gettime(CLOCK_MONOTONIC, &t))
661+
abort();
662+
663+
return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec;
664+
}
665+
#endif
666+
667+
int64_t js__gettimeofday_us(void) {
668+
struct timeval tv;
669+
#if defined(_MSC_VER)
670+
gettimeofday_msvc(&tv, NULL);
671+
#else
672+
gettimeofday(&tv, NULL);
673+
#endif
674+
return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
675+
}
676+
609677
#pragma GCC visibility pop

cutils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
/* set if CPU is big endian */
3232
#undef WORDS_BIGENDIAN
3333

34+
#if defined(_MSC_VER)
35+
#include <windows.h>
36+
#include <winsock2.h>
37+
#include <malloc.h>
38+
#define alloca _alloca
39+
#define ssize_t ptrdiff_t
40+
#endif
41+
3442
#define likely(x) __builtin_expect(!!(x), 1)
3543
#define unlikely(x) __builtin_expect(!!(x), 0)
3644
#define force_inline inline __attribute__((always_inline))
@@ -320,4 +328,7 @@ void rqsort(void *base, size_t nmemb, size_t size,
320328
int (*cmp)(const void *, const void *, void *),
321329
void *arg);
322330

331+
int64_t js__gettimeofday_us(void);
332+
uint64_t js__hrtime_ns(void);
333+
323334
#endif /* CUTILS_H */

0 commit comments

Comments
 (0)