diff --git a/cmaked/CMakeLists.txt b/cmaked/CMakeLists.txt index 80b77d6..2244609 100644 --- a/cmaked/CMakeLists.txt +++ b/cmaked/CMakeLists.txt @@ -20,6 +20,8 @@ SET (MOD_SRCS CMakeDetermineDCompiler.cmake FindGDCPath.cmake UseDDoc.cmake + UseDDeps.cmake + dependencies.cmake ) SET (PLAT_SRCS diff --git a/cmaked/UseDDeps.cmake b/cmaked/UseDDeps.cmake new file mode 100644 index 0000000..eee84b1 --- /dev/null +++ b/cmaked/UseDDeps.cmake @@ -0,0 +1,66 @@ +# Dependency tracking for D +# +# Copyright (c) 2010 Jens Mueller +# +# All rights reserved. +# +# See Copyright.txt 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}") + get_directory_property(include_dirs INCLUDE_DIRECTORIES) + foreach(include_dir IN LISTS include_dirs) + #message("Adding include directory ${include_dir}") + set(include_directories "-I${include_dir} ${include_directories}") + endforeach() + + # TODO + # somehow I have to pass each argument on its own + # this fails e.g. if using ${CMAKE_D_FLAGS} in dependencies.cmake + # or if there is more than one include dir + 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=${include_directories}" + -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=${include_directories}" + -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(add_executable_with_dependencies) diff --git a/cmaked/dependencies.cmake b/cmaked/dependencies.cmake new file mode 100644 index 0000000..e6ea20e --- /dev/null +++ b/cmaked/dependencies.cmake @@ -0,0 +1,47 @@ +#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}") + +execute_process(COMMAND ${CMAKE_D_COMPILER} ${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/tests/CMakeLists.txt b/tests/CMakeLists.txt index 269e790..dc49046 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,3 +29,4 @@ ADD_SUBDIRECTORY (app_5) ADD_SUBDIRECTORY (app_4) ADD_SUBDIRECTORY (app_6) ADD_SUBDIRECTORY (app_7) +ADD_SUBDIRECTORY (app_8) diff --git a/tests/app_8/CMakeLists.txt b/tests/app_8/CMakeLists.txt new file mode 100644 index 0000000..7f2527a --- /dev/null +++ b/tests/app_8/CMakeLists.txt @@ -0,0 +1,4 @@ +include(UseDDeps) + +include_directories(.) +add_executable_with_dependencies(app_8 app_8.d) diff --git a/tests/app_8/a.d b/tests/app_8/a.d new file mode 100644 index 0000000..e69de29 diff --git a/tests/app_8/app_8.d b/tests/app_8/app_8.d new file mode 100644 index 0000000..f768ac0 --- /dev/null +++ b/tests/app_8/app_8.d @@ -0,0 +1,9 @@ +// barebones app, depends on the standard library +import std.stdio; +import a; + +int main() +{ + writeln( "Hello World!" ); + return 0; +}