diff --git a/cmake/dotnet.cmake b/cmake/dotnet.cmake index 1049716bcf..7aabeb10a7 100644 --- a/cmake/dotnet.cmake +++ b/cmake/dotnet.cmake @@ -8,7 +8,7 @@ endif() # Will need swig set(CMAKE_SWIG_FLAGS) -find_package(SWIG) +find_package(SWIG REQUIRED) include(UseSWIG) #if(${SWIG_VERSION} VERSION_GREATER_EQUAL 4) @@ -19,7 +19,7 @@ if(UNIX AND NOT APPLE) list(APPEND CMAKE_SWIG_FLAGS "-DSWIGWORDSIZE64") endif() -# Setup Dotnet +# Find dotnet cli find_program(DOTNET_EXECUTABLE NAMES dotnet) if(NOT DOTNET_EXECUTABLE) message(FATAL_ERROR "Check for dotnet Program: not found") @@ -67,6 +67,13 @@ set_target_properties(google-ortools-native PROPERTIES # note: macOS is APPLE and also UNIX ! if(APPLE) set_target_properties(google-ortools-native PROPERTIES INSTALL_RPATH "@loader_path") + # Xcode fails to build if library doesn't contains at least one source file. + if(XCODE) + file(GENERATE + OUTPUT ${PROJECT_BINARY_DIR}/google-ortools-native/version.cpp + CONTENT "namespace {char* version = \"${PROJECT_VERSION}\";}") + target_sources(google-ortools-native PRIVATE ${PROJECT_BINARY_DIR}/google-ortools-native/version.cpp) + endif() elseif(UNIX) set_target_properties(google-ortools-native PROPERTIES INSTALL_RPATH "$ORIGIN") endif() @@ -82,8 +89,9 @@ if(USE_COINOR) endif() list(APPEND CMAKE_SWIG_FLAGS ${FLAGS} "-I${PROJECT_SOURCE_DIR}") -# Swig wrap all libraries -set(DOTNET_PROJECT Google.OrTools) +# Needed by dotnet/CMakeLists.txt +set(DOTNET_PACKAGE Google.OrTools) +set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") if(APPLE) set(RUNTIME_IDENTIFIER osx-x64) elseif(UNIX) @@ -93,21 +101,22 @@ elseif(WIN32) else() message(FATAL_ERROR "Unsupported system !") endif() -set(DOTNET_NATIVE_PROJECT ${DOTNET_PROJECT}.runtime.${RUNTIME_IDENTIFIER}) +set(DOTNET_NATIVE_PROJECT ${DOTNET_PACKAGE}.runtime.${RUNTIME_IDENTIFIER}) +set(DOTNET_PROJECT ${DOTNET_PACKAGE}) +# Swig wrap all libraries foreach(SUBPROJECT IN ITEMS algorithms graph init linear_solver constraint_solver sat util) add_subdirectory(ortools/${SUBPROJECT}/csharp) target_link_libraries(google-ortools-native PRIVATE dotnet_${SUBPROJECT}) endforeach() -############################ -## .Net Runtime Package ## -############################ file(COPY tools/doc/orLogo.png DESTINATION dotnet) -set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") set(DOTNET_LOGO_DIR "${PROJECT_BINARY_DIR}/dotnet") configure_file(ortools/dotnet/Directory.Build.props.in dotnet/Directory.Build.props) +############################ +## .Net SNK file ## +############################ # Build or retrieve .snk file if(DEFINED ENV{DOTNET_SNK}) add_custom_command(OUTPUT dotnet/or-tools.snk @@ -132,40 +141,48 @@ else() ) endif() -file(GENERATE OUTPUT dotnet/$/replace_runtime.cmake - CONTENT - "FILE(READ ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj.in input) -STRING(REPLACE \"@PROJECT_VERSION@\" \"${PROJECT_VERSION}\" input \"\${input}\") -STRING(REPLACE \"@ortools@\" \"$<$>:$>\" input \"\${input}\") -STRING(REPLACE \"@native@\" \"$\" input \"\${input}\") -FILE(WRITE ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj \"\${input}\")" +############################ +## .Net Runtime Package ## +############################ +message(STATUS ".Net runtime project: ${DOTNET_NATIVE_PROJECT}") +set(DOTNET_NATIVE_PATH ${PROJECT_BINARY_DIR}/dotnet/${DOTNET_NATIVE_PROJECT}) +message(STATUS ".Net runtime project build path: ${DOTNET_NATIVE_PATH}") + +# *.csproj.in contains: +# CMake variable(s) (@PROJECT_NAME@) that configure_file() can manage and +# generator expression ($) that file(GENERATE) can manage. +configure_file( + ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_PACKAGE}.runtime.csproj.in + ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj.in + @ONLY) +file(GENERATE + OUTPUT ${DOTNET_NATIVE_PATH}/$/${DOTNET_NATIVE_PROJECT}.csproj.in + INPUT ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj.in) + +add_custom_command( + OUTPUT ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj + DEPENDS ${DOTNET_NATIVE_PATH}/$/${DOTNET_NATIVE_PROJECT}.csproj.in + COMMAND ${CMAKE_COMMAND} -E copy ./$/${DOTNET_NATIVE_PROJECT}.csproj.in ${DOTNET_NATIVE_PROJECT}.csproj + WORKING_DIRECTORY ${DOTNET_NATIVE_PATH} ) -add_custom_command( - OUTPUT dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj - COMMAND ${CMAKE_COMMAND} -E make_directory ${DOTNET_NATIVE_PROJECT} - COMMAND ${CMAKE_COMMAND} -P ./$/replace_runtime.cmake - WORKING_DIRECTORY dotnet - ) +#if(WIN32) +#add_custom_command( +# OUTPUT dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets +# COMMAND ${CMAKE_COMMAND} -E make_directory ${DOTNET_NATIVE_PROJECT} +# COMMAND ${CMAKE_COMMAND} -E copy +# ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets +# ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets +# WORKING_DIRECTORY dotnet +# ) +# set(DOTNET_TARGETS dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets) +#endif() -if(WIN32) -add_custom_command( - OUTPUT dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets - COMMAND ${CMAKE_COMMAND} -E make_directory ${DOTNET_NATIVE_PROJECT} - COMMAND ${CMAKE_COMMAND} -E copy - ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets - ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets - WORKING_DIRECTORY dotnet - ) - set(DOTNET_TARGETS dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.targets) -endif() - -add_custom_target(dotnet_native ALL +add_custom_target(dotnet_native_package DEPENDS dotnet/or-tools.snk Dotnet${PROJECT_NAME}_proto - google-ortools-native - dotnet/${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj + ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj ${DOTNET_TARGETS} COMMAND ${CMAKE_COMMAND} -E make_directory packages COMMAND ${DOTNET_EXECUTABLE} build -c Release /p:Platform=x64 ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj @@ -174,33 +191,34 @@ add_custom_target(dotnet_native ALL dotnet/${DOTNET_NATIVE_PROJECT}/bin dotnet/${DOTNET_NATIVE_PROJECT}/obj WORKING_DIRECTORY dotnet - ) +) +add_dependencies(dotnet_native_package google-ortools-native) #################### ## .Net Package ## #################### -file(GENERATE OUTPUT dotnet/$/replace.cmake - CONTENT - "FILE(READ ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj.in input) -STRING(REPLACE \"@PROJECT_VERSION@\" \"${PROJECT_VERSION}\" input \"\${input}\") -STRING(REPLACE \"@PROJECT_SOURCE_DIR@\" \"${PROJECT_SOURCE_DIR}\" input \"\${input}\") -STRING(REPLACE \"@PROJECT_DOTNET_DIR@\" \"${PROJECT_BINARY_DIR}/dotnet\" input \"\${input}\") -STRING(REPLACE \"@DOTNET_PACKAGES_DIR@\" \"${PROJECT_BINARY_DIR}/dotnet/packages\" input \"\${input}\") -FILE(WRITE ${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj \"\${input}\")" -) +message(STATUS ".Net project: ${DOTNET_PROJECT}") +set(DOTNET_PATH ${PROJECT_BINARY_DIR}/dotnet/${DOTNET_PROJECT}) +message(STATUS ".Net project build path: ${DOTNET_PATH}") + +set(PROJECT_DOTNET_DIR ${PROJECT_BINARY_DIR}/dotnet) + +configure_file( + ${PROJECT_SOURCE_DIR}/ortools/dotnet/${DOTNET_PROJECT}.csproj.in + ${DOTNET_PATH}/${DOTNET_PROJECT}.csproj.in + @ONLY) add_custom_command( - OUTPUT dotnet/${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj - COMMAND ${CMAKE_COMMAND} -E make_directory ${DOTNET_PROJECT} - COMMAND ${CMAKE_COMMAND} -P ./$/replace.cmake - WORKING_DIRECTORY dotnet - ) + OUTPUT ${DOTNET_PATH}/${DOTNET_PROJECT}.csproj + DEPENDS ${DOTNET_PATH}/${DOTNET_PROJECT}.csproj.in + COMMAND ${CMAKE_COMMAND} -E copy ${DOTNET_PROJECT}.csproj.in ${DOTNET_PROJECT}.csproj + WORKING_DIRECTORY ${DOTNET_PATH} +) add_custom_target(dotnet_package ALL DEPENDS dotnet/or-tools.snk - dotnet_native - dotnet/${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj + ${DOTNET_PATH}/${DOTNET_PROJECT}.csproj COMMAND ${DOTNET_EXECUTABLE} build -c Release /p:Platform=x64 ${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj COMMAND ${DOTNET_EXECUTABLE} pack -c Release ${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj BYPRODUCTS @@ -208,52 +226,106 @@ add_custom_target(dotnet_package ALL dotnet/${DOTNET_PROJECT}/obj dotnet/packages WORKING_DIRECTORY dotnet - ) +) +add_dependencies(dotnet_package dotnet_native_package) +################# +## .Net Test ## +################# +# add_dotnet_test() +# CMake function to generate and build dotnet test. +# Parameters: +# the dotnet filename +# e.g.: +# add_dotnet_test(FooTests.cs) +function(add_dotnet_test FILE_NAME) + message(STATUS "Configuring test ${FILE_NAME} ...") + get_filename_component(TEST_NAME ${FILE_NAME} NAME_WE) + get_filename_component(COMPONENT_DIR ${FILE_NAME} DIRECTORY) + get_filename_component(COMPONENT_NAME ${COMPONENT_DIR} NAME) + + set(DOTNET_TEST_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${TEST_NAME}) + message(STATUS "build path: ${DOTNET_TEST_PATH}") + file(MAKE_DIRECTORY ${DOTNET_TEST_PATH}) + + file(COPY ${FILE_NAME} DESTINATION ${DOTNET_TEST_PATH}) + + set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") + configure_file( + ${PROJECT_SOURCE_DIR}/ortools/dotnet/Test.csproj.in + ${DOTNET_TEST_PATH}/${TEST_NAME}.csproj + @ONLY) + + add_custom_target(dotnet_test_${TEST_NAME} ALL + DEPENDS ${DOTNET_TEST_PATH}/${TEST_NAME}.csproj + COMMAND ${DOTNET_EXECUTABLE} build -c Release + BYPRODUCTS + ${DOTNET_TEST_PATH}/bin + ${DOTNET_TEST_PATH}/obj + WORKING_DIRECTORY ${DOTNET_TEST_PATH}) + add_dependencies(dotnet_test_${TEST_NAME} dotnet_package) + + if(BUILD_TESTING) + add_test( + NAME dotnet_${COMPONENT_NAME}_${TEST_NAME} + COMMAND ${DOTNET_EXECUTABLE} test --no-build -c Release + WORKING_DIRECTORY ${DOTNET_TEST_PATH}) + endif() + + message(STATUS "Configuring test ${FILE_NAME} done") +endfunction() + +################### +## .Net Sample ## +################### # add_dotnet_sample() # CMake function to generate and build dotnet sample. # Parameters: # the dotnet filename # e.g.: -# add_dotnet_sample(Foo.cs) +# add_dotnet_sample(FooApp.cs) function(add_dotnet_sample FILE_NAME) - message(STATUS "Building ${FILE_NAME}: ...") + message(STATUS "Configuring sample ${FILE_NAME} ...") get_filename_component(SAMPLE_NAME ${FILE_NAME} NAME_WE) get_filename_component(SAMPLE_DIR ${FILE_NAME} DIRECTORY) get_filename_component(COMPONENT_DIR ${SAMPLE_DIR} DIRECTORY) get_filename_component(COMPONENT_NAME ${COMPONENT_DIR} NAME) - set(SAMPLE_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${SAMPLE_NAME}) - file(MAKE_DIRECTORY ${SAMPLE_PATH}) + set(DOTNET_SAMPLE_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${SAMPLE_NAME}) + message(STATUS "build path: ${DOTNET_SAMPLE_PATH}") + file(MAKE_DIRECTORY ${DOTNET_SAMPLE_PATH}) - file(COPY ${FILE_NAME} DESTINATION ${SAMPLE_PATH}) + file(COPY ${FILE_NAME} DESTINATION ${DOTNET_SAMPLE_PATH}) set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") configure_file( ${PROJECT_SOURCE_DIR}/ortools/dotnet/Sample.csproj.in - ${SAMPLE_PATH}/${SAMPLE_NAME}.csproj + ${DOTNET_SAMPLE_PATH}/${SAMPLE_NAME}.csproj @ONLY) add_custom_target(dotnet_sample_${SAMPLE_NAME} ALL - DEPENDS ${SAMPLE_PATH}/${SAMPLE_NAME}.csproj + DEPENDS ${DOTNET_SAMPLE_PATH}/${SAMPLE_NAME}.csproj COMMAND ${DOTNET_EXECUTABLE} build -c Release COMMAND ${DOTNET_EXECUTABLE} pack -c Release BYPRODUCTS - ${SAMPLE_PATH}/bin - ${SAMPLE_PATH}/obj - WORKING_DIRECTORY ${SAMPLE_PATH}) + ${DOTNET_SAMPLE_PATH}/bin + ${DOTNET_SAMPLE_PATH}/obj + WORKING_DIRECTORY ${DOTNET_SAMPLE_PATH}) add_dependencies(dotnet_sample_${SAMPLE_NAME} dotnet_package) if(BUILD_TESTING) add_test( NAME dotnet_${COMPONENT_NAME}_${SAMPLE_NAME} COMMAND ${DOTNET_EXECUTABLE} run --no-build -c Release - WORKING_DIRECTORY ${SAMPLE_PATH}) + WORKING_DIRECTORY ${DOTNET_SAMPLE_PATH}) endif() - message(STATUS "Building ${FILE_NAME}: ...DONE") + message(STATUS "Configuring sample ${FILE_NAME} done") endfunction() +#################### +## .Net Example ## +#################### # add_dotnet_example() # CMake function to generate and build dotnet example. # Parameters: @@ -261,81 +333,41 @@ endfunction() # e.g.: # add_dotnet_example(Foo.cs) function(add_dotnet_example FILE_NAME) - message(STATUS "Building ${FILE_NAME}: ...") + message(STATUS "Configuring sample ${FILE_NAME} ...") get_filename_component(EXAMPLE_NAME ${FILE_NAME} NAME_WE) get_filename_component(COMPONENT_DIR ${FILE_NAME} DIRECTORY) get_filename_component(COMPONENT_NAME ${COMPONENT_DIR} NAME) - set(EXAMPLE_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${EXAMPLE_NAME}) - file(MAKE_DIRECTORY ${EXAMPLE_PATH}) + set(DOTNET_EXAMPLE_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${EXAMPLE_NAME}) + message(STATUS "build path: ${DOTNET_EXAMPLE_PATH}") + file(MAKE_DIRECTORY ${DOTNET_EXAMPLE_PATH}) - file(COPY ${FILE_NAME} DESTINATION ${EXAMPLE_PATH}) + file(COPY ${FILE_NAME} DESTINATION ${DOTNET_EXAMPLE_PATH}) set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") set(SAMPLE_NAME ${EXAMPLE_NAME}) configure_file( ${PROJECT_SOURCE_DIR}/ortools/dotnet/Sample.csproj.in - ${EXAMPLE_PATH}/${EXAMPLE_NAME}.csproj + ${DOTNET_EXAMPLE_PATH}/${EXAMPLE_NAME}.csproj @ONLY) add_custom_target(dotnet_example_${EXAMPLE_NAME} ALL - DEPENDS ${EXAMPLE_PATH}/${EXAMPLE_NAME}.csproj + DEPENDS ${DOTNET_EXAMPLE_PATH}/${EXAMPLE_NAME}.csproj COMMAND ${DOTNET_EXECUTABLE} build -c Release COMMAND ${DOTNET_EXECUTABLE} pack -c Release BYPRODUCTS - ${EXAMPLE_PATH}/bin - ${EXAMPLE_PATH}/obj - WORKING_DIRECTORY ${EXAMPLE_PATH}) + ${DOTNET_EXAMPLE_PATH}/bin + ${DOTNET_EXAMPLE_PATH}/obj + WORKING_DIRECTORY ${DOTNET_EXAMPLE_PATH}) add_dependencies(dotnet_example_${EXAMPLE_NAME} dotnet_package) if(BUILD_TESTING) add_test( NAME dotnet_${COMPONENT_NAME}_${EXAMPLE_NAME} COMMAND ${DOTNET_EXECUTABLE} run --no-build -c Release - WORKING_DIRECTORY ${EXAMPLE_PATH}) + WORKING_DIRECTORY ${DOTNET_EXAMPLE_PATH}) endif() - message(STATUS "Building ${FILE_NAME}: ...DONE") + message(STATUS "Configuring sample ${FILE_NAME} done") endfunction() -# add_dotnet_test() -# CMake function to generate and build dotnet test. -# Parameters: -# the dotnet filename -# e.g.: -# add_dotnet_test(Foo.cs) -function(add_dotnet_test FILE_NAME) - message(STATUS "Building ${FILE_NAME}: ...") - get_filename_component(TEST_NAME ${FILE_NAME} NAME_WE) - get_filename_component(COMPONENT_DIR ${FILE_NAME} DIRECTORY) - get_filename_component(COMPONENT_NAME ${COMPONENT_DIR} NAME) - - set(TEST_PATH ${PROJECT_BINARY_DIR}/dotnet/${COMPONENT_NAME}/${TEST_NAME}) - file(MAKE_DIRECTORY ${TEST_PATH}) - - file(COPY ${FILE_NAME} DESTINATION ${TEST_PATH}) - - set(DOTNET_PACKAGES_DIR "${PROJECT_BINARY_DIR}/dotnet/packages") - configure_file( - ${PROJECT_SOURCE_DIR}/ortools/dotnet/Test.csproj.in - ${TEST_PATH}/${TEST_NAME}.csproj - @ONLY) - - add_custom_target(dotnet_sample_${TEST_NAME} ALL - DEPENDS ${TEST_PATH}/${TEST_NAME}.csproj - COMMAND ${DOTNET_EXECUTABLE} build -c Release - BYPRODUCTS - ${TEST_PATH}/bin - ${TEST_PATH}/obj - WORKING_DIRECTORY ${TEST_PATH}) - add_dependencies(dotnet_sample_${TEST_NAME} dotnet_package) - - if(BUILD_TESTING) - add_test( - NAME dotnet_${COMPONENT_NAME}_${TEST_NAME} - COMMAND ${DOTNET_EXECUTABLE} test --no-build -c Release - WORKING_DIRECTORY ${TEST_PATH}) - endif() - - message(STATUS "Building ${FILE_NAME}: ...DONE") -endfunction()