diff --git a/.gitignore b/.gitignore index b0c3f99..2f6bbc2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -# Prerequisites -*.d - # Object files *.o *.ko diff --git a/CMakeLists.txt b/CMakeLists.txt index 93f051a..5db41af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,27 @@ cmake_minimum_required(VERSION 2.8.9) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/cmake-d") INCLUDE(CheckIncludeFile) -project(Open-USB-Extreme) +project(Open-USB-Extreme D C) include_directories(include) # check headers check_include_file("stdint.h" HAVE_STDINT) if (HAVE_STDINT) - add_definitions(-DHAVE_STDINT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_STDINT") endif() check_include_file("stddef.h" HAVE_STDDEF) if (HAVE_STDDEF) - add_definitions(-DHAVE_STDDEF) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_STDDEF") endif() file(GLOB SOURCES "lib/*.c") +file(GLOB DSOURCES "lib/*.d") file(GLOB HEADERS "include/*.h") file(GLOB EXAMPLE_SOURCES "examples/*.c") set (CMAKE_CXX_STANDARD 89) #set(CMAKE_C_FLAGS "-Wall -pedantic -Wextra -Werror") -add_library(${PROJECT_NAME} SHARED ${SOURCES}) +set(CMAKE_D_FLAGS "${CMAKE_D_FLAGS} -betterC -O -release") +add_library(${PROJECT_NAME} SHARED ${DSOURCES} ${SOURCES}) add_executable(open-usbextreme-example ${EXAMPLE_SOURCES}) target_link_libraries(open-usbextreme-example ${PROJECT_NAME}) diff --git a/cmake/cmake-d/CMakeDCompiler.cmake.in b/cmake/cmake-d/CMakeDCompiler.cmake.in new file mode 100644 index 0000000..68398af --- /dev/null +++ b/cmake/cmake-d/CMakeDCompiler.cmake.in @@ -0,0 +1,51 @@ +# < 2.8.10 backward compatibility +if(NOT CMAKE_PLATFORM_INFO_DIR) + set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) +endif() + +set(CMAKE_D_COMPILER "@CMAKE_D_COMPILER@") +set(CMAKE_D_COMPILER_ARG1 "@CMAKE_D_COMPILER_ARG1@") +set(CMAKE_D_COMPILER_ID "@CMAKE_D_COMPILER_ID@") +set(CMAKE_D_PLATFORM_ID "@CMAKE_D_PLATFORM_ID@") +@SET_MSVC_D_ARCHITECTURE_ID@ +set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_LINKER "@CMAKE_LINKER@") +set(CMAKE_COMPILER_IS_GDC @CMAKE_COMPILER_IS_GDC@) +set(CMAKE_COMPILER_IS_DMD @CMAKE_COMPILER_IS_DMD@) +set(CMAKE_D_COMPILER_LOADED 1) +set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) +set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_D_COMPILER_ENV_VAR "DC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_D_SOURCE_FILE_EXTENSIONS d;di) +set(CMAKE_D_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +# Prefer to use D's linker. +# The D value 40 beats CXX value of 30 and C value of 10 +set(CMAKE_D_LINKER_PREFERENCE 40 ) +set(CMAKE_D_LINKER_PREFERENCE_PROPOGATES 1 ) +# Save compiler ABI information. +set(CMAKE_D_SIZEOF_DATA_PTR "@CMAKE_D_SIZEOF_DATA_PTR@") +set(CMAKE_D_COMPILER_ABI "@CMAKE_D_COMPILER_ABI@") + +if(CMAKE_D_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_D_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_D_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_D_COMPILER_ABI}") +endif() + +set(CMAKE_D_HAS_ISYSROOT "@CMAKE_D_HAS_ISYSROOT@") +@CMAKE_D_OSX_DEPLOYMENT_TARGET_FLAG_CODE@ + +set(CMAKE_D_IMPLICIT_LINK_LIBRARIES "@CMAKE_D_IMPLICIT_LINK_LIBRARIES@") +set(CMAKE_D_IMPLICIT_LINK_DIRECTORIES "@CMAKE_D_IMPLICIT_LINK_DIRECTORIES@") diff --git a/cmake/cmake-d/CMakeDCompilerABI.d b/cmake/cmake-d/CMakeDCompilerABI.d new file mode 100644 index 0000000..0689f5e --- /dev/null +++ b/cmake/cmake-d/CMakeDCompilerABI.d @@ -0,0 +1,9 @@ +enum int sizeof_dptr = (void*).sizeof; +string info_sizeof_dptr = "INFO" ~ ":" ~ "sizeof_dptr[" ~ sizeof_dptr.stringof ~ "]"; + +int main(string[] args) +{ + int require = 0; + require += info_sizeof_dptr[args.length]; + return require; +} diff --git a/cmake/cmake-d/CMakeDCompilerId.d.in b/cmake/cmake-d/CMakeDCompilerId.d.in new file mode 100644 index 0000000..70eb7c1 --- /dev/null +++ b/cmake/cmake-d/CMakeDCompilerId.d.in @@ -0,0 +1,39 @@ +version(DigitalMars) +{ + const string COMPILER_ID = "DigitalMars"; +} +else version(GNU) +{ + const string COMPILER_ID = "GNU"; +} +else version(LDC) +{ + const string COMPILER_ID = "LDC"; +} +else version(SDC) +{ + const string COMPILER_ID = "SDC"; +} +else +{ + const string COMPILER_ID = ""; +} + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +string info_compiler = "INFO" ~ ":" ~ "compiler[" ~ COMPILER_ID ~ "]"; + +@CMAKE_D_COMPILER_ID_PLATFORM_CONTENT@ + +/*--------------------------------------------------------------------------*/ + +int main(string[] args) +{ + int require = 0; + require += info_compiler[args.length]; + require += info_platform[args.length]; + require += info_arch[args.length]; + return require; +} diff --git a/cmake/cmake-d/CMakeDInformation.cmake b/cmake/cmake-d/CMakeDInformation.cmake new file mode 100644 index 0000000..8e5fa3a --- /dev/null +++ b/cmake/cmake-d/CMakeDInformation.cmake @@ -0,0 +1,286 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2013, Selman Ulug +# Tim Burrell +# Steve King +# Dragos Carp +# Konstantin Oblaukhov +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 CMakeCInformation.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +# This file sets the basic flags for the D language in CMake. +# It also loads the available platform file for the system-compiler +# if it exists. +# It also loads a system - compiler - processor (or target hardware) +# specific file, which is mainly useful for crosscompiling and embedded systems. + +# Load compiler-specific information. + +set(_INCLUDED_FILE 0) # reset the indicator if an include occurred. + +if(CMAKE_D_COMPILER_ID) + include(Compiler/${CMAKE_D_COMPILER_ID}-D OPTIONAL) +endif() + +# set(CMAKE_D_OUTPUT_EXTENSION .o) +set(CMAKE_C_OUTPUT_EXTENSION_REPLACE TRUE ) +set(CMAKE_D_OUTPUT_EXTENSION_REPLACE TRUE ) + +set(CMAKE_BASE_NAME) +get_filename_component(CMAKE_BASE_NAME ${CMAKE_D_COMPILER} NAME_WE) + +set(_INCLUDED_FILE 0) # reset the indicator if an include occurred. + +# load a hardware specific file, mostly useful for embedded compilers +if(CMAKE_SYSTEM_PROCESSOR) + if(CMAKE_D_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_D_COMPILER_ID}-D-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) + endif() + if(NOT _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) + endif() +endif() + +set(_INCLUDED_FILE 0) # reset the indicator if an include occurred. + +# load the system- and compiler specific files +if(CMAKE_D_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_D_COMPILER_ID}-D + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) +endif() + +# if no high specificity file was included, then try a more general one +if(NOT _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) +endif() + +# We specify the compiler information in the system file for some +# platforms, but this language may not have been enabled when the file +# was first included. Include it again to get the language info. +# Remove this when all compiler info is removed from system files. +if(NOT _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) +endif() + + +# This should be included before the _INIT variables are +# used to initialize the cache. Since the rule variables +# have if blocks on them, users can still define them here. +# But, it should still be after the platform file so changes can +# be made to those values. + +if(CMAKE_USER_MAKE_RULES_OVERRIDE) + include(${CMAKE_USER_MAKE_RULES_OVERRIDE}) +endif() + +if(CMAKE_USER_MAKE_RULES_OVERRIDE_D) + include(${CMAKE_USER_MAKE_RULES_OVERRIDE_D}) +endif() + +# Lines below was taken from CMakeCXXInformation.cmake +# Not all of this flags are available on D compilers for now, but some as OPTIONS_PIC are. + +if(NOT CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS) + set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS}) +endif() + +if(NOT CMAKE_D_COMPILE_OPTIONS_PIC) + set(CMAKE_DCOMPILE_OPTIONS_PIC ${CMAKE_D_COMPILE_OPTIONS_PIC}) +endif() + +if(NOT CMAKE_D_COMPILE_OPTIONS_PIE) + set(CMAKE_D_COMPILE_OPTIONS_PIE ${CMAKE_D_COMPILE_OPTIONS_PIE}) +endif() + +if(NOT CMAKE_D_COMPILE_OPTIONS_DLL) + set(CMAKE_D_COMPILE_OPTIONS_DLL ${CMAKE_D_COMPILE_OPTIONS_DLL}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_D_FLAGS) + set(CMAKE_SHARED_LIBRARY_D_FLAGS ${CMAKE_SHARED_LIBRARY_D_FLAGS}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_D_FLAGS) + set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_D_FLAGS}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG) + set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP) + set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG) + set(CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG}) +endif() + +if(NOT DEFINED CMAKE_EXE_EXPORTS_D_FLAG) + set(CMAKE_EXE_EXPORTS_D_FLAG ${CMAKE_EXE_EXPORTS_D_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_D_FLAG) + set(CMAKE_SHARED_LIBRARY_SONAME_D_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_D_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_D_FLAG) + set(CMAKE_EXECUTABLE_RUNTIME_D_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_D_FLAG_SEP) + set(CMAKE_EXECUTABLE_RUNTIME_D_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP}) +endif() + +if(NOT CMAKE_EXECUTABLE_RPATH_LINK_D_FLAG) + set(CMAKE_EXECUTABLE_RPATH_LINK_D_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH) + set(CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH}) +endif() + +if(NOT CMAKE_INCLUDE_FLAG_D) + set(CMAKE_INCLUDE_FLAG_D ${CMAKE_INCLUDE_FLAG_D}) +endif() + +if(NOT CMAKE_INCLUDE_FLAG_SEP_D) + set(CMAKE_INCLUDE_FLAG_SEP_D ${CMAKE_INCLUDE_FLAG_SEP_D}) +endif() + +# for most systems a module is the same as a shared library +# so unless the variable CMAKE_MODULE_EXISTS is set just +# copy the values from the LIBRARY variables +if(NOT CMAKE_MODULE_EXISTS) + set(CMAKE_SHARED_MODULE_D_FLAGS ${CMAKE_SHARED_LIBRARY_D_FLAGS}) + set(CMAKE_SHARED_MODULE_CREATE_D_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS}) +endif() + +# repeat for modules +if(NOT CMAKE_SHARED_MODULE_CREATE_D_FLAGS) + set(CMAKE_SHARED_MODULE_CREATE_D_FLAGS ${CMAKE_SHARED_MODULE_CREATE_D_FLAGS}) +endif() + +if(NOT CMAKE_SHARED_MODULE_D_FLAGS) + set(CMAKE_SHARED_MODULE_D_FLAGS ${CMAKE_SHARED_MODULE_D_FLAGS}) +endif() + +set(CMAKE_D_FLAGS_INIT "$ENV{DFLAGS} ${CMAKE_D_FLAGS_INIT}") +# avoid just having a space as the initial value for the cache +if(CMAKE_D_FLAGS_INIT STREQUAL " ") + set(CMAKE_D_FLAGS_INIT) +endif() +set(CMAKE_D_FLAGS "${CMAKE_D_FLAGS_INIT}" CACHE STRING + "Flags used by the D compiler during all build types.") + +if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) + # default build type is none + if(NOT CMAKE_NO_BUILD_TYPE) + set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING + "Choose the type of build, options are: None(CMAKE_D_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") + endif() + set(CMAKE_D_FLAGS_DEBUG "${CMAKE_D_FLAGS_DEBUG_INIT}" CACHE STRING + "Flags used by the compiler during debug builds.") + set(CMAKE_D_FLAGS_MINSIZEREL "${CMAKE_D_FLAGS_MINSIZEREL_INIT}" CACHE STRING + "Flags used by the compiler during release minsize builds.") + set(CMAKE_D_FLAGS_RELEASE "${CMAKE_D_FLAGS_RELEASE_INIT}" CACHE STRING + "Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files).") + set(CMAKE_D_FLAGS_RELWITHDEBINFO "${CMAKE_D_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING + "Flags used by the compiler during Release with Debug Info builds.") +endif() + +if(CMAKE_D_STANDARD_LIBRARIES_INIT) + set(CMAKE_D_STANDARD_LIBRARIES "${CMAKE_D_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all D applications.") + mark_as_advanced(CMAKE_D_STANDARD_LIBRARIES) +endif() + +include(CMakeCommonLanguageInclude) + +# now define the following rule variables + +# CMAKE_D_CREATE_SHARED_LIBRARY +# CMAKE_D_CREATE_SHARED_MODULE +# CMAKE_D_CREATE_STATIC_LIBRARY +# CMAKE_D_COMPILE_OBJECT +# CMAKE_D_LINK_EXECUTABLE + +# variables supplied by the generator at use time +# +# the target without the suffix +# +# +# +# +# (cmake 3.4.0 or later) +# + +# D compiler information +# +# +# +# + +# Static library tools +# +# + +# < 2.8.10 backward compatibility +if(NOT CMAKE_PLATFORM_INFO_DIR) + set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) +endif() + +# create a D shared library +if(NOT CMAKE_D_CREATE_SHARED_LIBRARY) + set(CMAKE_D_CREATE_SHARED_LIBRARY + " ${CMAKE_D_DASH_O} ${DSTDLIB_FLAGS} ${CMAKE_D_STDLIBS}") +endif() + +# create a D shared module just copy the shared library rule +if(NOT CMAKE_D_CREATE_SHARED_MODULE) + set(CMAKE_D_CREATE_SHARED_MODULE "${CMAKE_D_CREATE_SHARED_LIBRARY}") +endif() + +if(NOT CMAKE_D_CREATE_STATIC_LIBRARY AND CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS) + set(CMAKE_D_CREATE_STATIC_LIBRARY + " ${CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS} ${CMAKE_D_DASH_O}") +endif() + +# Create a static archive incrementally for large object file counts. +# If CMAKE_D_CREATE_STATIC_LIBRARY is set it will override these. +set(CMAKE_D_ARCHIVE_CREATE " cr ") +set(CMAKE_D_ARCHIVE_APPEND " r ") +set(CMAKE_D_ARCHIVE_FINISH " ") + +# compile a D file into an object file +if(NOT CMAKE_D_COMPILE_OBJECT) + if(CMAKE_VERSION VERSION_LESS 3.4.0) + set(CMAKE_D_COMPILE_OBJECT + " ${CMAKE_D_DASH_O} -c ") + else() + set(CMAKE_D_COMPILE_OBJECT + " ${CMAKE_D_DASH_O} -c ") + endif() +endif() + +if(NOT CMAKE_D_LINK_EXECUTABLE) + set(CMAKE_D_LINK_EXECUTABLE + " ${CMAKE_D_DASH_O} ${CMAKE_D_STDLIBS}") +endif() + +mark_as_advanced( + CMAKE_D_FLAGS + CMAKE_D_FLAGS_DEBUG + CMAKE_D_FLAGS_MINSIZEREL + CMAKE_D_FLAGS_RELEASE + CMAKE_D_FLAGS_RELWITHDEBINFO) + +set(CMAKE_D_INFORMATION_LOADED 1) diff --git a/cmake/cmake-d/CMakeDetermineDCompiler.cmake b/cmake/cmake-d/CMakeDetermineDCompiler.cmake new file mode 100644 index 0000000..d03f33b --- /dev/null +++ b/cmake/cmake-d/CMakeDetermineDCompiler.cmake @@ -0,0 +1,163 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2013, Selman Ulug +# Tim Burrell +# Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 CMakeDetermineCCompiler.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +# determine the compiler to use for D programs +# NOTE, a generator may set CMAKE_D_COMPILER before +# loading this file to force a compiler. +# use environment variable DC first if defined by user, next use +# the cmake variable CMAKE_GENERATOR_D which can be defined by a generator +# as a default compiler + +if(NOT CMAKE_D_COMPILER) + set(CMAKE_D_COMPILER_INIT NOTFOUND) + # prefer the environment variable DC + if($ENV{DC} MATCHES ".+") + get_filename_component(CMAKE_D_COMPILER_INIT $ENV{DC} PROGRAM PROGRAM_ARGS CMAKE_D_FLAGS_ENV_INIT) + if(CMAKE_D_FLAGS_ENV_INIT) + set(CMAKE_D_COMPILER_ARG1 "${CMAKE_D_FLAGS_ENV_INIT}" CACHE STRING "First argument to D compiler") + endif() + if(NOT EXISTS ${CMAKE_D_COMPILER_INIT}) + MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable C:\n$ENV{DC}.") + endif() + endif() + + # next try prefer the compiler specified by the generator + if(CMAKE_GENERATOR_D) + if(NOT CMAKE_D_COMPILER_INIT) + set(CMAKE_D_COMPILER_INIT ${CMAKE_GENERATOR_D}) + endif() + endif() + + # finally list compilers to try + if(CMAKE_D_COMPILER_INIT) + set(CMAKE_D_COMPILER_LIST ${CMAKE_D_COMPILER_INIT}) + else() + set(CMAKE_D_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}dmd ${_CMAKE_TOOLCHAIN_PREFIX}ldc2 ${_CMAKE_TOOLCHAIN_PREFIX}gdc) + endif() + + # Find the compiler. + if(_CMAKE_USER_D_COMPILER_PATH) + find_program(CMAKE_D_COMPILER NAMES ${CMAKE_D_COMPILER_LIST} PATHS ${_CMAKE_USER_D_COMPILER_PATH} DOC "D compiler" NO_DEFAULT_PATH) + endif() + find_program(CMAKE_D_COMPILER NAMES ${CMAKE_D_COMPILER_LIST} DOC "D compiler") + + if(CMAKE_D_COMPILER_INIT AND NOT CMAKE_D_COMPILER) + set(CMAKE_D_COMPILER "${CMAKE_D_COMPILER_INIT}" CACHE FILEPATH "D compiler" FORCE) + endif() +else() + + # we only get here if CMAKE_D_COMPILER was specified using -D or a pre-made CMakeCache.txt + # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE + # if CMAKE_D_COMPILER is a list of length 2, use the first item as + # CMAKE_D_COMPILER and the 2nd one as CMAKE_D_COMPILER_ARG1 + + list(LENGTH CMAKE_D_COMPILER _CMAKE_D_COMPILER_LIST_LENGTH) + if("${_CMAKE_D_COMPILER_LIST_LENGTH}" EQUAL 2) + list(GET CMAKE_D_COMPILER 1 CMAKE_D_COMPILER_ARG1) + list(GET CMAKE_D_COMPILER 0 CMAKE_D_COMPILER) + endif() + + # if a compiler was specified by the user but without path, + # now try to find it with the full path + # if it is found, force it into the cache, + # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND" + # if the C compiler already had a path, reuse it for searching the CXX compiler + get_filename_component(_CMAKE_USER_D_COMPILER_PATH "${CMAKE_D_COMPILER}" PATH) + if(NOT _CMAKE_USER_D_COMPILER_PATH) + find_program(CMAKE_D_COMPILER_WITH_PATH NAMES ${CMAKE_D_COMPILER}) + mark_as_advanced(CMAKE_D_COMPILER_WITH_PATH) + if(CMAKE_D_COMPILER_WITH_PATH) + set(CMAKE_D_COMPILER ${CMAKE_D_COMPILER_WITH_PATH} CACHE STRING "D compiler" FORCE) + endif() + endif() +endif() +mark_as_advanced(CMAKE_D_COMPILER) + +if(NOT _CMAKE_TOOLCHAIN_LOCATION) + get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_D_COMPILER}" PATH) +endif() + +# Build a small source file to identify the compiler. +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + set(CMAKE_D_COMPILER_ID_RUN 1) + set(CMAKE_D_PLATFORM_ID "Windows") + + # TODO: Set the compiler id. It is probably MSVC but + # the user may be using an integrated Intel compiler. + # set(CMAKE_D_COMPILER_ID "MSVC") +endif() + +if(NOT CMAKE_D_COMPILER_ID_RUN) + set(CMAKE_D_COMPILER_ID_RUN 1) + + # Each entry in this list is a set of extra flags to try + # adding to the compile line to see if it helps produce + # a valid identification file. + set(CMAKE_D_COMPILER_ID_TEST_FLAGS + # Try compiling to an object file only. + "-c" + ) + + # Try to identify the compiler. + set(CMAKE_D_COMPILER_ID) + find_file(CMAKE_PLATFORM_ID_CONTENT_FILE CMakePlatformId.di.in PATHS ${CMAKE_ROOT}/Modules + ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) + file(READ ${CMAKE_PLATFORM_ID_CONTENT_FILE} CMAKE_D_COMPILER_ID_PLATFORM_CONTENT) + find_file(CMAKE_D_COMPILER_ID_FILE_IN CMakeDCompilerId.d.in PATHS ${CMAKE_ROOT}/Modules + ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) + # Workaround for bug http://public.kitware.com/Bug/view.php?id=14481 + # if CMAKE_MODULE_PATH is used, then patch ${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake + get_filename_component(CMAKE_D_COMPILER_ID_FILE_IN_PATH ${CMAKE_D_COMPILER_ID_FILE_IN} PATH) + if(CMAKE_MAJOR_VERSION GREATER 2 OR CMAKE_D_COMPILER_ID_FILE_IN_PATH STREQUAL ${CMAKE_ROOT}/Modules) + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + else() + file(READ ${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT) + STRING(REPLACE "file(READ \${CMAKE_ROOT}/Modules/\${src}.in ID_CONTENT_IN)" + "find_file(src_in \${src}.in PATHS \${CMAKE_ROOT}/Modules \${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) + file(READ \${src_in} ID_CONTENT_IN) + unset(src_in CACHE)" + CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT_PATCHED ${CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT}) + file(WRITE ${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerId.cmake + ${CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT_PATCHED}) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerId.cmake) + endif() + CMAKE_DETERMINE_COMPILER_ID(D DFLAGS CMakeDCompilerId.d) + unset(CMAKE_D_COMPILER_ID_FILE_IN CACHE) + unset(CMAKE_PLATFORM_ID_CONTENT_FILE CACHE) + + # Set old compiler and platform id variables. + if("${CMAKE_D_COMPILER_ID}" MATCHES "GNU") + set(CMAKE_COMPILER_IS_GDC 1) + endif() + if("${CMAKE_D_PLATFORM_ID}" MATCHES "MinGW") + set(CMAKE_COMPILER_IS_MINGW 1) + elseif("${CMAKE_D_PLATFORM_ID}" MATCHES "Cygwin") + set(CMAKE_COMPILER_IS_CYGWIN 1) + endif() +endif() + +include(CMakeFindBinUtils) +if(MSVC_D_ARCHITECTURE_ID) + set(SET_MSVC_D_ARCHITECTURE_ID + "set(MSVC_D_ARCHITECTURE_ID ${MSVC_D_ARCHITECTURE_ID})") +endif() +# configure variables set in this file for fast reload later on +find_file(CMAKE_D_COMPILER_CMAKE_IN CMakeDCompiler.cmake.in PATHS ${CMAKE_ROOT}/Modules + ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) +configure_file(${CMAKE_D_COMPILER_CMAKE_IN} + ${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake + @ONLY IMMEDIATE # IMMEDIATE must be here for compatibility mode <= 2.0 + ) +set(CMAKE_D_COMPILER_ENV_VAR "DC") diff --git a/cmake/cmake-d/CMakeLists.txt b/cmake/cmake-d/CMakeLists.txt new file mode 100644 index 0000000..e8301a1 --- /dev/null +++ b/cmake/cmake-d/CMakeLists.txt @@ -0,0 +1,43 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2013, Selman Ulug +# Tim Burrell +# Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# +cmake_minimum_required(VERSION 2.8.1) +project(cmake-d NONE) + +set(MOD_SRCS + CMakeDCompiler.cmake.in + CMakeDCompilerId.d.in + CMakeDInformation.cmake + CMakeDCompilerABI.d + CMakeTestDCompiler.cmake + CMakeDetermineDCompiler.cmake + FindGDCPath.cmake + UseDDoc.cmake + UseDDeps.cmake + UseDub.cmake + dependencies.cmake + UseDUnittest.cmake + FindPhobos.cmake + CMakePlatformId.di.in +) + +set(PLAT_SRCS + Platform/Darwin-dmd.cmake + Platform/Darwin-ldc2.cmake + Platform/Linux-dmd.cmake + Platform/Linux-gdc.cmake + Platform/Linux-ldc2.cmake + Platform/Windows-dmd.cmake + Platform/Windows-gdc.cmake +) + +install(FILES ${MOD_SRCS} DESTINATION ${CMAKE_ROOT}/Modules) +install(FILES ${PLAT_SRCS} DESTINATION ${CMAKE_ROOT}/Modules/Platform) diff --git a/cmake/cmake-d/CMakePlatformId.di.in b/cmake/cmake-d/CMakePlatformId.di.in new file mode 100644 index 0000000..a6b87a9 --- /dev/null +++ b/cmake/cmake-d/CMakePlatformId.di.in @@ -0,0 +1,118 @@ +/* Identify known platforms by name. */ +version(linux) +{ + const string PLATFORM_ID = "Linux"; +} +else version(Cygwin) +{ + const string PLATFORM_ID = "Cygwin"; +} +else version(MinGW) +{ + const string PLATFORM_ID = "MinGW"; +} +else version(OSX) +{ + const string PLATFORM_ID = "Darwin"; +} +else version(Windows) +{ + const string PLATFORM_ID = "Windows"; +} +else version(FreeBSD) +{ + const string PLATFORM_ID = "FreeBSD"; +} +else version(NetBSD) +{ + const string PLATFORM_ID = "NetBSD"; +} +else version(OpenBSD) +{ + const string PLATFORM_ID = "OpenBSD"; +} +else version(NetBSD) +{ + const string PLATFORM_ID = "NetBSD"; +} +else version(Solaris) +{ + const string PLATFORM_ID = "SunOS"; +} +else version(AIX) +{ + const string PLATFORM_ID = "AIX"; +} +else version(Haiku) +{ + const string PLATFORM_ID = "Haiku"; +} +else version(AIX) +{ + const string PLATFORM_ID = "BeOS"; +} +else version(AIX) +{ + const string PLATFORM_ID = "QNX"; +} +else version(AIX) +{ + const string PLATFORM_ID = "Tru64"; +} +else version(AIX) +{ + const string PLATFORM_ID = "RISCos"; +} +else +{ + const string PLATFORM_ID = ""; +} + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +version(IA64) +{ + const string ARCHITECTURE_ID = "IA64"; +} +else version(X86_64) +{ + const string ARCHITECTURE_ID = "x64"; +} +else version(X86) +{ + const string ARCHITECTURE_ID = "X86"; +} +else version(ARM) +{ + const string ARCHITECTURE_ID = "ARM"; +} +else version(MIPS32) +{ + const string ARCHITECTURE_ID = "MIPS"; +} +else version(MIPS64) +{ + const string ARCHITECTURE_ID = "MIPS"; +} +else version(SH) +{ + const string ARCHITECTURE_ID = "SHx"; +} +else version(SH64) +{ + const string ARCHITECTURE_ID = "SHx"; +} +else +{ + const string ARCHITECTURE_ID = ""; +} + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +string info_platform = "INFO" ~ ":" ~ "platform[" ~ PLATFORM_ID ~ "]"; +string info_arch = "INFO" ~ ":" ~ "arch[" ~ ARCHITECTURE_ID ~ "]"; diff --git a/cmake/cmake-d/CMakeTestDCompiler.cmake b/cmake/cmake-d/CMakeTestDCompiler.cmake new file mode 100644 index 0000000..493dfcb --- /dev/null +++ b/cmake/cmake-d/CMakeTestDCompiler.cmake @@ -0,0 +1,82 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 CMakeTestCCompiler.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +include(CMakeTestCompilerCommon) + +# Remove any cached result from an older CMake version. +# We now store this in CMakeCCompiler.cmake. +unset(CMAKE_D_COMPILER_WORKS CACHE) + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that that selected D compiler can actually compile +# and link the most basic of programs. If not, a fatal error +# is set and cmake stops processing commands and will not generate +# any makefiles or projects. +if(NOT CMAKE_D_COMPILER_WORKS) + PrintTestCompilerStatus("D" "") + file(WRITE ${CMAKE_PLATFORM_INFO_DIR}/CMakeTmp/testDCompiler.d + "int main(char[][] args)\n" + "{return args.sizeof-1;}\n") + try_compile(CMAKE_D_COMPILER_WORKS ${CMAKE_BINARY_DIR} + ${CMAKE_PLATFORM_INFO_DIR}/CMakeTmp/testDCompiler.d + OUTPUT_VARIABLE OUTPUT) + set(D_TEST_WAS_RUN 1) +endif() + +if(NOT CMAKE_D_COMPILER_WORKS) + PrintTestCompilerStatus("D" " -- broken") + message(STATUS "To force a specific D compiler set the DC environment variable") + message(STATUS " ie - export DC=\"/usr/bin/dmd\"") + file(APPEND ${CMAKE_PLATFORM_INFO_DIR}/CMakeError.log + "Determining if the D compiler works failed with " + "the following output:\n${OUTPUT}\n\n") + # if the compiler is broken make sure to remove the platform file + # since Windows-cl configures both c/cxx files both need to be removed + # when c or c++ fails + file(REMOVE ${CMAKE_PLATFORM_INFO_DIR}/CMakeDPlatform.cmake) + message(FATAL_ERROR "The D compiler \"${CMAKE_D_COMPILER}\" " + "is not able to compile a simple test program.\nIt fails " + "with the following output:\n ${OUTPUT}\n\n" + "CMake will not be able to correctly generate this project.") +else() + if(D_TEST_WAS_RUN) + message(STATUS "Check for working D compiler: ${CMAKE_D_COMPILER} -- works") + file(APPEND ${CMAKE_PLATFORM_INFO_DIR}/CMakeOutput.log + "Determining if the D compiler works passed with " + "the following output:\n${OUTPUT}\n\n") + endif() + set(CMAKE_D_COMPILER_WORKS 1 CACHE INTERNAL "") + + if(CMAKE_D_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + else() + # Try to identify the ABI and configure it into CMakeDCompiler.cmake + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) + find_file(CMAKE_D_COMPILER_ABI_SRC CMakeDCompilerABI.d PATHS ${CMAKE_ROOT}/Modules + ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) + CMAKE_DETERMINE_COMPILER_ABI(D ${CMAKE_D_COMPILER_ABI_SRC}) + find_file(CMAKE_D_COMPILER_CMAKE_IN CMakeDCompiler.cmake.in PATHS ${CMAKE_ROOT}/Modules + ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) + configure_file( + ${CMAKE_D_COMPILER_CMAKE_IN} + ${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake + @ONLY IMMEDIATE # IMMEDIATE must be here for compatibility mode <= 2.0 + ) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake) + unset(CMAKE_D_COMPILER_ABI_SRC CACHE) + unset(CMAKE_D_COMPILER_CMAKE_IN CACHE) + endif() +endif() diff --git a/cmake/cmake-d/FindGDCPath.cmake b/cmake/cmake-d/FindGDCPath.cmake new file mode 100644 index 0000000..e9f42aa --- /dev/null +++ b/cmake/cmake-d/FindGDCPath.cmake @@ -0,0 +1,46 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2013, Selman Ulug +# Tim Burrell +# Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# +# - Find GDC Include Path +# +# GDC_INCLUDE_PATH = path to where object.d is found +# + +set(GDC_POSSIBLE_INCLUDE_PATHS + /usr/include/d/4.8.2 + /usr/include/d/4.8.1 + /usr/include/d/4.8.0 + /usr/include/d/4.7.3 + /usr/include/d/4.7.2 + /usr/include/d/4.7.1 + /usr/include/d/4.7.0 + /usr/include/d/4.2.1 + /usr/include/d/4.2.0 + /usr/include/d/4.1.2 + /usr/include/d/4.1.1 + /usr/include/d/4.1.0 + /usr/include/d/4.0.4 + /usr/include/d/4.0.3 + /usr/include/d/4.0.2 + /usr/include/d/4.0.1 + /usr/include/d/4.0.0 + /usr/include/d/4.0.6 + /usr/include/d/4.0.5 + /usr/include/d/3.4.4 + /usr/include/d/3.4.3 + /usr/include/d/3.4.2 + /usr/include/d/3.4.1 + /usr/include/d/3.4.0) + +find_path(GDC_INCLUDE_PATH object.d + ${GDC_POSSIBLE_INCLUDE_PATHS}) + +mark_as_advanced(GDC_INCLUDE_PATH) diff --git a/cmake/cmake-d/FindPhobos.cmake b/cmake/cmake-d/FindPhobos.cmake new file mode 100644 index 0000000..25691a9 --- /dev/null +++ b/cmake/cmake-d/FindPhobos.cmake @@ -0,0 +1,5 @@ +find_path(PHOBOS_INCLUDE_DIR std/file.d) +find_library(PHOBOS_LIBRARY phobos2) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Phobos DEFAULT_MSG PHOBOS_LIBRARY PHOBOS_INCLUDE_DIR) diff --git a/cmake/cmake-d/Platform/Darwin-dmd.cmake b/cmake/cmake-d/Platform/Darwin-dmd.cmake new file mode 100644 index 0000000..6894491 --- /dev/null +++ b/cmake/cmake-d/Platform/Darwin-dmd.cmake @@ -0,0 +1,67 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +#set(DSTDLIB_FLAGS "-version=Phobos") +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-D -Dddocumentation") + # foreach(item ${CMAKE_D_DDOC_FILES}) + # set(DDOC_FLAGS "${DDOC_FLAGS} ${item}") + # endforeach() +endif() + +set(CMAKE_D_OUTPUT_EXTENSION .o) +set(CMAKE_D_DASH_O "-of") +set(CMAKE_BASE_NAME dmd) + +set(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib") + +set(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic +set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared -defaultlib=libphobos2.so") # -shared +set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty +set(CMAKE_SHARED_LIBRARY_SONAME_D_FLAG "-L-soname=") +set(CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG "-L-rpath=") +set(CMAKE_INCLUDE_FLAG_D "-I") # -I +set(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty +set(CMAKE_LIBRARY_PATH_FLAG "-L-L") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/" +set(CMAKE_LINK_LIBRARY_FLAG "-L-l") + +set(CMAKE_D_COMPILE_OPTIONS_PIC "-fPIC") + +set(CMAKE_LINK_LIBRARY_SUFFIX "") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_EXECUTABLE_SUFFIX "") # .exe +set(CMAKE_DL_LIBS "dl") + +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") + +# set(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm -defaultlib=libphobos2.so") + +# set(CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}") +set(CMAKE_D_FLAGS_INIT "") + +set(CMAKE_D_LINK_FLAGS "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g -debug -L-export_dynamic ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-O -L-s ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L-export_dynamic ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -of") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") diff --git a/cmake/cmake-d/Platform/Darwin-ldc2.cmake b/cmake/cmake-d/Platform/Darwin-ldc2.cmake new file mode 100644 index 0000000..4d17aa9 --- /dev/null +++ b/cmake/cmake-d/Platform/Darwin-ldc2.cmake @@ -0,0 +1,63 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +# set(DSTDLIB_FLAGS "-version=Phobos") +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-D -Dddocumentation") + # foreach(item ${CMAKE_D_DDOC_FILES}) + # set(DDOC_FLAGS "${DDOC_FLAGS} ${item}") + # endforeach() +endif() + +set(CMAKE_D_OUTPUT_EXTENSION .o) +set(CMAKE_D_DASH_O "-of") +set(CMAKE_BASE_NAME ldc2) + +set(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib") + +set(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic +set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared") # -shared +set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty +set(CMAKE_INCLUDE_FLAG_D "-I") # -I +set(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty +set(CMAKE_LIBRARY_PATH_FLAG "-L-L") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/" +set(CMAKE_LINK_LIBRARY_FLAG "-L-l") + +set(CMAKE_LINK_LIBRARY_SUFFIX "") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_EXECUTABLE_SUFFIX "") # .exe +set(CMAKE_DL_LIBS "dl") + +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") + +# set(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm" ) + +# set(CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}") +set(CMAKE_D_FLAGS_INIT "") +# DMD can only produce 32-bit binaries for now +set(CMAKE_D_LINK_FLAGS "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g -d-debug -L-export_dynamic ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O -release ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L-export_dynamic ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -of") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") diff --git a/cmake/cmake-d/Platform/Linux-dmd.cmake b/cmake/cmake-d/Platform/Linux-dmd.cmake new file mode 100644 index 0000000..1cf610c --- /dev/null +++ b/cmake/cmake-d/Platform/Linux-dmd.cmake @@ -0,0 +1,67 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +#set(DSTDLIB_FLAGS "-version=Phobos") +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-D -Dddocumentation") + # foreach(item ${CMAKE_D_DDOC_FILES}) + # set(DDOC_FLAGS "${DDOC_FLAGS} ${item}") + # endforeach() +endif() + +set(CMAKE_D_OUTPUT_EXTENSION .o) +set(CMAKE_D_DASH_O "-of") +set(CMAKE_BASE_NAME dmd) + +set(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib") + +set(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic +set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared -defaultlib=libphobos2.so") # -shared +set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty +set(CMAKE_SHARED_LIBRARY_SONAME_D_FLAG "-L-soname=") +set(CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG "-L-rpath=") +set(CMAKE_INCLUDE_FLAG_D "-I") # -I +set(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty +set(CMAKE_LIBRARY_PATH_FLAG "-L-L") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/" +set(CMAKE_LINK_LIBRARY_FLAG "-L-l") + +set(CMAKE_D_COMPILE_OPTIONS_PIC "-fPIC") + +set(CMAKE_LINK_LIBRARY_SUFFIX "") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_EXECUTABLE_SUFFIX "") # .exe +set(CMAKE_DL_LIBS "dl") + +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") + +# set(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm -defaultlib=libphobos2.so") + +# set(CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}") +set(CMAKE_D_FLAGS_INIT "") + +set(CMAKE_D_LINK_FLAGS "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g -debug -L--export-dynamic ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-O -L-s ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L--export-dynamic ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -of") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") diff --git a/cmake/cmake-d/Platform/Linux-gdc.cmake b/cmake/cmake-d/Platform/Linux-gdc.cmake new file mode 100644 index 0000000..0f31c26 --- /dev/null +++ b/cmake/cmake-d/Platform/Linux-gdc.cmake @@ -0,0 +1,41 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +set(CMAKE_D_DASH_O "-o") +set(CMAKE_BASE_NAME gdc) + +if(CMAKE_D_USE_TANGO) + set(DSTDLIB_FLAGS "-fversion=Tango") +endif() +if(CMAKE_D_USE_PHOBOS) + set(DSTDLIB_FLAGS "-fversion=Phobos") +endif() +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-fdoc -fdoc-dir=documentation") + foreach(item ${CMAKE_D_DDOC_FILES}) + set(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}") + endforeach() +endif() + +# SET(CMAKE_D_FLAGS_INIT "-fversion=Posix -fversion=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS}") +set(CMAKE_D_FLAGS_INIT "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -o ") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") + +set(CMAKE_INCLUDE_FLAG_D "-I") # -I diff --git a/cmake/cmake-d/Platform/Linux-ldc2.cmake b/cmake/cmake-d/Platform/Linux-ldc2.cmake new file mode 100644 index 0000000..7b06a80 --- /dev/null +++ b/cmake/cmake-d/Platform/Linux-ldc2.cmake @@ -0,0 +1,63 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +# set(DSTDLIB_FLAGS "-version=Phobos") +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-D -Dddocumentation") + # foreach(item ${CMAKE_D_DDOC_FILES}) + # set(DDOC_FLAGS "${DDOC_FLAGS} ${item}") + # endforeach() +endif() + +set(CMAKE_D_OUTPUT_EXTENSION .o) +set(CMAKE_D_DASH_O "-of") +set(CMAKE_BASE_NAME ldc2) + +set(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib") + +set(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic +set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared") # -shared +set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty +set(CMAKE_INCLUDE_FLAG_D "-I") # -I +set(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty +set(CMAKE_LIBRARY_PATH_FLAG "-L-L") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/" +set(CMAKE_LINK_LIBRARY_FLAG "-L-l") + +set(CMAKE_LINK_LIBRARY_SUFFIX "") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_EXECUTABLE_SUFFIX "") # .exe +set(CMAKE_DL_LIBS "dl") + +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") + +# set(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm" ) + +# set(CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}") +set(CMAKE_D_FLAGS_INIT "") +# DMD can only produce 32-bit binaries for now +set(CMAKE_D_LINK_FLAGS "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g -d-debug -L--export-dynamic ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O -release ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L--export-dynamic ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -of") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") diff --git a/cmake/cmake-d/Platform/Windows-dmd.cmake b/cmake/cmake-d/Platform/Windows-dmd.cmake new file mode 100644 index 0000000..def1fd3 --- /dev/null +++ b/cmake/cmake-d/Platform/Windows-dmd.cmake @@ -0,0 +1,56 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +#set(DSTDLIB_FLAGS "-version=Phobos") +IF(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-D -Dddocumentation") + # foreach(item ${CMAKE_D_DDOC_FILES}) + # set(DDOC_FLAGS "${DDOC_FLAGS} ${item}") + # endforeach() +endif() + +set(CMAKE_D_OUTPUT_EXTENSION .obj) +set(CMAKE_D_DASH_O "-of") +set(CMAKE_BASE_NAME dmd) + +set(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib") + +set(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic +set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared") # -shared +set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath +set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty +set(CMAKE_INCLUDE_FLAG_D "-I") # -I +set(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty +set(CMAKE_LIBRARY_PATH_FLAG "-L-L") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/" + +set(CMAKE_LINK_LIBRARY_FLAG "-L-l") +set(CMAKE_STATIC_LIBRARY_PREFIX "") # +set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib") # lib +set(CMAKE_SHARED_LIBRARY_PREFIX "") # +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") # .dll +set(CMAKE_EXECUTABLE_SUFFIX ".exe") # .exe +set(CMAKE_DL_LIBS "dl") + +set(CMAKE_FIND_LIBRARY_PREFIXES "") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll") + +set(CMAKE_D_FLAGS_INIT "") +# DMD can only produce 32-bit binaries for now +set(CMAKE_D_LINK_FLAGS "") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g -debug ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g ${DDOC_FLAGS}") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -of") diff --git a/cmake/cmake-d/Platform/Windows-gdc.cmake b/cmake/cmake-d/Platform/Windows-gdc.cmake new file mode 100644 index 0000000..a476fe3 --- /dev/null +++ b/cmake/cmake-d/Platform/Windows-gdc.cmake @@ -0,0 +1,35 @@ +# +# CMakeD - CMake module for D Language +# +# Copyright (c) 2007, Selman Ulug +# Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# +# Modified from CMake 2.6.5 gcc.cmake +# See http://www.cmake.org/HTML/Copyright.html for details +# + +if(CMAKE_D_USE_TANGO) + set(DSTDLIB_FLAGS "-fversion=Tango") +endif() +if(CMAKE_D_USE_PHOBOS) + set(DSTDLIB_FLAGS "-fversion=Phobos") +endif() +if(CMAKE_D_BUILD_DOCS) + set(DDOC_FLAGS "-fdoc -fdoc-dir=documentation") + foreach(item ${CMAKE_D_DDOC_FILES}) + set(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}") + endforeach() +endif() + +set(CMAKE_D_FLAGS_INIT "-fversion=Win -fversion=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS}") +set(CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}") +set(CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}") +# set(CMAKE_D_CREATE_PREPROCESSED_SOURCE " -E > ") +set(CMAKE_D_CREATE_ASSEMBLY_SOURCE " -S -o ") +# set(CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ") diff --git a/cmake/cmake-d/UseDDeps.cmake b/cmake/cmake-d/UseDDeps.cmake new file mode 100644 index 0000000..41284f5 --- /dev/null +++ b/cmake/cmake-d/UseDDeps.cmake @@ -0,0 +1,63 @@ +# Dependency tracking for D +# +# Copyright (c) 2010 Jens Mueller +# +# All rights reserved. +# +# See LICENSE for details. +# + +macro(add_executable_with_dependencies _target) + # extract D source files from arguments + foreach(file ${ARGV}) + if(${file} MATCHES "\\.d$") + list(APPEND d_source_files ${file}) + endif() + endforeach() + + #message("D files in arguments: ${d_source_files}") + + foreach(file IN LISTS d_source_files) + set(source_file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") + set(dependency_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${file}-depend.cmake") + set(dependency_files ${dependency_files} ${dependency_file}) + + #message("Checking dependencies for ${source_file}") + #message("Put into ${dependency_file}") + # TODO + # better way to get the included directories + get_directory_property(include_dirs INCLUDE_DIRECTORIES) + set(INCLUDES ) + foreach(include_dir IN LISTS include_dirs) + list(APPEND INCLUDES "${CMAKE_INCLUDE_FLAG_D}${include_dir}") + endforeach() + + execute_process( + COMMAND ${CMAKE_COMMAND} + -D "CMAKE_D_COMPILER:STRING=${CMAKE_D_COMPILER}" + -D "CMAKE_D_FLAGS:STRING=${CMAKE_D_FLAGS}" + -D "include_directories:STRING=${INCLUDES}" + -D "source_file:STRING=${source_file}" + -D "dependency_file:STRING=${dependency_file}" + -P "${CMAKE_ROOT}/Modules/dependencies.cmake" # TODO hard coded path + ) + + # load dependencies from file + include(${dependency_file}) + #message("DEPENDENCIES ${D_DMD_DEPEND}") + + add_custom_command( + OUTPUT ${dependency_file} + DEPENDS ${D_DMD_DEPEND} + COMMAND ${CMAKE_COMMAND} + -D "CMAKE_D_COMPILER:STRING=${CMAKE_D_COMPILER}" + -D "CMAKE_D_FLAGS:STRING=${CMAKE_D_FLAGS}" + -D "include_directories:STRING=${INCLUDES}" + -D "source_file:STRING=${source_file}" + -D "dependency_file:STRING=${dependency_file}" + -P "${CMAKE_ROOT}/Modules/dependencies.cmake" # TODO hard coded path + COMMENT "Scanning for dependencies") + endforeach() + + add_executable(${ARGV} ${dependency_files}) +endmacro() diff --git a/cmake/cmake-d/UseDDoc.cmake b/cmake/cmake-d/UseDDoc.cmake new file mode 100644 index 0000000..5fc6cc6 --- /dev/null +++ b/cmake/cmake-d/UseDDoc.cmake @@ -0,0 +1,72 @@ +# check if the user wants to build ddocs +# +# Copyright (c) 2007 Tim Burrell +# +# All rights reserved. +# +# See LICENSE for details. +# + +# Do not build documentation by default +if(NOT CMAKE_D_BUILD_DOCS) + set(CMAKE_D_BUILD_DOCS False CACHE BOOLEAN TRUE FORCE) +else() + # check for specified ddoc files + # default to the candydoc usual + set(CMAKE_D_BUILD_DOCS True CACHE BOOLEAN FALSE FORCE) + if(NOT CMAKE_D_DDOC_FILES) + set(CMAKE_D_DDOC_FILES "documentation/candydoc/candy.ddoc;documentation/candydoc/modules.ddoc" CACHE STRING FALSE FORCE) + else() + set(CMAKE_D_DDOC_FILES "${CMAKE_D_DDOC_FILES}" CACHE STRING FALSE FORCE) + endif() + + # copy the candydoc files + file(GLOB_RECURSE CANDY_DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/candydoc/*") + foreach(item ${CANDY_DOC_FILES}) + string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item}) + configure_file(${item} ${CMAKE_CURRENT_BINARY_DIR}/documentation/${item} COPYONLY) + endforeach() + + # create modules.ddoc + file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/*.d") + set(first True) + foreach(item ${sources}) + # first make sure we're not config.d + string(REGEX MATCH "config\\.d" ignore ${item}) + if(NOT ${ignore} MATCHES "") + # fix up the output + string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item}) + string(REGEX REPLACE "\\.d" ".html" htmlFile ${item}) + string(REGEX REPLACE "^.*/" "" htmlFile ${htmlFile}) + string(REGEX REPLACE "\\.d" "" item ${item}) + string(REGEX REPLACE "/" "." item ${item}) + if(first) + set(modules "${item}") + set(first False) + set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE) + else() + set(modules "${modules};${item}") + set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_D_DDOC_CLEAN_FILES}" "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE) + endif() + endif() + endforeach() + + # create formatted modules string + set(modString "MODULES = \n") + foreach(item ${modules}) + set(modString "${modString}\t$(MODULE ${item})\n") + endforeach() + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/documentation/candydoc/modules.ddoc" ${modString}) + + # create index.html + set(modString "${PROJECT_NAME} API Documentation\n") + set(modString "${PROJECT_NAME} API Documentation:
\n") + set(modString "${modString}
    \n") + foreach(item ${modules}) + string(REGEX REPLACE "[a-z0-9]*\\." "" filename ${item}) + set(modString "${modString}\t
  • ${item}
  • \n") + endforeach() + set(modString "${modString}
