/ CMakeLists.txt
CMakeLists.txt
   1  cmake_minimum_required(VERSION 3.15)
   2  project(ProgrammingBenchmark)
   3  
   4  set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
   5  
   6  # Set output directory for binaries
   7  set(BIN_DIR ${CMAKE_SOURCE_DIR}/bin)
   8  file(MAKE_DIRECTORY ${BIN_DIR})
   9  
  10  # Hyperfine build target
  11  set(HYPERFINE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/hyperfine)
  12  set(HYPERFINE_BINARY ${HYPERFINE_SOURCE_DIR}/target/release/hyperfine)
  13  set(HYPERFINE_OUTPUT ${BIN_DIR}/hyperfine)
  14  
  15  # Check for cargo
  16  find_program(CARGO_EXECUTABLE cargo)
  17  if(NOT CARGO_EXECUTABLE)
  18      message(FATAL_ERROR "Cargo not found. Install Rust from https://rustup.rs/")
  19  endif()
  20  
  21  # Custom command to build hyperfine
  22  add_custom_command(
  23      OUTPUT ${HYPERFINE_BINARY}
  24      COMMAND ${CARGO_EXECUTABLE} build --release
  25      WORKING_DIRECTORY ${HYPERFINE_SOURCE_DIR}
  26      COMMENT "Building hyperfine with cargo..."
  27      VERBATIM
  28  )
  29  
  30  # Custom command to copy hyperfine to bin directory
  31  add_custom_command(
  32      OUTPUT ${HYPERFINE_OUTPUT}
  33      COMMAND ${CMAKE_COMMAND} -E copy ${HYPERFINE_BINARY} ${HYPERFINE_OUTPUT}
  34      DEPENDS ${HYPERFINE_BINARY}
  35      COMMENT "Copying hyperfine to ${BIN_DIR}..."
  36      VERBATIM
  37  )
  38  
  39  # Custom target that depends on the copied binary
  40  add_custom_target(hyperfine ALL
  41      DEPENDS ${HYPERFINE_OUTPUT}
  42  )
  43  
  44  # Print build information
  45  message(STATUS "Hyperfine source directory: ${HYPERFINE_SOURCE_DIR}")
  46  message(STATUS "Binary output directory: ${BIN_DIR}")
  47  
  48  # ======================================================================
  49  # Build test programs with multiple compilers
  50  # ======================================================================
  51  
  52  set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/test_src)
  53  set(TEST_BIN_DIR ${CMAKE_SOURCE_DIR}/bin/tests)
  54  
  55  # Detect available compilers
  56  find_program(GCC_EXECUTABLE g++)
  57  find_program(CLANG_EXECUTABLE clang++)
  58  find_program(GCC_C_EXECUTABLE gcc)
  59  find_program(CLANG_C_EXECUTABLE clang)
  60  find_program(NASM_EXECUTABLE nasm)
  61  find_program(YASM_EXECUTABLE yasm)
  62  find_program(GAS_EXECUTABLE as)
  63  find_program(LD_EXECUTABLE ld)
  64  find_program(RUSTC_EXECUTABLE rustc)
  65  find_program(ZIG_EXECUTABLE zig)
  66  find_program(GO_EXECUTABLE go)
  67  find_program(DMD_EXECUTABLE dmd)
  68  find_program(LDC2_EXECUTABLE ldc2)
  69  find_program(GDC_EXECUTABLE gdc)
  70  find_program(NIM_EXECUTABLE nim)
  71  find_program(ODIN_EXECUTABLE odin)
  72  find_program(V_EXECUTABLE v)
  73  find_program(GNAT_EXECUTABLE gnatmake)
  74  find_program(GHC_EXECUTABLE ghc)
  75  find_program(GFORTRAN_EXECUTABLE gfortran)
  76  find_program(FPC_EXECUTABLE fpc)
  77  find_program(COBC_EXECUTABLE cobc)
  78  find_program(CSC_EXECUTABLE csc)
  79  find_program(MCS_EXECUTABLE mcs)
  80  find_program(PYTHON_EXECUTABLE python3)
  81  find_program(CYTHON_EXECUTABLE cython)
  82  find_program(R_EXECUTABLE R)
  83  
  84  # List of compilers to use
  85  set(COMPILERS "")
  86  if(GCC_EXECUTABLE)
  87      list(APPEND COMPILERS "gcc")
  88      message(STATUS "GCC found: ${GCC_EXECUTABLE}")
  89  endif()
  90  if(CLANG_EXECUTABLE)
  91      list(APPEND COMPILERS "clang")
  92      message(STATUS "Clang found: ${CLANG_EXECUTABLE}")
  93  endif()
  94  
  95  if(NOT COMPILERS)
  96      message(FATAL_ERROR "No C++ compilers found (need g++ or clang++)")
  97  endif()
  98  
  99  # C++ Hello World implementations - build with each compiler
 100  set(CPP_IMPLEMENTATIONS 001 002 003 004 005 006)
 101  foreach(COMPILER ${COMPILERS})
 102      # Set compiler executable
 103      if(COMPILER STREQUAL "gcc")
 104          set(COMPILER_EXEC ${GCC_EXECUTABLE})
 105      elseif(COMPILER STREQUAL "clang")
 106          set(COMPILER_EXEC ${CLANG_EXECUTABLE})
 107      endif()
 108      
 109      foreach(IMPL ${CPP_IMPLEMENTATIONS})
 110          set(CPP_SRC ${TEST_SRC_DIR}/cpp/hello_world/${IMPL}/hello.cpp)
 111          set(CPP_BIN ${TEST_BIN_DIR}/${COMPILER}/cpp/hello_world/${IMPL}/hello)
 112          
 113          if(EXISTS ${CPP_SRC})
 114              file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/cpp/hello_world/${IMPL})
 115              
 116              add_custom_command(
 117                  OUTPUT ${CPP_BIN}
 118                  COMMAND ${COMPILER_EXEC} ${CPP_SRC} -o ${CPP_BIN} -O3 -std=c++17
 119                  DEPENDS ${CPP_SRC}
 120                  COMMENT "Building C++ hello_world/${IMPL} with ${COMPILER}..."
 121                  VERBATIM
 122              )
 123              
 124              add_custom_target(${COMPILER}_cpp_hello_${IMPL} ALL DEPENDS ${CPP_BIN})
 125          endif()
 126      endforeach()
 127  endforeach()
 128  
 129  # ASM Hello World 001 - Support multiple assemblers
 130  set(ASSEMBLERS "")
 131  if(NASM_EXECUTABLE)
 132      list(APPEND ASSEMBLERS "nasm")
 133  endif()
 134  if(YASM_EXECUTABLE)
 135      list(APPEND ASSEMBLERS "yasm")
 136  endif()
 137  if(GAS_EXECUTABLE)
 138      list(APPEND ASSEMBLERS "gas")
 139  endif()
 140  
 141  if(ASSEMBLERS AND LD_EXECUTABLE)
 142      foreach(ASSEMBLER ${ASSEMBLERS})
 143          foreach(COMPILER ${COMPILERS})
 144              if(ASSEMBLER STREQUAL "nasm")
 145                  set(ASM_001_SRC ${TEST_SRC_DIR}/asm/hello_world/001/hello.asm)
 146                  set(ASM_001_OBJ ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello.o)
 147                  set(ASM_001_BIN ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello)
 148                  file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001)
 149                  
 150                  add_custom_command(
 151                      OUTPUT ${ASM_001_OBJ}
 152                      COMMAND ${NASM_EXECUTABLE} -f elf64 ${ASM_001_SRC} -o ${ASM_001_OBJ}
 153                      DEPENDS ${ASM_001_SRC}
 154                      COMMENT "Assembling ASM hello_world/001 with NASM for ${COMPILER}..."
 155                      VERBATIM
 156                  )
 157                  
 158                  add_custom_command(
 159                      OUTPUT ${ASM_001_BIN}
 160                      COMMAND ${LD_EXECUTABLE} ${ASM_001_OBJ} -o ${ASM_001_BIN}
 161                      DEPENDS ${ASM_001_OBJ}
 162                      COMMENT "Linking ASM hello_world/001 (NASM) for ${COMPILER}..."
 163                      VERBATIM
 164                  )
 165                  
 166                  add_custom_target(${COMPILER}_asm_${ASSEMBLER}_hello_001 ALL DEPENDS ${ASM_001_BIN})
 167                  
 168              elseif(ASSEMBLER STREQUAL "yasm")
 169                  set(ASM_001_SRC ${TEST_SRC_DIR}/asm/hello_world/001/hello_yasm.asm)
 170                  set(ASM_001_OBJ ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello.o)
 171                  set(ASM_001_BIN ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello)
 172                  file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001)
 173                  
 174                  add_custom_command(
 175                      OUTPUT ${ASM_001_OBJ}
 176                      COMMAND ${YASM_EXECUTABLE} -f elf64 ${ASM_001_SRC} -o ${ASM_001_OBJ}
 177                      DEPENDS ${ASM_001_SRC}
 178                      COMMENT "Assembling ASM hello_world/001 with YASM for ${COMPILER}..."
 179                      VERBATIM
 180                  )
 181                  
 182                  add_custom_command(
 183                      OUTPUT ${ASM_001_BIN}
 184                      COMMAND ${LD_EXECUTABLE} ${ASM_001_OBJ} -o ${ASM_001_BIN}
 185                      DEPENDS ${ASM_001_OBJ}
 186                      COMMENT "Linking ASM hello_world/001 (YASM) for ${COMPILER}..."
 187                      VERBATIM
 188                  )
 189                  
 190                  add_custom_target(${COMPILER}_asm_${ASSEMBLER}_hello_001 ALL DEPENDS ${ASM_001_BIN})
 191                  
 192              elseif(ASSEMBLER STREQUAL "gas")
 193                  set(ASM_001_SRC ${TEST_SRC_DIR}/asm/hello_world/001/hello_gas.s)
 194                  set(ASM_001_OBJ ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello.o)
 195                  set(ASM_001_BIN ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001/hello)
 196                  file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/asm_${ASSEMBLER}/hello_world/001)
 197                  
 198                  add_custom_command(
 199                      OUTPUT ${ASM_001_OBJ}
 200                      COMMAND ${GAS_EXECUTABLE} ${ASM_001_SRC} -o ${ASM_001_OBJ}
 201                      DEPENDS ${ASM_001_SRC}
 202                      COMMENT "Assembling ASM hello_world/001 with GAS for ${COMPILER}..."
 203                      VERBATIM
 204                  )
 205                  
 206                  add_custom_command(
 207                      OUTPUT ${ASM_001_BIN}
 208                      COMMAND ${LD_EXECUTABLE} ${ASM_001_OBJ} -o ${ASM_001_BIN}
 209                      DEPENDS ${ASM_001_OBJ}
 210                      COMMENT "Linking ASM hello_world/001 (GAS) for ${COMPILER}..."
 211                      VERBATIM
 212                  )
 213                  
 214                  add_custom_target(${COMPILER}_asm_${ASSEMBLER}_hello_001 ALL DEPENDS ${ASM_001_BIN})
 215              endif()
 216          endforeach()
 217      endforeach()
 218      message(STATUS "ASM build enabled with assemblers: ${ASSEMBLERS}")
 219  else()
 220      message(WARNING "No assembler or linker found, skipping ASM builds")
 221  endif()
 222  
 223  # Rust Hello World 001 - build with different linkers
 224  if(RUSTC_EXECUTABLE)
 225      foreach(COMPILER ${COMPILERS})
 226          set(RUST_001_SRC ${TEST_SRC_DIR}/rust/hello_world/001/main.rs)
 227          set(RUST_001_BIN ${TEST_BIN_DIR}/${COMPILER}/rust/hello_world/001/hello)
 228          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/rust/hello_world/001)
 229          
 230          # Use different linker based on compiler
 231          if(COMPILER STREQUAL "gcc")
 232              set(RUST_LINKER "gcc")
 233          elseif(COMPILER STREQUAL "clang")
 234              set(RUST_LINKER "clang")
 235          endif()
 236          
 237          add_custom_command(
 238              OUTPUT ${RUST_001_BIN}
 239              COMMAND ${RUSTC_EXECUTABLE} ${RUST_001_SRC} -o ${RUST_001_BIN} -C opt-level=3 -C linker=${RUST_LINKER}
 240              DEPENDS ${RUST_001_SRC}
 241              COMMENT "Building Rust hello_world/001 with ${COMPILER} linker..."
 242              VERBATIM
 243          )
 244          
 245          add_custom_target(${COMPILER}_rust_hello_001 ALL DEPENDS ${RUST_001_BIN})
 246      endforeach()
 247      message(STATUS "Rust build enabled")
 248  else()
 249      message(WARNING "rustc not found, skipping Rust builds")
 250  endif()
 251  
 252  # Zig Hello World 001 - Zig has its own compiler, build for each configuration
 253  if(ZIG_EXECUTABLE)
 254      foreach(COMPILER ${COMPILERS})
 255          set(ZIG_001_SRC ${TEST_SRC_DIR}/zig/hello_world/001/main.zig)
 256          set(ZIG_001_BIN ${TEST_BIN_DIR}/${COMPILER}/zig/hello_world/001/hello)
 257          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/zig/hello_world/001)
 258          
 259          add_custom_command(
 260              OUTPUT ${ZIG_001_BIN}
 261              COMMAND ${ZIG_EXECUTABLE} build-exe ${ZIG_001_SRC} -O ReleaseFast -femit-bin=${ZIG_001_BIN}
 262              DEPENDS ${ZIG_001_SRC}
 263              COMMENT "Building Zig hello_world/001 for ${COMPILER}..."
 264              VERBATIM
 265          )
 266          
 267          add_custom_target(${COMPILER}_zig_hello_001 ALL DEPENDS ${ZIG_001_BIN})
 268      endforeach()
 269      message(STATUS "Zig build enabled")
 270  else()
 271      message(WARNING "zig not found, skipping Zig builds")
 272  endif()
 273  
 274  # C Hello World 001 - build with gcc and clang
 275  if(GCC_C_EXECUTABLE OR CLANG_C_EXECUTABLE)
 276      foreach(COMPILER ${COMPILERS})
 277          # Set C compiler executable
 278          if(COMPILER STREQUAL "gcc" AND GCC_C_EXECUTABLE)
 279              set(C_COMPILER_EXEC ${GCC_C_EXECUTABLE})
 280          elseif(COMPILER STREQUAL "clang" AND CLANG_C_EXECUTABLE)
 281              set(C_COMPILER_EXEC ${CLANG_C_EXECUTABLE})
 282          else()
 283              continue()
 284          endif()
 285          
 286          set(C_001_SRC ${TEST_SRC_DIR}/c/hello_world/001/hello.c)
 287          set(C_001_BIN ${TEST_BIN_DIR}/${COMPILER}/c/hello_world/001/hello)
 288          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/c/hello_world/001)
 289          
 290          add_custom_command(
 291              OUTPUT ${C_001_BIN}
 292              COMMAND ${C_COMPILER_EXEC} ${C_001_SRC} -o ${C_001_BIN} -O3
 293              DEPENDS ${C_001_SRC}
 294              COMMENT "Building C hello_world/001 with ${COMPILER}..."
 295              VERBATIM
 296          )
 297          
 298          add_custom_target(${COMPILER}_c_hello_001 ALL DEPENDS ${C_001_BIN})
 299      endforeach()
 300      message(STATUS "C build enabled")
 301  else()
 302      message(WARNING "gcc or clang not found, skipping C builds")
 303  endif()
 304  
 305  # Go Hello World 001 - Go compiler is independent
 306  if(GO_EXECUTABLE)
 307      foreach(COMPILER ${COMPILERS})
 308          set(GO_001_SRC ${TEST_SRC_DIR}/go/hello_world/001/main.go)
 309          set(GO_001_BIN ${TEST_BIN_DIR}/${COMPILER}/go/hello_world/001/hello)
 310          set(GO_001_DIR ${TEST_SRC_DIR}/go/hello_world/001)
 311          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/go/hello_world/001)
 312          
 313          add_custom_command(
 314              OUTPUT ${GO_001_BIN}
 315              COMMAND ${GO_EXECUTABLE} build -o ${GO_001_BIN} -ldflags=-s\ -w ${GO_001_SRC}
 316              WORKING_DIRECTORY ${GO_001_DIR}
 317              DEPENDS ${GO_001_SRC}
 318              COMMENT "Building Go hello_world/001 for ${COMPILER}..."
 319              VERBATIM
 320          )
 321          
 322          add_custom_target(${COMPILER}_go_hello_001 ALL DEPENDS ${GO_001_BIN})
 323      endforeach()
 324      message(STATUS "Go build enabled")
 325  else()
 326      message(WARNING "go not found, skipping Go builds")
 327  endif()
 328  
 329  # D Hello World 001 - try multiple D compilers
 330  set(D_COMPILER "")
 331  if(LDC2_EXECUTABLE)
 332      set(D_COMPILER ${LDC2_EXECUTABLE})
 333      set(D_COMPILER_NAME "ldc2")
 334      set(D_FLAGS "-O3;-release")
 335      message(STATUS "D compiler: ldc2 (LLVM-based)")
 336  elseif(DMD_EXECUTABLE)
 337      set(D_COMPILER ${DMD_EXECUTABLE})
 338      set(D_COMPILER_NAME "dmd")
 339      set(D_FLAGS "-O;-release")
 340      message(STATUS "D compiler: dmd (reference)")
 341  elseif(GDC_EXECUTABLE)
 342      set(D_COMPILER ${GDC_EXECUTABLE})
 343      set(D_COMPILER_NAME "gdc")
 344      set(D_FLAGS "-O3;-frelease")
 345      message(STATUS "D compiler: gdc (GCC-based)")
 346  endif()
 347  
 348  if(D_COMPILER)
 349      foreach(COMPILER ${COMPILERS})
 350          set(D_001_SRC ${TEST_SRC_DIR}/d/hello_world/001/hello.d)
 351          set(D_001_BIN ${TEST_BIN_DIR}/${COMPILER}/d/hello_world/001/hello)
 352          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/d/hello_world/001)
 353          
 354          add_custom_command(
 355              OUTPUT ${D_001_BIN}
 356              COMMAND ${D_COMPILER} ${D_001_SRC} -of=${D_001_BIN} ${D_FLAGS}
 357              DEPENDS ${D_001_SRC}
 358              COMMENT "Building D hello_world/001 with ${D_COMPILER_NAME} for ${COMPILER}..."
 359              VERBATIM
 360          )
 361          
 362          add_custom_target(${COMPILER}_d_hello_001 ALL DEPENDS ${D_001_BIN})
 363      endforeach()
 364      message(STATUS "D build enabled")
 365  else()
 366      message(WARNING "No D compiler found (dmd, ldc2, or gdc), skipping D builds")
 367  endif()
 368  
 369  # Nim Hello World 001
 370  if(NIM_EXECUTABLE)
 371      foreach(COMPILER ${COMPILERS})
 372          set(NIM_001_SRC ${TEST_SRC_DIR}/nim/hello_world/001/hello.nim)
 373          set(NIM_001_BIN ${TEST_BIN_DIR}/${COMPILER}/nim/hello_world/001/hello)
 374          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/nim/hello_world/001)
 375          
 376          add_custom_command(
 377              OUTPUT ${NIM_001_BIN}
 378              COMMAND ${NIM_EXECUTABLE} c -d:release --opt:speed -o:${NIM_001_BIN} ${NIM_001_SRC}
 379              DEPENDS ${NIM_001_SRC}
 380              COMMENT "Building Nim hello_world/001 for ${COMPILER}..."
 381              VERBATIM
 382          )
 383          
 384          add_custom_target(${COMPILER}_nim_hello_001 ALL DEPENDS ${NIM_001_BIN})
 385      endforeach()
 386      message(STATUS "Nim build enabled")
 387  else()
 388      message(WARNING "nim not found, skipping Nim builds")
 389  endif()
 390  
 391  # Odin Hello World 001
 392  if(ODIN_EXECUTABLE)
 393      foreach(COMPILER ${COMPILERS})
 394          set(ODIN_001_SRC ${TEST_SRC_DIR}/odin/hello_world/001/hello.odin)
 395          set(ODIN_001_BIN ${TEST_BIN_DIR}/${COMPILER}/odin/hello_world/001/hello)
 396          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/odin/hello_world/001)
 397          
 398          add_custom_command(
 399              OUTPUT ${ODIN_001_BIN}
 400              COMMAND ${ODIN_EXECUTABLE} build ${ODIN_001_SRC} -file -o:speed -out:${ODIN_001_BIN}
 401              DEPENDS ${ODIN_001_SRC}
 402              COMMENT "Building Odin hello_world/001 for ${COMPILER}..."
 403              VERBATIM
 404          )
 405          
 406          add_custom_target(${COMPILER}_odin_hello_001 ALL DEPENDS ${ODIN_001_BIN})
 407      endforeach()
 408      message(STATUS "Odin build enabled")
 409  else()
 410      message(WARNING "odin not found, skipping Odin builds")
 411  endif()
 412  
 413  # V Hello World 001
 414  if(V_EXECUTABLE)
 415      foreach(COMPILER ${COMPILERS})
 416          set(V_001_SRC ${TEST_SRC_DIR}/v/hello_world/001/hello.v)
 417          set(V_001_BIN ${TEST_BIN_DIR}/${COMPILER}/v/hello_world/001/hello)
 418          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/v/hello_world/001)
 419          
 420          add_custom_command(
 421              OUTPUT ${V_001_BIN}
 422              COMMAND ${V_EXECUTABLE} -prod -o ${V_001_BIN} ${V_001_SRC}
 423              DEPENDS ${V_001_SRC}
 424              COMMENT "Building V hello_world/001 for ${COMPILER}..."
 425              VERBATIM
 426          )
 427          
 428          add_custom_target(${COMPILER}_v_hello_001 ALL DEPENDS ${V_001_BIN})
 429      endforeach()
 430      message(STATUS "V build enabled")
 431  else()
 432      message(WARNING "v not found, skipping V builds")
 433  endif()
 434  
 435  # Ada Hello World 001
 436  if(GNAT_EXECUTABLE)
 437      foreach(COMPILER ${COMPILERS})
 438          set(ADA_001_SRC ${TEST_SRC_DIR}/ada/hello_world/001/hello.adb)
 439          set(ADA_001_BIN ${TEST_BIN_DIR}/${COMPILER}/ada/hello_world/001/hello)
 440          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/ada/hello_world/001)
 441          
 442          add_custom_command(
 443              OUTPUT ${ADA_001_BIN}
 444              COMMAND ${GNAT_EXECUTABLE} ${ADA_001_SRC} -O3 -o ${ADA_001_BIN}
 445              DEPENDS ${ADA_001_SRC}
 446              COMMENT "Building Ada hello_world/001 for ${COMPILER}..."
 447              VERBATIM
 448          )
 449          
 450          add_custom_target(${COMPILER}_ada_hello_001 ALL DEPENDS ${ADA_001_BIN})
 451      endforeach()
 452      message(STATUS "Ada build enabled")
 453  else()
 454      message(WARNING "gnatmake not found, skipping Ada builds")
 455  endif()
 456  
 457  # Haskell Hello World 001
 458  if(GHC_EXECUTABLE)
 459      foreach(COMPILER ${COMPILERS})
 460          set(HASKELL_001_SRC ${TEST_SRC_DIR}/haskell/hello_world/001/hello.hs)
 461          set(HASKELL_001_BIN ${TEST_BIN_DIR}/${COMPILER}/haskell/hello_world/001/hello)
 462          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/haskell/hello_world/001)
 463          
 464          add_custom_command(
 465              OUTPUT ${HASKELL_001_BIN}
 466              COMMAND ${GHC_EXECUTABLE} -O2 -outputdir ${TEST_BIN_DIR}/${COMPILER}/haskell/hello_world/001 -o ${HASKELL_001_BIN} ${HASKELL_001_SRC}
 467              DEPENDS ${HASKELL_001_SRC}
 468              COMMENT "Building Haskell hello_world/001 for ${COMPILER}..."
 469              VERBATIM
 470          )
 471          
 472          add_custom_target(${COMPILER}_haskell_hello_001 ALL DEPENDS ${HASKELL_001_BIN})
 473      endforeach()
 474      message(STATUS "Haskell build enabled")
 475  else()
 476      message(WARNING "ghc not found, skipping Haskell builds")
 477  endif()
 478  
 479  # Fortran Hello World 001
 480  if(GFORTRAN_EXECUTABLE)
 481      foreach(COMPILER ${COMPILERS})
 482          set(FORTRAN_001_SRC ${TEST_SRC_DIR}/fortran/hello_world/001/hello.f90)
 483          set(FORTRAN_001_BIN ${TEST_BIN_DIR}/${COMPILER}/fortran/hello_world/001/hello)
 484          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/fortran/hello_world/001)
 485          
 486          add_custom_command(
 487              OUTPUT ${FORTRAN_001_BIN}
 488              COMMAND ${GFORTRAN_EXECUTABLE} ${FORTRAN_001_SRC} -O3 -o ${FORTRAN_001_BIN}
 489              DEPENDS ${FORTRAN_001_SRC}
 490              COMMENT "Building Fortran hello_world/001 for ${COMPILER}..."
 491              VERBATIM
 492          )
 493          
 494          add_custom_target(${COMPILER}_fortran_hello_001 ALL DEPENDS ${FORTRAN_001_BIN})
 495      endforeach()
 496      message(STATUS "Fortran build enabled")
 497  else()
 498      message(WARNING "gfortran not found, skipping Fortran builds")
 499  endif()
 500  
 501  # Pascal Hello World 001
 502  if(FPC_EXECUTABLE)
 503      foreach(COMPILER ${COMPILERS})
 504          set(PASCAL_001_SRC ${TEST_SRC_DIR}/pascal/hello_world/001/hello.pas)
 505          set(PASCAL_001_BIN ${TEST_BIN_DIR}/${COMPILER}/pascal/hello_world/001/hello)
 506          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/pascal/hello_world/001)
 507          
 508          add_custom_command(
 509              OUTPUT ${PASCAL_001_BIN}
 510              COMMAND ${FPC_EXECUTABLE} ${PASCAL_001_SRC} -O3 -o${PASCAL_001_BIN}
 511              DEPENDS ${PASCAL_001_SRC}
 512              COMMENT "Building Pascal hello_world/001 for ${COMPILER}..."
 513              VERBATIM
 514          )
 515          
 516          add_custom_target(${COMPILER}_pascal_hello_001 ALL DEPENDS ${PASCAL_001_BIN})
 517      endforeach()
 518      message(STATUS "Pascal build enabled")
 519  else()
 520      message(WARNING "fpc not found, skipping Pascal builds")
 521  endif()
 522  
 523  # COBOL Hello World 001
 524  if(COBC_EXECUTABLE)
 525      foreach(COMPILER ${COMPILERS})
 526          set(COBOL_001_SRC ${TEST_SRC_DIR}/cobol/hello_world/001/hello.cob)
 527          set(COBOL_001_BIN ${TEST_BIN_DIR}/${COMPILER}/cobol/hello_world/001/hello)
 528          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/cobol/hello_world/001)
 529          
 530          add_custom_command(
 531              OUTPUT ${COBOL_001_BIN}
 532              COMMAND ${COBC_EXECUTABLE} -x -O3 -o ${COBOL_001_BIN} ${COBOL_001_SRC}
 533              DEPENDS ${COBOL_001_SRC}
 534              COMMENT "Building COBOL hello_world/001 for ${COMPILER}..."
 535              VERBATIM
 536          )
 537          
 538          add_custom_target(${COMPILER}_cobol_hello_001 ALL DEPENDS ${COBOL_001_BIN})
 539      endforeach()
 540      message(STATUS "COBOL build enabled")
 541  else()
 542      message(WARNING "cobc not found, skipping COBOL builds")
 543  endif()
 544  
 545  # C# Hello World 001
 546  set(CSHARP_COMPILER "")
 547  if(MCS_EXECUTABLE)
 548      set(CSHARP_COMPILER ${MCS_EXECUTABLE})
 549      set(CSHARP_FLAGS "-optimize+")
 550      message(STATUS "C# compiler: mcs (Mono)")
 551  endif()
 552  
 553  if(CSHARP_COMPILER)
 554      foreach(COMPILER ${COMPILERS})
 555          set(CSHARP_001_SRC ${TEST_SRC_DIR}/csharp/hello_world/001/hello.cs)
 556          set(CSHARP_001_BIN ${TEST_BIN_DIR}/${COMPILER}/csharp/hello_world/001/hello.exe)
 557          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/csharp/hello_world/001)
 558          
 559          add_custom_command(
 560              OUTPUT ${CSHARP_001_BIN}
 561              COMMAND ${CSHARP_COMPILER} ${CSHARP_FLAGS} -out:${CSHARP_001_BIN} ${CSHARP_001_SRC}
 562              DEPENDS ${CSHARP_001_SRC}
 563              COMMENT "Building C# hello_world/001 for ${COMPILER}..."
 564              VERBATIM
 565          )
 566          
 567          add_custom_target(${COMPILER}_csharp_hello_001 ALL DEPENDS ${CSHARP_001_BIN})
 568      endforeach()
 569      message(STATUS "C# build enabled")
 570  else()
 571      message(WARNING "No C# compiler found (csc or mcs), skipping C# builds")
 572  endif()
 573  
 574  # Python Hello World 001 - Compile with Cython
 575  if(CYTHON_EXECUTABLE AND PYTHON_EXECUTABLE)
 576      foreach(COMPILER ${COMPILERS})
 577          set(PY_001_SRC ${TEST_SRC_DIR}/python/hello_world/001/hello.py)
 578          set(PY_001_C ${TEST_BIN_DIR}/${COMPILER}/python/hello_world/001/hello.c)
 579          set(PY_001_BIN ${TEST_BIN_DIR}/${COMPILER}/python/hello_world/001/hello)
 580          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/python/hello_world/001)
 581          
 582          # Get Python include and library paths
 583          execute_process(
 584              COMMAND ${PYTHON_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_path('include'))"
 585              OUTPUT_VARIABLE PYTHON_INCLUDE_DIR
 586              OUTPUT_STRIP_TRAILING_WHITESPACE
 587          )
 588          
 589          execute_process(
 590              COMMAND ${PYTHON_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"
 591              OUTPUT_VARIABLE PYTHON_LIB_DIR
 592              OUTPUT_STRIP_TRAILING_WHITESPACE
 593          )
 594          
 595          execute_process(
 596              COMMAND ${PYTHON_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('LDVERSION'))"
 597              OUTPUT_VARIABLE PYTHON_LDVERSION
 598              OUTPUT_STRIP_TRAILING_WHITESPACE
 599          )
 600          
 601          # Set compiler executable
 602          if(COMPILER STREQUAL "gcc")
 603              set(C_COMPILER ${GCC_C_EXECUTABLE})
 604          elseif(COMPILER STREQUAL "clang")
 605              set(C_COMPILER ${CLANG_C_EXECUTABLE})
 606          endif()
 607          
 608          # Step 1: Cython compile .py to .c with --embed flag for standalone executable
 609          add_custom_command(
 610              OUTPUT ${PY_001_C}
 611              COMMAND ${CYTHON_EXECUTABLE} --embed -o ${PY_001_C} ${PY_001_SRC}
 612              DEPENDS ${PY_001_SRC}
 613              COMMENT "Cythonizing Python hello_world/001 for ${COMPILER}..."
 614              VERBATIM
 615          )
 616          
 617          # Step 2: Compile .c to executable
 618          add_custom_command(
 619              OUTPUT ${PY_001_BIN}
 620              COMMAND ${C_COMPILER} -O3 ${PY_001_C} -I${PYTHON_INCLUDE_DIR} -L${PYTHON_LIB_DIR} -lpython${PYTHON_LDVERSION} -o ${PY_001_BIN}
 621              DEPENDS ${PY_001_C}
 622              COMMENT "Compiling Cython hello_world/001 with ${COMPILER}..."
 623              VERBATIM
 624          )
 625          
 626          add_custom_target(${COMPILER}_python_hello_001 ALL DEPENDS ${PY_001_BIN})
 627      endforeach()
 628      message(STATUS "Python (Cython) build enabled")
 629  else()
 630      message(WARNING "Cython or Python not found, skipping Python builds")
 631  endif()
 632  
 633  # R Hello World 001 - Compile with embedded R
 634  if(R_EXECUTABLE)
 635      # Get R include and library paths
 636      execute_process(
 637          COMMAND ${R_EXECUTABLE} CMD config --cppflags
 638          OUTPUT_VARIABLE R_INCLUDE_FLAGS_RAW
 639          OUTPUT_STRIP_TRAILING_WHITESPACE
 640      )
 641      
 642      execute_process(
 643          COMMAND ${R_EXECUTABLE} CMD config --ldflags
 644          OUTPUT_VARIABLE R_LD_FLAGS_RAW
 645          OUTPUT_STRIP_TRAILING_WHITESPACE
 646      )
 647      
 648      # Remove -ltirpc which may not be available on all systems
 649      string(REPLACE "-ltirpc" "" R_LD_FLAGS_RAW "${R_LD_FLAGS_RAW}")
 650      
 651      # Convert to lists for proper handling
 652      separate_arguments(R_INCLUDE_FLAGS UNIX_COMMAND "${R_INCLUDE_FLAGS_RAW}")
 653      separate_arguments(R_LD_FLAGS UNIX_COMMAND "${R_LD_FLAGS_RAW}")
 654      
 655      foreach(COMPILER ${COMPILERS})
 656          set(R_001_WRAPPER ${TEST_SRC_DIR}/r/hello_world/001/hello_wrapper.c)
 657          set(R_001_BIN ${TEST_BIN_DIR}/${COMPILER}/r/hello_world/001/hello)
 658          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/r/hello_world/001)
 659          
 660          if(COMPILER STREQUAL "gcc")
 661              set(C_COMPILER ${GCC_C_EXECUTABLE})
 662          elseif(COMPILER STREQUAL "clang")
 663              set(C_COMPILER ${CLANG_C_EXECUTABLE})
 664          endif()
 665          
 666          add_custom_command(
 667              OUTPUT ${R_001_BIN}
 668              COMMAND ${C_COMPILER} ${R_001_WRAPPER} ${R_INCLUDE_FLAGS} ${R_LD_FLAGS} -o ${R_001_BIN}
 669              DEPENDS ${R_001_WRAPPER}
 670              COMMENT "Building R hello_world/001 for ${COMPILER}..."
 671              VERBATIM
 672          )
 673          
 674          add_custom_target(${COMPILER}_r_hello_001 ALL DEPENDS ${R_001_BIN})
 675      endforeach()
 676      message(STATUS "R build enabled")
 677  else()
 678      message(WARNING "R not found, skipping R builds")
 679  endif()
 680  
 681  message(STATUS "Test binaries output directory: ${TEST_BIN_DIR}")
 682  
 683  # ======================================================================
 684  # Build benchmark tool
 685  # ======================================================================
 686  
 687  set(BENCHMARK_SRC ${CMAKE_SOURCE_DIR}/src/benchmark.cpp)
 688  set(BENCHMARK_BIN ${BIN_DIR}/benchmark)
 689  
 690  add_executable(benchmark_tool ${BENCHMARK_SRC})
 691  set_target_properties(benchmark_tool PROPERTIES
 692      OUTPUT_NAME benchmark
 693      RUNTIME_OUTPUT_DIRECTORY ${BIN_DIR}
 694      CXX_STANDARD 17
 695      CXX_STANDARD_REQUIRED ON
 696  )
 697  
 698  target_compile_options(benchmark_tool PRIVATE -O3 -Wall -Wextra)
 699  target_link_libraries(benchmark_tool stdc++fs)
 700  
 701  message(STATUS "Benchmark tool will be built to: ${BIN_DIR}/benchmark")
 702  
 703  # ======================================================================
 704  # FIRST 1000 PRIMES SERIES
 705  # ======================================================================
 706  
 707  # C++ first1000primes 001
 708  foreach(COMPILER ${COMPILERS})
 709      if(COMPILER STREQUAL "gcc")
 710          set(COMPILER_EXEC ${GCC_EXECUTABLE})
 711      elseif(COMPILER STREQUAL "clang")
 712          set(COMPILER_EXEC ${CLANG_EXECUTABLE})
 713      endif()
 714      
 715      set(CPP_PRIMES_SRC ${TEST_SRC_DIR}/cpp/first1000primes/001/primes.cpp)
 716      set(CPP_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/cpp/first1000primes/001/primes)
 717      file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/cpp/first1000primes/001)
 718      
 719      add_custom_command(
 720          OUTPUT ${CPP_PRIMES_BIN}
 721          COMMAND ${COMPILER_EXEC} ${CPP_PRIMES_SRC} -o ${CPP_PRIMES_BIN} -O3 -std=c++17
 722          DEPENDS ${CPP_PRIMES_SRC}
 723          COMMENT "Building C++ first1000primes/001 with ${COMPILER}..."
 724          VERBATIM
 725      )
 726      
 727      add_custom_target(${COMPILER}_cpp_primes_001 ALL DEPENDS ${CPP_PRIMES_BIN})
 728  endforeach()
 729  
 730  # C first1000primes 001
 731  if(GCC_C_EXECUTABLE OR CLANG_C_EXECUTABLE)
 732      foreach(COMPILER ${COMPILERS})
 733          if(COMPILER STREQUAL "gcc")
 734              set(C_COMPILER ${GCC_C_EXECUTABLE})
 735          elseif(COMPILER STREQUAL "clang")
 736              set(C_COMPILER ${CLANG_C_EXECUTABLE})
 737          endif()
 738          
 739          if(C_COMPILER)
 740              set(C_PRIMES_SRC ${TEST_SRC_DIR}/c/first1000primes/001/primes.c)
 741              set(C_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/c/first1000primes/001/primes)
 742              file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/c/first1000primes/001)
 743              
 744              add_custom_command(
 745                  OUTPUT ${C_PRIMES_BIN}
 746                  COMMAND ${C_COMPILER} ${C_PRIMES_SRC} -o ${C_PRIMES_BIN} -O3 -std=c11 -lm
 747                  DEPENDS ${C_PRIMES_SRC}
 748                  COMMENT "Building C first1000primes/001 with ${COMPILER}..."
 749                  VERBATIM
 750              )
 751              
 752              add_custom_target(${COMPILER}_c_primes_001 ALL DEPENDS ${C_PRIMES_BIN})
 753          endif()
 754      endforeach()
 755  endif()
 756  
 757  # ASM first1000primes 001 - NASM only
 758  if(NASM_EXECUTABLE AND LD_EXECUTABLE)
 759      foreach(COMPILER ${COMPILERS})
 760          set(ASM_PRIMES_SRC ${TEST_SRC_DIR}/asm/first1000primes/001/primes.asm)
 761          set(ASM_PRIMES_OBJ ${TEST_BIN_DIR}/${COMPILER}/asm/first1000primes/001/primes.o)
 762          set(ASM_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/asm/first1000primes/001/primes)
 763          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/asm/first1000primes/001)
 764          
 765          add_custom_command(
 766              OUTPUT ${ASM_PRIMES_OBJ}
 767              COMMAND ${NASM_EXECUTABLE} -f elf64 ${ASM_PRIMES_SRC} -o ${ASM_PRIMES_OBJ}
 768              DEPENDS ${ASM_PRIMES_SRC}
 769              COMMENT "Assembling ASM first1000primes/001 for ${COMPILER}..."
 770              VERBATIM
 771          )
 772          
 773          add_custom_command(
 774              OUTPUT ${ASM_PRIMES_BIN}
 775              COMMAND ${LD_EXECUTABLE} ${ASM_PRIMES_OBJ} -o ${ASM_PRIMES_BIN}
 776              DEPENDS ${ASM_PRIMES_OBJ}
 777              COMMENT "Linking ASM first1000primes/001 for ${COMPILER}..."
 778              VERBATIM
 779          )
 780          
 781          add_custom_target(${COMPILER}_asm_primes_001 ALL DEPENDS ${ASM_PRIMES_BIN})
 782      endforeach()
 783  endif()
 784  
 785  # Rust first1000primes 001
 786  if(RUSTC_EXECUTABLE)
 787      foreach(COMPILER ${COMPILERS})
 788          set(RUST_PRIMES_SRC ${TEST_SRC_DIR}/rust/first1000primes/001/primes.rs)
 789          set(RUST_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/rust/first1000primes/001/primes)
 790          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/rust/first1000primes/001)
 791          
 792          add_custom_command(
 793              OUTPUT ${RUST_PRIMES_BIN}
 794              COMMAND ${RUSTC_EXECUTABLE} ${RUST_PRIMES_SRC} -o ${RUST_PRIMES_BIN} -C opt-level=3
 795              DEPENDS ${RUST_PRIMES_SRC}
 796              COMMENT "Building Rust first1000primes/001 for ${COMPILER}..."
 797              VERBATIM
 798          )
 799          
 800          add_custom_target(${COMPILER}_rust_primes_001 ALL DEPENDS ${RUST_PRIMES_BIN})
 801      endforeach()
 802  endif()
 803  
 804  # Zig first1000primes 001
 805  if(ZIG_EXECUTABLE)
 806      foreach(COMPILER ${COMPILERS})
 807          set(ZIG_PRIMES_SRC ${TEST_SRC_DIR}/zig/first1000primes/001/primes.zig)
 808          set(ZIG_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/zig/first1000primes/001/primes)
 809          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/zig/first1000primes/001)
 810          
 811          add_custom_command(
 812              OUTPUT ${ZIG_PRIMES_BIN}
 813              COMMAND ${ZIG_EXECUTABLE} build-exe ${ZIG_PRIMES_SRC} -O ReleaseFast -femit-bin=${ZIG_PRIMES_BIN}
 814              DEPENDS ${ZIG_PRIMES_SRC}
 815              COMMENT "Building Zig first1000primes/001 for ${COMPILER}..."
 816              VERBATIM
 817          )
 818          
 819          add_custom_target(${COMPILER}_zig_primes_001 ALL DEPENDS ${ZIG_PRIMES_BIN})
 820      endforeach()
 821  endif()
 822  
 823  # Go first1000primes 001
 824  if(GO_EXECUTABLE)
 825      foreach(COMPILER ${COMPILERS})
 826          set(GO_PRIMES_SRC ${TEST_SRC_DIR}/go/first1000primes/001/primes.go)
 827          set(GO_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/go/first1000primes/001/primes)
 828          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/go/first1000primes/001)
 829          
 830          add_custom_command(
 831              OUTPUT ${GO_PRIMES_BIN}
 832              COMMAND ${GO_EXECUTABLE} build -o ${GO_PRIMES_BIN} ${GO_PRIMES_SRC}
 833              DEPENDS ${GO_PRIMES_SRC}
 834              WORKING_DIRECTORY ${TEST_SRC_DIR}/go/first1000primes/001
 835              COMMENT "Building Go first1000primes/001 for ${COMPILER}..."
 836              VERBATIM
 837          )
 838          
 839          add_custom_target(${COMPILER}_go_primes_001 ALL DEPENDS ${GO_PRIMES_BIN})
 840      endforeach()
 841  endif()
 842  
 843  # D first1000primes 001
 844  if(LDC2_EXECUTABLE)
 845      set(D_PRIMES_FLAGS "-O3")
 846      foreach(COMPILER ${COMPILERS})
 847          set(D_PRIMES_SRC ${TEST_SRC_DIR}/d/first1000primes/001/primes.d)
 848          set(D_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/d/first1000primes/001/primes)
 849          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/d/first1000primes/001)
 850          
 851          add_custom_command(
 852              OUTPUT ${D_PRIMES_BIN}
 853              COMMAND ${LDC2_EXECUTABLE} ${D_PRIMES_FLAGS} -of=${D_PRIMES_BIN} ${D_PRIMES_SRC}
 854              DEPENDS ${D_PRIMES_SRC}
 855              COMMENT "Building D first1000primes/001 for ${COMPILER}..."
 856              VERBATIM
 857          )
 858          
 859          add_custom_target(${COMPILER}_d_primes_001 ALL DEPENDS ${D_PRIMES_BIN})
 860      endforeach()
 861  endif()
 862  
 863  # Nim first1000primes 001
 864  if(NIM_EXECUTABLE)
 865      foreach(COMPILER ${COMPILERS})
 866          set(NIM_PRIMES_SRC ${TEST_SRC_DIR}/nim/first1000primes/001/primes.nim)
 867          set(NIM_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/nim/first1000primes/001/primes)
 868          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/nim/first1000primes/001)
 869          
 870          add_custom_command(
 871              OUTPUT ${NIM_PRIMES_BIN}
 872              COMMAND ${NIM_EXECUTABLE} c -d:release -o:${NIM_PRIMES_BIN} ${NIM_PRIMES_SRC}
 873              DEPENDS ${NIM_PRIMES_SRC}
 874              COMMENT "Building Nim first1000primes/001 for ${COMPILER}..."
 875              VERBATIM
 876          )
 877          
 878          add_custom_target(${COMPILER}_nim_primes_001 ALL DEPENDS ${NIM_PRIMES_BIN})
 879      endforeach()
 880  endif()
 881  
 882  # Ada first1000primes 001
 883  if(GNAT_EXECUTABLE)
 884      foreach(COMPILER ${COMPILERS})
 885          set(ADA_PRIMES_SRC ${TEST_SRC_DIR}/ada/first1000primes/001/primes.adb)
 886          set(ADA_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/ada/first1000primes/001/primes)
 887          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/ada/first1000primes/001)
 888          
 889          add_custom_command(
 890              OUTPUT ${ADA_PRIMES_BIN}
 891              COMMAND ${GNAT_EXECUTABLE} ${ADA_PRIMES_SRC} -o ${ADA_PRIMES_BIN} -O3 -gnatpn
 892              DEPENDS ${ADA_PRIMES_SRC}
 893              WORKING_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/ada/first1000primes/001
 894              COMMENT "Building Ada first1000primes/001 for ${COMPILER}..."
 895              VERBATIM
 896          )
 897          
 898          add_custom_target(${COMPILER}_ada_primes_001 ALL DEPENDS ${ADA_PRIMES_BIN})
 899      endforeach()
 900  endif()
 901  
 902  # Haskell first1000primes 001
 903  if(GHC_EXECUTABLE)
 904      foreach(COMPILER ${COMPILERS})
 905          set(HS_PRIMES_SRC ${TEST_SRC_DIR}/haskell/first1000primes/001/primes.hs)
 906          set(HS_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/haskell/first1000primes/001/primes)
 907          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/haskell/first1000primes/001)
 908          
 909          add_custom_command(
 910              OUTPUT ${HS_PRIMES_BIN}
 911              COMMAND ${GHC_EXECUTABLE} -O2 -o ${HS_PRIMES_BIN} ${HS_PRIMES_SRC}
 912              DEPENDS ${HS_PRIMES_SRC}
 913              WORKING_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/haskell/first1000primes/001
 914              COMMENT "Building Haskell first1000primes/001 for ${COMPILER}..."
 915              VERBATIM
 916          )
 917          
 918          add_custom_target(${COMPILER}_haskell_primes_001 ALL DEPENDS ${HS_PRIMES_BIN})
 919      endforeach()
 920  endif()
 921  
 922  # Fortran first1000primes 001
 923  if(GFORTRAN_EXECUTABLE)
 924      foreach(COMPILER ${COMPILERS})
 925          set(F90_PRIMES_SRC ${TEST_SRC_DIR}/fortran/first1000primes/001/primes.f90)
 926          set(F90_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/fortran/first1000primes/001/primes)
 927          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/fortran/first1000primes/001)
 928          
 929          add_custom_command(
 930              OUTPUT ${F90_PRIMES_BIN}
 931              COMMAND ${GFORTRAN_EXECUTABLE} ${F90_PRIMES_SRC} -o ${F90_PRIMES_BIN} -O3
 932              DEPENDS ${F90_PRIMES_SRC}
 933              COMMENT "Building Fortran first1000primes/001 for ${COMPILER}..."
 934              VERBATIM
 935          )
 936          
 937          add_custom_target(${COMPILER}_fortran_primes_001 ALL DEPENDS ${F90_PRIMES_BIN})
 938      endforeach()
 939  endif()
 940  
 941  # Pascal first1000primes 001
 942  if(FPC_EXECUTABLE)
 943      foreach(COMPILER ${COMPILERS})
 944          set(PAS_PRIMES_SRC ${TEST_SRC_DIR}/pascal/first1000primes/001/primes.pas)
 945          set(PAS_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/pascal/first1000primes/001/primes)
 946          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/pascal/first1000primes/001)
 947          
 948          add_custom_command(
 949              OUTPUT ${PAS_PRIMES_BIN}
 950              COMMAND ${FPC_EXECUTABLE} ${PAS_PRIMES_SRC} -O3 -FE${TEST_BIN_DIR}/${COMPILER}/pascal/first1000primes/001 -oprimes
 951              DEPENDS ${PAS_PRIMES_SRC}
 952              COMMENT "Building Pascal first1000primes/001 for ${COMPILER}..."
 953              VERBATIM
 954          )
 955          
 956          add_custom_target(${COMPILER}_pascal_primes_001 ALL DEPENDS ${PAS_PRIMES_BIN})
 957      endforeach()
 958  endif()
 959  
 960  # COBOL first1000primes 001
 961  if(COBC_EXECUTABLE)
 962      foreach(COMPILER ${COMPILERS})
 963          set(COB_PRIMES_SRC ${TEST_SRC_DIR}/cobol/first1000primes/001/primes.cob)
 964          set(COB_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/cobol/first1000primes/001/primes)
 965          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/cobol/first1000primes/001)
 966          
 967          add_custom_command(
 968              OUTPUT ${COB_PRIMES_BIN}
 969              COMMAND ${COBC_EXECUTABLE} -x ${COB_PRIMES_SRC} -o ${COB_PRIMES_BIN} -O3
 970              DEPENDS ${COB_PRIMES_SRC}
 971              COMMENT "Building COBOL first1000primes/001 for ${COMPILER}..."
 972              VERBATIM
 973          )
 974          
 975          add_custom_target(${COMPILER}_cobol_primes_001 ALL DEPENDS ${COB_PRIMES_BIN})
 976      endforeach()
 977  endif()
 978  
 979  # C# first1000primes 001
 980  if(CSHARP_COMPILER)
 981      foreach(COMPILER ${COMPILERS})
 982          set(CS_PRIMES_SRC ${TEST_SRC_DIR}/csharp/first1000primes/001/primes.cs)
 983          set(CS_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/csharp/first1000primes/001/primes.exe)
 984          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/csharp/first1000primes/001)
 985          
 986          add_custom_command(
 987              OUTPUT ${CS_PRIMES_BIN}
 988              COMMAND ${CSHARP_COMPILER} ${CSHARP_FLAGS} -out:${CS_PRIMES_BIN} ${CS_PRIMES_SRC}
 989              DEPENDS ${CS_PRIMES_SRC}
 990              COMMENT "Building C# first1000primes/001 for ${COMPILER}..."
 991              VERBATIM
 992          )
 993          
 994          add_custom_target(${COMPILER}_csharp_primes_001 ALL DEPENDS ${CS_PRIMES_BIN})
 995      endforeach()
 996  endif()
 997  
 998  # Python first1000primes 001
 999  if(CYTHON_EXECUTABLE AND PYTHON_EXECUTABLE)