\n") + set(modString "${modString}\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/documentation/index.html" ${modString}) +endif() diff --git a/cmake/cmake-d/UseDUnittest.cmake b/cmake/cmake-d/UseDUnittest.cmake new file mode 100644 index 0000000..f564bf6 --- /dev/null +++ b/cmake/cmake-d/UseDUnittest.cmake @@ -0,0 +1,75 @@ +# Adding D unittests +# +# Copyright (c) 2010 Jens Mueller +# +# All rights reserved. +# +# See LICENSE for details. +# + +macro(_add_unittests _TEST_TARGET _SOURCES _INCLUDE_DIRECTORIES _LINK_LIBRARIES) + set(_TEST_FLAGS "${CMAKE_D_FLAGS_DEBUG_INIT}") + separate_arguments(_TEST_FLAGS) + + set(_TEST_MAIN "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/unittest.d") + if(NOT EXISTS ${_TEST_MAIN}) + file(WRITE ${_TEST_MAIN} "// Generated by UseDUnittest.cmake\nint main() { return 0; }") + endif() + + #if(_INCLUDE_DIRECTORIES) + set(_TEST_INCLUDE_DIRECTORIES ) + foreach(_INCLUDE_DIRECTORY ${_INCLUDE_DIRECTORIES}) + if(_INCLUDE_DIRECTORY) # since commented out if doesn't work for some reason + list(APPEND _TEST_INCLUDE_DIRECTORIES "${CMAKE_INCLUDE_FLAG_D}${_INCLUDE_DIRECTORY}") + endif() + endforeach() + #endif() + + #if(_LINK_LIBRARIES) + set(_TEST_LINK_LIBRARIES ) + foreach(_LINK_LIBRARY ${_LINK_LIBRARIES}) + if(_LINK_LIBRARY) # since commented out if doesn't work for some reason + list(APPEND _TEST_LINK_LIBRARIES "${CMAKE_LINK_LIBRARY_FLAG}${_LINK_LIBRARY}") + endif() + endforeach() + #endif() + + set(_TEST_SOURCES ) + foreach(_SOURCE ${_SOURCES}) + list(APPEND _TEST_LINK_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/${_SOURCE}") + endforeach() + + if(CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(_TEST_LIBRARY_PATH "${CMAKE_LIBRARY_PATH_FLAG}${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") + endif() + + add_test(NAME build_${_TEST_TARGET} + COMMAND ${CMAKE_D_COMPILER} ${_TEST_FLAGS} ${_TEST_INCLUDE_DIRECTORIES} ${_TEST_LIBRARY_PATH} ${_TEST_LINK_LIBRARIES} -of${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_TEST_TARGET} ${_TEST_SOURCES} -unittest ${_TEST_MAIN}) + + add_test(NAME ${_TEST_TARGET} + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_TEST_TARGET}) + set_tests_properties(${_TEST_TARGET} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") +endmacro() + +macro(add_unittests_for_target _TARGET) + set(_TEST_TARGET "test_${_TARGET}") + + get_target_property(_TARGET_TEST_SOURCES ${_TARGET} SOURCES) + if(_TARGET_TEST_SOURCES) + get_target_property(_TARGET_INCLUDE_DIRECTORIES ${_TARGET} INCLUDE_DIRECTORIES) + get_target_property(_TARGET_LINK_LIBRARIES ${_TARGET} LINK_LIBRARIES) + + _add_unittests(${_TEST_TARGET} "${_TARGET_TEST_SOURCES}" "${_TARGET_INCLUDE_DIRECTORIES}" "${_TARGET_LINK_LIBRARIES}") + else() + message(SEND_ERROR "cannot add unittests for target ${TARGET }with no source files") + endif() +endmacro() + +macro(add_unittests _SOURCE) + set(_TEST_TARGET "test_${_SOURCE}") + + get_directory_property(_INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES) + get_directory_property(_LINK_LIBRARIES LINK_LIBRARIES) + + _add_unittests(${_TEST_TARGET} "${_SOURCE}" "${_INCLUDE_DIRECTORIES}" "${_LINK_LIBRARIES}") +endmacro() diff --git a/cmake/cmake-d/UseDub.cmake b/cmake/cmake-d/UseDub.cmake new file mode 100644 index 0000000..18da419 --- /dev/null +++ b/cmake/cmake-d/UseDub.cmake @@ -0,0 +1,84 @@ +# This modules add functions for downloading and building dub dependencies. +# This code sets the following variables and functions: +# +# DUB_DIRECTORY = the full path to Dub pacakges +# +# DubProject_Add( [version]) +# +#============================================================================ +# Copyright (c) 2014 Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# + +if(NOT DUB_DIRECTORY) + set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages directory") +endif() + +set(DUB_REGISTRY "http://code.dlang.org/packages") +file(MAKE_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + +if(NOT CMAKE_D_COMPILER) + message(FATAL_ERROR "UseDub needs a D compiler or use it in a D project.") +endif() + +#compile json parsers +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl) + find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + find_file(SEMVER_SRC "semver.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + get_filename_component(SEMVER_PATH ${SEMVER_SRC} PATH) + execute_process(COMMAND ${CMAKE_D_COMPILER} -I${SEMVER_PATH} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC} + WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + unset(DUB_GET_PACKAGE_URL_D_SRC CACHE) +endif() +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake) + find_file(DUB_PACKAGE_TO_CMAKE_D_SRC "DubToCMake.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_PACKAGE_TO_CMAKE_D_SRC} + WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + unset(DUB_PACKAGE_TO_CMAKE_D_SRC CACHE) +endif() + +include(ExternalProject) + +function(DubProject_Add name) + if(NOT EXISTS ${DUB_DIRECTORY}/${name}.json) + file(DOWNLOAD ${DUB_REGISTRY}/${name}.json ${DUB_DIRECTORY}/${name}.json STATUS status) + list(GET status 0 statusCode) + + if(NOT statusCode EQUAL 0) + file(REMOVE ${DUB_DIRECTORY}/${name}.json) + message(FATAL_ERROR "Failed to download ${DUB_REGISTRY}/${name}.json") + endif() + endif() + + if(${ARGC} GREATER 1) + execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json -t ${ARGN} + WORKING_DIRECTORY ${DUB_DIRECTORY}) + else() + execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json + WORKING_DIRECTORY ${DUB_DIRECTORY}) + endif() + + include(${DUB_DIRECTORY}/${name}.cmake) + + ExternalProject_Add(${name} + DOWNLOAD_DIR ${DUB_DIRECTORY}/archive/${name} + SOURCE_DIR ${DUB_DIRECTORY}/source/${name} + URL ${DUB_PACKAGE_URL} + PATCH_COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubToCMake -p package.json + INSTALL_DIR ${DUB_DIRECTORY}/export + CMAKE_CACHE_ARGS + -DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH} + -DCMAKE_INSTALL_PREFIX:PATH= + -DDUB_DIRECTORY:PATH=${DUB_DIRECTORY}) + + include_directories(${DUB_DIRECTORY}/source/${name}/source ${DUB_DIRECTORY}/source/${name}/src) +endfunction() diff --git a/cmake/cmake-d/UseDub/DubToCMake.d b/cmake/cmake-d/UseDub/DubToCMake.d new file mode 100644 index 0000000..aafac60 --- /dev/null +++ b/cmake/cmake-d/UseDub/DubToCMake.d @@ -0,0 +1,103 @@ +import std.file; +import std.getopt; +import std.json; +import std.stdio; +import std.string; + +int main(string[] args) +{ + string dubFile = "dub.json"; + string cmakeFile = "CMakeLists.txt"; + + getopt(args, + "package|p", &dubFile, + "output|o", &cmakeFile); + + if (!exists(dubFile)) + { + stderr.writefln("Cannot find file: '%s'", dubFile); + return -1; + } + + string json = readText(dubFile); + JSONValue root = parseJSON(json); + string target = root["targetName"].str; + + string cmake = q"< +cmake_minimum_required(VERSION 2.8) + +project(%1$s D) + +find_file(APP_MAIN_FILE + NAMES app.d main.d %1$s/main.d %1$s/app.d + PATHS source src NO_DEFAULT_PATH) + +file(GLOB_RECURSE SRC_FILES source/*.d src/*.d) +if(APP_MAIN_FILE) + list(REMOVE_ITEM SRC_FILES ${APP_MAIN_FILE}) +endif() + +include_directories(source src) +>".format(root["name"].str); + + switch ("targetType" in root.object ? root["targetType"].str : "autodetect") + { + case "autodetect": + cmake ~= q"< +if(APP_MAIN_FILE) + add_executable(%1$s ${SRC_FILES} ${APP_MAIN_FILE}) +else() + add_library(%1$s ${SRC_FILES}) +endif() +>".format(target); + break; + case "none": + break; + case "executable": + cmake ~= q"< +add_executable(%s ${SRC_FILES} ${APP_MAIN_FILE}) +>".format(target); + break; + case "library": + cmake ~= q"< +add_library(%s ${SRC_FILES}) +>".format(target); + break; + case "sourceLibrary": + break; + case "staticLibrary": + cmake ~= q"< +add_library(%s STATIC ${SRC_FILES}) +>".format(target); + break; + case "dynamicLibrary": + cmake ~= q"< +add_library(%s SHARED ${SRC_FILES}) +>".format(target); + break; + default: + assert(false, "Unknown targetType"); + break; + } + + cmake ~= q"< +install(TARGETS %s + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) +>".format(target); + + if ("dependencies" in root.object) + { + cmake ~= "\ninclude(UseDub)\n"; + foreach (dependency, version_; root["dependencies"].object) + { + cmake ~= "DubProject_Add(%s %s)\n".format(dependency, version_.str); + } + cmake ~= "\nadd_dependencies(%s %-(%s %))\n".format(target, root["dependencies"].object.keys); + } + + std.file.write(cmakeFile, cmake); + + return 0; +} diff --git a/cmake/cmake-d/UseDub/DubUrl.d b/cmake/cmake-d/UseDub/DubUrl.d new file mode 100644 index 0000000..2947894 --- /dev/null +++ b/cmake/cmake-d/UseDub/DubUrl.d @@ -0,0 +1,158 @@ +import std.algorithm; +import std.array; +import std.file; +import std.getopt; +import std.json; +import std.stdio; +import std.string; +import semver; + +/** + * Finds the best match of $(D range) in $(D choices) versions list. + * + * Params: + * range = Match criteria. + * choices = Versions list it is matched against. + * + * Returns: + * Best match in $(D choices) or empty string if no match is found. + * + * See_Also: + * $(WEB https://github.com/npm/npm/blob/master/doc/misc/semver.md#ranges Ranges definition) + */ +string matchVersion(string range, string[] choices) +{ + foreach (ref choice; choices) + { + choice.skipOver('~'); + } + + if (range.skipOver('~')) + { + foreach (choice; choices) + { + if (choice.startsWith(range)) + return choice; + } + return ""; + } + + return ""; +} + +unittest +{ + +} + +int main(string[] args) +{ + string registryFile = ""; + string packageVersion = ""; + bool listVersions; + string outputPath = "."; + + getopt(args, + "package|p", ®istryFile, + "tag|t", &packageVersion, + "list|l", &listVersions, + "output|o", &outputPath); + + if (registryFile.empty) + { + stderr.writeln("Package registry file (.json) need to be specified."); + return -1; + } + + if (!exists(registryFile) && !registryFile.endsWith(".json")) + registryFile ~= ".json"; + + if (!exists(registryFile)) + { + stderr.writefln("Package registry file '%s' not found.", registryFile); + return -1; + } + + string json = readText(registryFile); + JSONValue node; + JSONValue root = parseJSON(json); + + if (packageVersion.empty) + { + packageVersion = "*"; + } + + auto versionRange = SemVerRange(packageVersion); + + if (!versionRange.valid) + { + // try exact string match + auto range = root["versions"].array.find!`a["version"].str == b`(packageVersion); + if (!range.empty) + { + node = range[0]; + } + else + { + stderr.writefln("%s has no version tagged %s.", root["name"].str, packageVersion); + return -1; + } + } + else + { + string nodeVersionString(JSONValue node) + { + auto ver = node["version"].str; + ver.skipOver('~'); + return ver; + } + + auto nodes = root["versions"].array.filter!(a => SemVer(nodeVersionString(a)).valid).array; + auto maxVersion = nodes.map!(a => SemVer(nodeVersionString(a))).array.maxSatisfying(versionRange); + + if (maxVersion.valid) + { + auto range = nodes.find!((a, b) => SemVer(nodeVersionString(a)) == b)(maxVersion); + assert(!range.empty); + node = range[0]; + } + else + { + stderr.writefln("%s has no version %s.", root["name"].str, versionRange); + return -1; + } + } + + if (registryFile.endsWith(".json")) + { + registryFile = registryFile[0..$-5]; + } + + if (listVersions) + { + writefln("Package '%s'", registryFile); + + foreach(n; root["versions"].array) + { + writefln(" %s => %s", n["version"].str, n["downloadUrl"].str); + } + } + + packageVersion = node["version"].str; + auto packageUrl = node["downloadUrl"].str; + auto packageName = root["name"].str; + + if (!outputPath.isDir) + { + stderr.writefln("Output path '%s' need to be a directory.", outputPath); + return -1; + } + + string output = "set(DUB_PACKAGE_NAME, \"%s\")\n".format(packageName) ~ + "set(DUB_PACKAGE_VERSION \"%s\")\n".format(packageVersion) ~ + "set(DUB_PACKAGE_URL \"%s\")\n".format(packageUrl); + + std.file.write(outputPath ~ "/" ~ packageName ~ ".cmake", output); + + return 0; +} diff --git a/cmake/cmake-d/UseDub/semver.d b/cmake/cmake-d/UseDub/semver.d new file mode 100644 index 0000000..36c648f --- /dev/null +++ b/cmake/cmake-d/UseDub/semver.d @@ -0,0 +1,612 @@ +import std.algorithm; +import std.array; +import std.conv; +import std.range; +import std.regex; +import std.stdio; +import std.string; + +enum ReleaseType +{ + MAJOR, + MINOR, + PATCH, + PRERELEASE, +}; + +struct SemVer +{ + uint[3] ids; + string[] prerelease; + string[] build; + + bool isValid; + + @disable this(); + + this(string semVer) + { + isValid = false; + if (semVer.empty) + return; + if (!semVer.skipOver('v')) + semVer.skipOver('='); + + auto re = regex(`^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([a-zA-Z\d-.]+))?(?:\+([a-zA-Z\d-.]+))?$`); + auto m = semVer.matchAll(re); + if (m.empty) + return; + + foreach (i, ref id; ids) + { + if (!m.captures[i+1].empty) + id = m.captures[i+1].to!uint; + } + + if (!m.captures[4].empty) + { + prerelease = m.captures[4].splitter('.').array; + if (prerelease.any!empty) + return; + } + + if (!m.captures[5].empty) + { + build = m.captures[5].splitter('.').array; + if (build.any!empty) + return; + } + + isValid = true; + } + + string toString() const + { + if (!isValid) + return ""; + + string semVer = "%(%s.%)".format(ids); + if (!prerelease.empty) + semVer ~= "-" ~ "%-(%s.%)".format(prerelease); + if (!build.empty) + semVer ~= "+" ~ "%-(%s.%)".format(build); + return semVer; + } + + @property bool valid() const + { + return isValid; + } + + SemVer inc(ReleaseType releaseType) const + in + { + assert(this.valid); + } + out(result) + { + assert(result.valid); + } + body + { + SemVer result = "0"; + foreach (i; 0..releaseType) + result.ids[i] = this.ids[i]; + if (releaseType != ReleaseType.PRERELEASE) + result.ids[releaseType] = this.ids[releaseType]+1; + return result; + } + + SemVer appendPrerelease0() + { + if (prerelease.empty) + prerelease ~= "0"; + return this; + } + + unittest + { + assert(SemVer("1.2.3").inc(ReleaseType.MAJOR) == SemVer("2.0.0")); + assert(SemVer("1.2.3").inc(ReleaseType.MINOR) == SemVer("1.3.0")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.MINOR) == SemVer("1.3.0")); + assert(SemVer("1.2.3").inc(ReleaseType.PATCH) == SemVer("1.2.4")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.PATCH) == SemVer("1.2.4")); + assert(SemVer("1.2.3").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3")); + } + + int opCmp(ref const SemVer v) const + in + { + assert(this.valid); + assert(v.valid); + } + body + { + foreach (i; 0..ids.length) + { + if (ids[i] != v.ids[i]) + return ids[i] < v.ids[i] ? -1 : 1; + } + + if (!prerelease.empty && v.prerelease.empty) + return -1; + if (prerelease.empty && !v.prerelease.empty) + return 1; + + foreach (a, b; lockstep(prerelease, v.prerelease)) + { + if (a.isNumeric && b.isNumeric) + { + if (a.to!uint != b.to!uint) + return a.to!uint < b.to!uint ? -1 : 1; + else + continue; + } + if (a != b) + return a < b ? -1 : 1; + } + if (prerelease.length != v.prerelease.length) + return prerelease.length < v.prerelease.length ? -1 : 1; + + return 0; + } + + int opCmp(const SemVer v) const + { + return this.opCmp(v); + } + + bool opEquals(ref const SemVer v) const + { + return this.opCmp(v) == 0; + } + + bool opEquals(const SemVer v) const + { + return this.opEquals(v); + } +} + +unittest +{ + assert(!SemVer("1.2-.alpha.32").valid); + assert(!SemVer("1.2-alpha+").valid); + assert(!SemVer("1.2-alpha_").valid); + assert(!SemVer("1.2+32.").valid); + assert(!SemVer("1.2.5.6").valid); + assert(!SemVer("").valid); + assert(SemVer("1.0.0-alpha") < SemVer("1.0.0-alpha.1")); + assert(SemVer("1.0.0-alpha.1") < SemVer("1.0.0-alpha.beta")); + assert(SemVer("1.0.0-alpha.beta") < SemVer("1.0.0-beta")); + assert(SemVer("1.0.0-beta") < SemVer("1.0.0-beta.2")); + assert(SemVer("1.0.0-beta.2") < SemVer("1.0.0-beta.11")); + assert(SemVer("1.0.0-beta.11") < SemVer("1.0.0-rc.1")); + assert(SemVer("1.0.0-rc.1") < SemVer("1.0.0")); + assert(SemVer("1.0.0-rc.1") == SemVer("1.0.0-rc.1+build.5")); +} + +struct SemVerRange +{ + struct SimpleRange + { + string op; + SemVer semVer; + + string toString() const + { + return op ~ semVer.toString; + } + } + + SimpleRange[][] ranges; + + invariant() + { + assert(ranges.all!(r => r.all!(r => ["<", "<=", "=", ">=", ">"].canFind(r.op)))); + } + + bool isValid; + + @disable this(); + + this(string semVerRange) + { + isValid = false; + auto re = regex(`(~|~>|\^|<|<=|=|>=|>)?[v]?(\d+|\*|X|x)(?:\.(\d+|\*|X|x))?(?:\.(\d+|\*|X|x))?([\S]*)`); + + ranges = [SimpleRange[].init]; + + while (!semVerRange.stripLeft.empty) + { + auto m = semVerRange.matchFirst(re); + if (m.empty) + return; + + auto operator = m.captures[1]; + auto wildcard = wildcardAt([m.captures[2], m.captures[3], m.captures[4]]); + auto expanded = expand([m.captures[2], m.captures[3], m.captures[4], m.captures[5]]); + if (expanded.empty) + return; + + auto semVer = SemVer(expanded); + if (!semVer.valid) + return; + + switch (m.captures.pre.strip) + { + case "": + break; + case "-": + if (ranges[$-1].empty || ranges[$-1][$-1].op != "=" || + operator != "" || wildcard != ReleaseType.PRERELEASE) + return; + ranges[$-1][$-1].op = ">="; + operator = "<="; + break; + case "||": + ranges ~= SimpleRange[].init; + break; + default: + return; + } + + switch (operator) + { + case "": + case "=": + final switch (wildcard) + { + case ReleaseType.MAJOR: + assert(semVer == SemVer("0.0.0")); + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + break; + case ReleaseType.MINOR: + case ReleaseType.PATCH: + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(--wildcard).appendPrerelease0); + break; + case ReleaseType.PRERELEASE: + ranges[$-1] ~= SimpleRange("=", semVer); + break; + } + break; + case "<": + ranges[$-1] ~= SimpleRange(operator, semVer.appendPrerelease0); + break; + case "<=": + case ">=": + case ">": + if (wildcard < ReleaseType.PRERELEASE) + semVer.appendPrerelease0; + ranges[$-1] ~= SimpleRange(operator, semVer); + break; + case "~": + final switch (wildcard) + { + case ReleaseType.MAJOR: + return; + case ReleaseType.MINOR: + case ReleaseType.PATCH: + --wildcard; + break; + case ReleaseType.PRERELEASE: + --wildcard; + --wildcard; + break; + } + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0); + break; + case "~>": + final switch (wildcard) + { + case ReleaseType.MAJOR: + return; + case ReleaseType.MINOR: + --wildcard; + break; + case ReleaseType.PATCH: + case ReleaseType.PRERELEASE: + --wildcard; + --wildcard; + break; + } + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0); + break; + case "^": + if (wildcard == ReleaseType.MAJOR || !semVer.prerelease.empty) + return; + if (semVer.ids[ReleaseType.MAJOR] != 0) + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MAJOR).appendPrerelease0); + } + else if (semVer.ids[ReleaseType.MINOR] != 0) + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MINOR).appendPrerelease0); + } + else + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.PATCH).appendPrerelease0); + } + break; + default: + assert(0); + break; + } + semVerRange = m.captures.post; + } + isValid = true; + } + + private static ReleaseType wildcardAt(string[3] semVer) + { + foreach (i; ReleaseType.MAJOR..ReleaseType.PRERELEASE) + { + if (["", "*", "X", "x"].canFind(semVer[i])) + return i; + } + return ReleaseType.PRERELEASE; + } + + unittest + { + assert(wildcardAt(["*", "", ""]) == ReleaseType.MAJOR); + assert(wildcardAt(["X", "", ""]) == ReleaseType.MAJOR); + assert(wildcardAt(["1", "", ""]) == ReleaseType.MINOR); + assert(wildcardAt(["1", "x", ""]) == ReleaseType.MINOR); + assert(wildcardAt(["1", "2", ""]) == ReleaseType.PATCH); + assert(wildcardAt(["1", "2", "x"]) == ReleaseType.PATCH); + assert(wildcardAt(["1", "2", "3"]) == ReleaseType.PRERELEASE); + } + + private static string expand(string[4] semVer) + { + ReleaseType wildcard = wildcardAt(semVer[0..3]); + if (wildcard != ReleaseType.PRERELEASE) + { + if (semVer[wildcard+1..$].any!`!["", "*", "X", "x"].canFind(a)`) + return ""; + foreach (j; wildcard..ReleaseType.PRERELEASE) + semVer[j] = "0"; + } + string result = "%-(%s.%)".format(semVer[0..3]); + if (!semVer[3].empty) + result ~= semVer[3]; + return result; + } + + unittest + { + assert(expand(["*", "", "", ""]) == "0.0.0"); + assert(expand(["X", "", "", ""]) == "0.0.0"); + assert(expand(["1", "2", "3", ""]) == "1.2.3"); + assert(expand(["1", "2", "3", "-abc"]) == "1.2.3-abc"); + assert(expand(["1", "2", "", ""]) == "1.2.0"); + assert(expand(["1", "2", "", "-abc"]) == ""); + assert(expand(["1", "2", "x", ""]) == "1.2.0"); + assert(expand(["1", "", "", ""]) == "1.0.0"); + assert(expand(["1", "x", "", ""]) == "1.0.0"); + } + + string toString() const + { + if (!isValid) + return ""; + + return "%(%(%s %) || %)".format(ranges); + } + + @property bool valid() const + { + return isValid; + } + + private static bool simpleRangeSatisfiedBy(SimpleRange simpleRange, SemVer semVer) + in + { + assert(semVer.valid); + assert(["<", "<=", "=", ">=", ">"].canFind(simpleRange.op)); + assert(simpleRange.semVer.valid); + } + body + { + switch (simpleRange.op) + { + case "<": + return semVer < simpleRange.semVer; + case "<=": + return semVer <= simpleRange.semVer; + case "=": + return semVer == simpleRange.semVer; + case ">=": + return semVer >= simpleRange.semVer; + case ">": + return semVer > simpleRange.semVer; + default: + return false; + } + } + + bool satisfiedBy(SemVer semVer) + in + { + assert(semVer.valid); + assert(valid); + } + body + { + return ranges.any!(r => r.all!(s => simpleRangeSatisfiedBy(s, semVer))); + } + +} + +bool satisfies(SemVer semVer, SemVerRange semVerRange) +{ + return semVerRange.satisfiedBy(semVer); +} + +SemVer maxSatisfying(SemVer[] semVers, SemVerRange semVerRange) +in +{ + assert(semVers.all!"a.valid"); + assert(semVerRange.valid); +} +body +{ + auto found = semVers.sort!"a > b".find!(a => satisfies(a, semVerRange)); + return found.empty ? SemVer("invalid") : found[0]; +} + +unittest +{ + assert(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3").valid); + assert(!SemVerRange("blerg").valid); + assert(!SemVerRange("git+https://user:password0123@github.com/foo").valid); + + assert(SemVer("1.2.3").satisfies(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3"))); + + assert(SemVer("1.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0"))); + assert(SemVer("1.0.0").satisfies(SemVerRange("1.0.0"))); + assert(SemVer("0.2.4").satisfies(SemVerRange(">=*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("*"))); + assert(SemVer("v1.2.3-foo").satisfies(SemVerRange("*"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("v0.1.97").satisfies(SemVerRange(">=0.1.97"))); + assert(SemVer("0.1.97").satisfies(SemVerRange(">=0.1.97"))); + assert(SemVer("1.2.4").satisfies(SemVerRange("0.1.20 || 1.2.4"))); + assert(SemVer("0.0.0").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("0.2.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("0.2.4").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("2.x.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("x"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("2.*.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.*"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("*"))); + assert(SemVer("2.1.2").satisfies(SemVerRange("2"))); + assert(SemVer("2.3.1").satisfies(SemVerRange("2.3"))); + assert(SemVer("2.4.0").satisfies(SemVerRange("~2.4"))); + assert(SemVer("2.4.5").satisfies(SemVerRange("~2.4"))); + assert(SemVer("3.2.2").satisfies(SemVerRange("~>3.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~>1"))); + assert(SemVer("1.0.2").satisfies(SemVerRange("~1.0"))); + assert(SemVer("1.0.12").satisfies(SemVerRange("~1.0.3"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1"))); + assert(SemVer("1.1.1").satisfies(SemVerRange("<1.2"))); + assert(SemVer("1.1.9").satisfies(SemVerRange("<=1.2"))); + assert(SemVer("1.0.0-bet").satisfies(SemVerRange("1"))); + assert(SemVer("0.5.5").satisfies(SemVerRange("~v0.5.4-pre"))); + assert(SemVer("0.5.4").satisfies(SemVerRange("~v0.5.4-pre"))); + assert(SemVer("0.7.2").satisfies(SemVerRange("=0.7.x"))); + assert(SemVer("0.7.2").satisfies(SemVerRange(">=0.7.x"))); + assert(SemVer("0.7.0-asdf").satisfies(SemVerRange("=0.7.x"))); + assert(SemVer("0.7.0-asdf").satisfies(SemVerRange(">=0.7.x"))); + assert(SemVer("0.6.2").satisfies(SemVerRange("<=0.7.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 =1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3 >=1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.3 >=1.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.3 >=1.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 >=1.2.3"))); + assert(SemVer("1.2.3-beta").satisfies(SemVerRange("<=1.2.3"))); + assert(SemVer("1.3.0-beta").satisfies(SemVerRange(">1.2"))); + assert(SemVer("1.2.8").satisfies(SemVerRange(">=1.2"))); + assert(SemVer("1.8.1").satisfies(SemVerRange("^1.2.3"))); + assert(SemVer("1.2.3-beta").satisfies(SemVerRange("^1.2.3"))); + assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1.2"))); + assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1"))); + assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2"))); + assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2 ^1"))); + assert(SemVer("1.2.0-pre").satisfies(SemVerRange("^1.2"))); + assert(SemVer("1.2.3-pre").satisfies(SemVerRange("^1.2.3"))); + + assert(!SemVer("2.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0"))); + assert(!SemVer("1.0.1").satisfies(SemVerRange("1.0.0"))); + assert(!SemVer("0.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(!SemVer("0.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(!SemVer("3.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(!SemVer("2.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(!SemVer("v0.1.93").satisfies(SemVerRange(">=0.1.97"))); + assert(!SemVer("0.1.93").satisfies(SemVerRange(">=0.1.97"))); + assert(!SemVer("1.2.3").satisfies(SemVerRange("0.1.20 || 1.2.4"))); + assert(!SemVer("0.0.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(!SemVer("0.2.2").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("2.x.x"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("2.x.x"))); + assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.x"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("2.*.*"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("2.*.*"))); + assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.*"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(!SemVer("1.1.2").satisfies(SemVerRange("2"))); + assert(!SemVer("2.4.1").satisfies(SemVerRange("2.3"))); + assert(!SemVer("2.5.0").satisfies(SemVerRange("~2.4"))); + assert(!SemVer("2.3.9").satisfies(SemVerRange("~2.4"))); + assert(!SemVer("3.3.2").satisfies(SemVerRange("~>3.2.1"))); + assert(!SemVer("3.2.0").satisfies(SemVerRange("~>3.2.1"))); + assert(!SemVer("0.2.3").satisfies(SemVerRange("~1"))); + assert(!SemVer("2.2.3").satisfies(SemVerRange("~>1"))); + assert(!SemVer("1.1.0").satisfies(SemVerRange("~1.0"))); + assert(!SemVer("1.0.0").satisfies(SemVerRange("<1"))); + assert(!SemVer("1.1.1").satisfies(SemVerRange(">=1.2"))); + assert(!SemVer("1.3.0").satisfies(SemVerRange("<=1.2"))); + assert(!SemVer("2.0.0-beta").satisfies(SemVerRange("1"))); + assert(!SemVer("0.5.4-alpha").satisfies(SemVerRange("~v0.5.4-beta"))); + assert(!SemVer("1.0.0-beta").satisfies(SemVerRange("<1"))); + assert(!SemVer("0.8.2").satisfies(SemVerRange("=0.7.x"))); + assert(!SemVer("0.6.2").satisfies(SemVerRange(">=0.7.x"))); + assert(!SemVer("0.7.2").satisfies(SemVerRange("<=0.7.x"))); + assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("<1.2.3"))); + assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("=1.2.3"))); + assert(!SemVer("1.2.8").satisfies(SemVerRange(">1.3"))); + assert(!SemVer("2.0.0-alpha").satisfies(SemVerRange("^1.2.3"))); + assert(!SemVer("1.2.2").satisfies(SemVerRange("^1.2.3"))); + assert(!SemVer("1.1.9").satisfies(SemVerRange("^1.2"))); + assert(!SemVer("2.0.0-pre").satisfies(SemVerRange("^1.2.3"))); + + auto semVers = [SemVer("0.8.0"), SemVer("1.0.0"), SemVer("1.1.0")]; + assert(semVers.maxSatisfying(SemVerRange("<=1.0.0")) == SemVer("1.0.0")); + assert(semVers.maxSatisfying(SemVerRange(">=1.0")) == SemVer("1.1.0")); +} diff --git a/cmake/cmake-d/dependencies.cmake b/cmake/cmake-d/dependencies.cmake new file mode 100644 index 0000000..307aec9 --- /dev/null +++ b/cmake/cmake-d/dependencies.cmake @@ -0,0 +1,52 @@ +#message("Adding dependencies") + +#message("CMAKE_D_FLAGS: ${CMAKE_D_FLAGS} ") +#message("CMAKE_D_COMPILER: ${CMAKE_D_COMPILER} ") +#message("include_directories: ${include_directories} ") +#message("source file ${source_file}") +#message("dependency file ${dependency_file}") + +separate_arguments(CMAKE_D_FLAGS) + +# TODO +# need to pass all arguments that are used for building +# can't I use the build rule somehow +execute_process(COMMAND ${CMAKE_D_COMPILER} ${CMAKE_D_FLAGS} ${include_directories} -deps=${dependency_file}.tmp -o- ${source_file}) +#message("executing: ${CMAKE_D_COMPILER} ${CMAKE_D_FLAGS} ${include_directories} -deps=${dependency_file}.tmp -o- ${source_file}") + +if(NOT EXISTS ${dependency_file}) + file(WRITE ${dependency_file} "# Generated by: ${CMAKE_CURRENT_LIST_FILE}\nSET(D_DMD_DEPEND\n)\n\n") +endif() + +file(READ ${dependency_file}.tmp depend_text) +#message("DEPENDENCIES: ${depend_text}") + +# extract dependencies +string(REGEX MATCHALL "\\([^)]*\\)" out ${depend_text}) +string(REGEX MATCHALL "[^()]+" out ${out}) +list(REMOVE_DUPLICATES out) +list(SORT out) + +foreach(file ${out}) + set(dependencies "${dependencies} \"${file}\"\n") +endforeach() + +# write new dependencies to temporary file +file(WRITE ${dependency_file}.tmp "# Generated by: ${CMAKE_CURRENT_LIST_FILE}\nSET(D_DMD_DEPEND\n ${dependencies})\n\n") + +# get old dependencies +include(${dependency_file}) +set(old_dependencies ${D_DMD_DEPEND}) +# and the new dependencies from temporary file +include(${dependency_file}.tmp) + +# did the dependencies change? +if(NOT "${D_DMD_DEPEND}" STREQUAL "${old_dependencies}") + message("Dependencies changed. Need to build.") + execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${source_file}) +endif() + +execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${dependency_file}.tmp ${dependency_file}) +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${dependency_file}.tmp) + +#message("Finished dependencies") diff --git a/lib/dusbextreme.d b/lib/dusbextreme.d new file mode 100644 index 0000000..c7b552f --- /dev/null +++ b/lib/dusbextreme.d @@ -0,0 +1,29 @@ +module dusbextreme; +import std.stdint; + +enum USBEXTREME_NAME_LENGTH = 32; +enum USBEXTREME_ID_LENGTH = 15; +enum USBEXTREME_NAME_EXT_LENGTH = 10; +enum USBEXTREME_MAGIC = 0x08; +enum USBEXTREME_HEADER_SIZE = usb_extreme_base.sizeof; + +struct usb_extreme_base { + uint8_t[6 + USBEXTREME_ID_LENGTH + USBEXTREME_NAME_LENGTH] empty; + uint8_t magic; + uint8_t[10] empty2; +} + +extern(C) int is_oue(immutable(void)* headers, immutable(size_t) headerslen) { + immutable headers_oeu = cast(immutable usb_extreme_base*) headers; + immutable headers_nlen = headerslen / USBEXTREME_HEADER_SIZE; + + for (auto i = 0; i < headers_nlen; i++) { + immutable header = headers_oeu[i]; + + if (header.magic != USBEXTREME_MAGIC) { + return 0; + } + } + + return 1; +} diff --git a/lib/usbextreme.c b/lib/usbextreme.c index 90e68fe..ad43ef5 100644 --- a/lib/usbextreme.c +++ b/lib/usbextreme.c @@ -1,22 +1,6 @@ #include #include -int is_oue(const void *headers, const size_t headerslen) { - const usb_extreme_base *headers_oeu = headers; - int headers_nlen = (int) (headerslen / USBEXTREME_HEADER_SIZE); - int i; - - for(i = 0; i < headers_nlen; i++) { - const usb_extreme_base header = headers_oeu[i]; - - if (header.magic != USBEXTREME_MAGIC) { - return 0; - } - } - - return 1; -} - usb_extreme_versions get_version(u8 version) { switch (version) { case 0: {