1000      foreach(COMPILER ${COMPILERS})
1001          set(PY_PRIMES_SRC ${TEST_SRC_DIR}/python/first1000primes/001/primes.py)
1002          set(PY_PRIMES_C ${TEST_BIN_DIR}/${COMPILER}/python/first1000primes/001/primes.c)
1003          set(PY_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/python/first1000primes/001/primes)
1004          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/python/first1000primes/001)
1005          
1006          if(COMPILER STREQUAL "gcc")
1007              set(C_COMPILER ${GCC_C_EXECUTABLE})
1008          elseif(COMPILER STREQUAL "clang")
1009              set(C_COMPILER ${CLANG_C_EXECUTABLE})
1010          endif()
1011          
1012          add_custom_command(
1013              OUTPUT ${PY_PRIMES_C}
1014              COMMAND ${CYTHON_EXECUTABLE} --embed -o ${PY_PRIMES_C} ${PY_PRIMES_SRC}
1015              DEPENDS ${PY_PRIMES_SRC}
1016              COMMENT "Cythonizing Python first1000primes/001 for ${COMPILER}..."
1017              VERBATIM
1018          )
1019          
1020          add_custom_command(
1021              OUTPUT ${PY_PRIMES_BIN}
1022              COMMAND ${C_COMPILER} -O3 ${PY_PRIMES_C} -I${PYTHON_INCLUDE_DIR} -L${PYTHON_LIB_DIR} -lpython${PYTHON_LDVERSION} -o ${PY_PRIMES_BIN}
1023              DEPENDS ${PY_PRIMES_C}
1024              COMMENT "Compiling Cython first1000primes/001 with ${COMPILER}..."
1025              VERBATIM
1026          )
1027          
1028          add_custom_target(${COMPILER}_python_primes_001 ALL DEPENDS ${PY_PRIMES_BIN})
1029      endforeach()
1030  endif()
1031  
1032  # R first1000primes 001
1033  if(R_EXECUTABLE)
1034      foreach(COMPILER ${COMPILERS})
1035          set(R_PRIMES_WRAPPER ${TEST_SRC_DIR}/r/first1000primes/001/primes_wrapper.c)
1036          set(R_PRIMES_BIN ${TEST_BIN_DIR}/${COMPILER}/r/first1000primes/001/primes)
1037          file(MAKE_DIRECTORY ${TEST_BIN_DIR}/${COMPILER}/r/first1000primes/001)
1038          
1039          if(COMPILER STREQUAL "gcc")
1040              set(C_COMPILER ${GCC_C_EXECUTABLE})
1041          elseif(COMPILER STREQUAL "clang")
1042              set(C_COMPILER ${CLANG_C_EXECUTABLE})
1043          endif()
1044          
1045          add_custom_command(
1046              OUTPUT ${R_PRIMES_BIN}
1047              COMMAND ${C_COMPILER} ${R_PRIMES_WRAPPER} ${R_INCLUDE_FLAGS} ${R_LD_FLAGS} -o ${R_PRIMES_BIN}
1048              DEPENDS ${R_PRIMES_WRAPPER}
1049              COMMENT "Building R first1000primes/001 for ${COMPILER}..."
1050              VERBATIM
1051          )
1052          
1053          add_custom_target(${COMPILER}_r_primes_001 ALL DEPENDS ${R_PRIMES_BIN})
1054      endforeach()
1055  endif()