diff --git a/benchmarks/linear_programming/cuopt/run_mip.cpp b/benchmarks/linear_programming/cuopt/run_mip.cpp index 713d55f16..e3e8641b4 100644 --- a/benchmarks/linear_programming/cuopt/run_mip.cpp +++ b/benchmarks/linear_programming/cuopt/run_mip.cpp @@ -292,7 +292,7 @@ void return_gpu_to_the_queue(std::unordered_map& pid_gpu_map, int main(int argc, char* argv[]) { - argparse::ArgumentParser program("solve_mps_file"); + argparse::ArgumentParser program("solve_MIP"); // Define all arguments with appropriate defaults and help messages program.add_argument("--path").help("input path").required(); diff --git a/benchmarks/linear_programming/cuopt/run_pdlp.cu b/benchmarks/linear_programming/cuopt/run_pdlp.cu index e4fad3c26..396ff6fbd 100644 --- a/benchmarks/linear_programming/cuopt/run_pdlp.cu +++ b/benchmarks/linear_programming/cuopt/run_pdlp.cu @@ -113,7 +113,7 @@ static cuopt::linear_programming::pdlp_solver_settings_t create_sol int main(int argc, char* argv[]) { // Parse binary arguments - argparse::ArgumentParser program("solve_mps_file"); + argparse::ArgumentParser program("solve_LP"); parse_arguments(program); try { diff --git a/benchmarks/linear_programming/utils/benchmark_lp_mittelmann.sh b/benchmarks/linear_programming/utils/benchmark_lp_mittelmann.sh index bf561fceb..0f2b475cc 100755 --- a/benchmarks/linear_programming/utils/benchmark_lp_mittelmann.sh +++ b/benchmarks/linear_programming/utils/benchmark_lp_mittelmann.sh @@ -30,12 +30,12 @@ echo "Download done" # EAGER module loading to simulate real-life condition export CUDA_MODULE_LOADING=EAGER -# Benchmark all instances (cuOpt needs to be compiled first) +# Benchmark all instances (cuOpt needs to be compiled first, you can compile in LP only mode and you should turn on BUILD_LP_BENCHMARKS) for instance in ${CUOPT_HOME}/benchmarks/linear_programming/datasets/*/ ; do # Will generate the solver log for each instance. Could addtionally generate the solution file by uncommenting the --solution-path instance_name=$(basename $instance) echo "Parsing ${instance_name}.mps then solving" - ${CUOPT_HOME}/cpp/build/solve_MPS_file --path ${CUOPT_HOME}/benchmarks/linear_programming/datasets/${instance_name}/${instance_name}.mps --time-limit 3600 # --solution-path $CUOPT_HOME/benchmarks/linear_programming/datasets/$instance.sol + ${CUOPT_HOME}/cpp/build/solve_LP --path ${CUOPT_HOME}/benchmarks/linear_programming/datasets/${instance_name}/${instance_name}.mps --time-limit 3600 # --solution-path $CUOPT_HOME/benchmarks/linear_programming/datasets/$instance.sol done echo "Benchmark done" diff --git a/build.sh b/build.sh index 0d376c538..15367eb3e 100755 --- a/build.sh +++ b/build.sh @@ -27,7 +27,7 @@ REPODIR=$(cd "$(dirname "$0")"; pwd) LIBCUOPT_BUILD_DIR=${LIBCUOPT_BUILD_DIR:=${REPODIR}/cpp/build} LIBMPS_PARSER_BUILD_DIR=${LIBMPS_PARSER_BUILD_DIR:=${REPODIR}/cpp/libmps_parser/build} -VALIDARGS="clean libcuopt libmps_parser cuopt_mps_parser cuopt cuopt_server cuopt_sh_client docs deb -a -b -g -v -l= --verbose-pdlp [--cmake-args=\\\"\\\"] [--cache-tool=] -n --allgpuarch --ci-only-arch --show_depr_warn -h --help" +VALIDARGS="clean libcuopt libmps_parser cuopt_mps_parser cuopt cuopt_server cuopt_sh_client docs deb -a -b -g -v -l= --verbose-pdlp --build-lp-only --no-fetch-rapids --skip-c-python-adapters --skip-tests-build --skip-routing-build --skip-fatbin-write [--cmake-args=\\\"\\\"] [--cache-tool=] -n --allgpuarch --ci-only-arch --show_depr_warn -h --help" HELP="$0 [ ...] [ ...] where is: clean - remove all existing build artifacts and configuration (start over) @@ -45,8 +45,14 @@ HELP="$0 [ ...] [ ...] -a - Enable assertion (by default in debug mode) -b - Build with benchmark settings -n - no install step + --no-fetch-rapids - don't fetch rapids dependencies -l= - log level. Options are: TRACE | DEBUG | INFO | WARN | ERROR | CRITICAL | OFF. Default=INFO --verbose-pdlp - verbose mode for pdlp solver + --build-lp-only - build only linear programming components, excluding routing package and MIP-specific files + --skip-c-python-adapters - skip building C and Python adapter files (cython_solve.cu and cuopt_c.cpp) + --skip-tests-build - disable building of all tests + --skip-routing-build - skip building routing components + --skip-fatbin-write - skip the fatbin write --cache-tool= - pass the build cache tool (eg: ccache, sccache, distcc) that will be used to speedup the build process. --cmake-args=\\\"\\\" - pass arbitrary list of CMake configuration options (escape all quotes in argument) @@ -78,6 +84,11 @@ INSTALL_TARGET=install BUILD_DISABLE_DEPRECATION_WARNING=ON BUILD_ALL_GPU_ARCH=0 BUILD_CI_ONLY=0 +BUILD_LP_ONLY=0 +SKIP_C_PYTHON_ADAPTERS=0 +SKIP_TESTS_BUILD=0 +SKIP_ROUTING_BUILD=0 +WRITE_FATBIN=1 CACHE_ARGS=() PYTHON_ARGS_FOR_INSTALL=("-m" "pip" "install" "--no-build-isolation" "--no-deps") LOGGING_ACTIVE_LEVEL="INFO" @@ -208,6 +219,9 @@ fi if hasArg -n; then INSTALL_TARGET="" fi +if hasArg --no-fetch-rapids; then + FETCH_RAPIDS=OFF +fi if hasArg --allgpuarch; then BUILD_ALL_GPU_ARCH=1 fi @@ -217,6 +231,22 @@ fi if hasArg --show_depr_warn; then BUILD_DISABLE_DEPRECATION_WARNING=OFF fi +if hasArg --build-lp-only; then + BUILD_LP_ONLY=1 + SKIP_ROUTING_BUILD=1 # Automatically skip routing when building LP-only +fi +if hasArg --skip-c-python-adapters; then + SKIP_C_PYTHON_ADAPTERS=1 +fi +if hasArg --skip-tests-build; then + SKIP_TESTS_BUILD=1 +fi +if hasArg --skip-routing-build; then + SKIP_ROUTING_BUILD=1 +fi +if hasArg --skip-fatbin-write; then + WRITE_FATBIN=0 +fi function contains_string { local search_string="$1" @@ -264,6 +294,12 @@ if [ ${BUILD_CI_ONLY} -eq 1 ] && [ ${BUILD_ALL_GPU_ARCH} -eq 1 ]; then exit 1 fi +if [ ${BUILD_LP_ONLY} -eq 1 ] && [ ${SKIP_C_PYTHON_ADAPTERS} -eq 0 ]; then + echo "ERROR: When using --build-lp-only, you must also specify --skip-c-python-adapters" + echo "The C and Python adapter files (cython_solve.cu and cuopt_c.cpp) are not compatible with LP-only builds" + exit 1 +fi + if [ ${BUILD_ALL_GPU_ARCH} -eq 1 ]; then CUOPT_CMAKE_CUDA_ARCHITECTURES="RAPIDS" echo "Building for *ALL* supported GPU architectures..." @@ -308,6 +344,12 @@ if buildAll || hasArg libcuopt; then -DDISABLE_DEPRECATION_WARNING=${BUILD_DISABLE_DEPRECATION_WARNING} \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DFETCH_RAPIDS=${FETCH_RAPIDS} \ + -DBUILD_LP_ONLY=${BUILD_LP_ONLY} \ + -DSKIP_C_PYTHON_ADAPTERS=${SKIP_C_PYTHON_ADAPTERS} \ + -DBUILD_TESTS=$((1 - ${SKIP_TESTS_BUILD})) \ + -DSKIP_ROUTING_BUILD=${SKIP_ROUTING_BUILD} \ + -DWRITE_FATBIN=${WRITE_FATBIN} \ + "${CACHE_ARGS[@]}" \ "${EXTRA_CMAKE_ARGS[@]}" \ "${REPODIR}"/cpp if hasArg -n; then diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 76c856e0e..919064b87 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -52,11 +52,19 @@ option(CMAKE_CUDA_LINEINFO "Enable the -lineinfo option for nvcc useful for cuda option(BUILD_TESTS "Configure CMake to build tests" ON) option(DISABLE_OPENMP "Disable OpenMP" OFF) option(CUDA_STATIC_RUNTIME "Statically link the CUDA toolkit runtime and libraries" OFF) +option(BUILD_LP_ONLY "Build only linear programming components, exclude routing and MIP-specific files" OFF) +option(SKIP_C_PYTHON_ADAPTERS "Skip building C and Python adapter files (cython_solve.cu and cuopt_c.cpp)" OFF) +option(SKIP_ROUTING_BUILD "Skip building routing components" OFF) +option(WRITE_FATBIN "Enable fatbin writing" ON) message(VERBOSE "cuOpt: Enable nvcc -lineinfo: ${CMAKE_CUDA_LINEINFO}") message(VERBOSE "cuOpt: Build cuOpt unit-tests: ${BUILD_TESTS}") message(VERBOSE "cuOpt: Build cuOpt multigpu tests: ${BUILD_TESTS}") message(VERBOSE "cuOpt: Disable OpenMP: ${DISABLE_OPENMP}") +message(VERBOSE "cuOpt: Build LP-only mode: ${BUILD_LP_ONLY}") +message(VERBOSE "cuOpt: Skip C/Python adapters: ${SKIP_C_PYTHON_ADAPTERS}") +message(VERBOSE "cuOpt: Skip routing build: ${SKIP_ROUTING_BUILD}") +message(VERBOSE "cuOpt: fatbin: ${WRITE_FATBIN}") # ################################################################################################## # - compiler options ------------------------------------------------------------------------------ @@ -209,15 +217,17 @@ target_compile_options(cuopt "$<$:${CUOPT_CUDA_FLAGS}>" ) -file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld" - [=[ -SECTIONS -{ - .nvFatBinSegment : { *(.nvFatBinSegment) } - .nv_fatbin : { *(.nv_fatbin) } -} -]=]) -target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld") +if(WRITE_FATBIN) + file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld" + [=[ + SECTIONS + { + .nvFatBinSegment : { *(.nvFatBinSegment) } + .nv_fatbin : { *(.nv_fatbin) } + } + ]=]) + target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld") +endif() add_library(cuopt::cuopt ALIAS cuopt) # ################################################################################################## @@ -361,44 +371,63 @@ if(Doxygen_FOUND) endif() -add_executable(cuopt_cli cuopt_cli.cpp) -target_compile_options(cuopt_cli - PRIVATE "$<$:${CUOPT_CXX_FLAGS}>" - "$<$:${CUOPT_CUDA_FLAGS}>" -) +if(NOT BUILD_LP_ONLY) + add_executable(cuopt_cli cuopt_cli.cpp) + target_compile_options(cuopt_cli + PRIVATE "$<$:${CUOPT_CXX_FLAGS}>" + "$<$:${CUOPT_CUDA_FLAGS}>" + ) -target_include_directories(cuopt_cli - PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/src" - PUBLIC - "$" - "$" - "$" -) + target_include_directories(cuopt_cli + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src" + PUBLIC + "$" + "$" + "$" + ) -target_link_libraries(cuopt_cli - PUBLIC - cuopt - OpenMP::OpenMP_CXX - PRIVATE - papilo-core -) -set_property(TARGET cuopt_cli PROPERTY INSTALL_RPATH "$ORIGIN/../${lib_dir}") + target_link_libraries(cuopt_cli + PUBLIC + cuopt + OpenMP::OpenMP_CXX + PRIVATE + papilo-core + ) + set_property(TARGET cuopt_cli PROPERTY INSTALL_RPATH "$ORIGIN/../${lib_dir}") -# adds the cuopt_cli executable to the runtime deb package -install(TARGETS cuopt_cli - COMPONENT runtime - RUNTIME DESTINATION ${_BIN_DEST} -) + # adds the cuopt_cli executable to the runtime deb package + install(TARGETS cuopt_cli + COMPONENT runtime + RUNTIME DESTINATION ${_BIN_DEST} + ) +endif() + + +option(BUILD_MIP_BENCHMARKS "Build MIP benchmarks" OFF) +if(BUILD_MIP_BENCHMARKS AND NOT BUILD_LP_ONLY) + add_executable(solve_MIP ../benchmarks/linear_programming/cuopt/run_mip.cpp) + target_compile_options(solve_MIP + PRIVATE "$<$:${CUOPT_CXX_FLAGS}>" + "$<$:${CUOPT_CUDA_FLAGS}>" + ) + target_link_libraries(solve_MIP + PUBLIC + cuopt + OpenMP::OpenMP_CXX + PRIVATE + papilo-core + ) +endif() -option(BUILD_BENCHMARKS "Build benchmarks" ON) -if(BUILD_BENCHMARKS) - add_executable(solve_MPS_file ../benchmarks/linear_programming/cuopt/run_mip.cpp) - target_compile_options(solve_MPS_file +option(BUILD_LP_BENCHMARKS "Build LP benchmarks" OFF) +if(BUILD_LP_BENCHMARKS) + add_executable(solve_LP ../benchmarks/linear_programming/cuopt/run_pdlp.cu) + target_compile_options(solve_LP PRIVATE "$<$:${CUOPT_CXX_FLAGS}>" "$<$:${CUOPT_CUDA_FLAGS}>" ) - target_link_libraries(solve_MPS_file + target_link_libraries(solve_LP PUBLIC cuopt OpenMP::OpenMP_CXX diff --git a/cpp/libmps_parser/CMakeLists.txt b/cpp/libmps_parser/CMakeLists.txt index 33f0a7b58..0c0ead6ce 100644 --- a/cpp/libmps_parser/CMakeLists.txt +++ b/cpp/libmps_parser/CMakeLists.txt @@ -84,15 +84,17 @@ target_compile_options(mps_parser PRIVATE "$<$:${MPS_PARSER_CXX_FLAGS}>" ) -file(WRITE "${MPS_PARSER_BINARY_DIR}/fatbin.ld" - [=[ -SECTIONS -{ - .nvFatBinSegment : { *(.nvFatBinSegment) } - .nv_fatbin : { *(.nv_fatbin) } -} -]=]) -target_link_options(mps_parser PRIVATE "${MPS_PARSER_BINARY_DIR}/fatbin.ld") +if(WRITE_FATBIN) + file(WRITE "${MPS_PARSER_BINARY_DIR}/fatbin.ld" + [=[ + SECTIONS + { + .nvFatBinSegment : { *(.nvFatBinSegment) } + .nv_fatbin : { *(.nv_fatbin) } + } + ]=]) + target_link_options(mps_parser PRIVATE "${MPS_PARSER_BINARY_DIR}/fatbin.ld") +endif() add_library(cuopt::mps_parser ALIAS mps_parser) diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 18d83f393..1ffa94fc0 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -19,7 +19,12 @@ set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu add_subdirectory(linear_programming) add_subdirectory(math_optimization) add_subdirectory(mip) -add_subdirectory(routing) + +# Only build routing for full builds, not LP-only builds +if(NOT SKIP_ROUTING_BUILD) + add_subdirectory(routing) +endif() + add_subdirectory(dual_simplex) set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/linear_programming/CMakeLists.txt b/cpp/src/linear_programming/CMakeLists.txt index 45fa59134..e2deef2e4 100644 --- a/cpp/src/linear_programming/CMakeLists.txt +++ b/cpp/src/linear_programming/CMakeLists.txt @@ -13,10 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(LP_SRC_FILES +# Core LP files always included +set(LP_CORE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu ${CMAKE_CURRENT_SOURCE_DIR}/optimization_problem.cu - ${CMAKE_CURRENT_SOURCE_DIR}/utilities/cython_solve.cu ${CMAKE_CURRENT_SOURCE_DIR}/utilities/problem_checking.cu ${CMAKE_CURRENT_SOURCE_DIR}/solve.cu ${CMAKE_CURRENT_SOURCE_DIR}/pdlp.cu @@ -34,7 +34,19 @@ set(LP_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/termination_strategy/termination_strategy.cu ${CMAKE_CURRENT_SOURCE_DIR}/termination_strategy/infeasibility_information.cu ${CMAKE_CURRENT_SOURCE_DIR}/termination_strategy/convergence_information.cu +) + +# C and Python adapter files +set(LP_ADAPTER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/utilities/cython_solve.cu ${CMAKE_CURRENT_SOURCE_DIR}/cuopt_c.cpp ) +# Choose which files to include based on build mode +if(SKIP_C_PYTHON_ADAPTERS) + set(LP_SRC_FILES ${LP_CORE_FILES}) +else() + set(LP_SRC_FILES ${LP_CORE_FILES} ${LP_ADAPTER_FILES}) +endif() + set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${LP_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/CMakeLists.txt b/cpp/src/mip/CMakeLists.txt index 43c007280..8f859e2d0 100644 --- a/cpp/src/mip/CMakeLists.txt +++ b/cpp/src/mip/CMakeLists.txt @@ -13,15 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(MIP_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/problem/problem.cu) - -list(PREPEND - MIP_SRC_FILES +# Files necessary for Linear Programming functionality +set(MIP_LP_NECESSARY_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/problem/problem.cu + ${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu + ${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu ${CMAKE_CURRENT_SOURCE_DIR}/problem/write_mps.cu + ${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/simple_rounding.cu + ${CMAKE_CURRENT_SOURCE_DIR}/presolve/third_party_presolve.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/solution/solution.cu +) + +# Files that are MIP-specific and not needed for pure LP +set(MIP_NON_LP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/solve.cu ${CMAKE_CURRENT_SOURCE_DIR}/solver.cu - ${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu - ${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu ${CMAKE_CURRENT_SOURCE_DIR}/diversity/assignment_hash_map.cu ${CMAKE_CURRENT_SOURCE_DIR}/diversity/diversity_manager.cu ${CMAKE_CURRENT_SOURCE_DIR}/diversity/multi_armed_bandit.cu @@ -32,7 +38,6 @@ list(PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/constraint_prop.cu ${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/lb_bounds_repair.cu ${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/lb_constraint_prop.cu - ${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/simple_rounding.cu ${CMAKE_CURRENT_SOURCE_DIR}/local_search/feasibility_pump/feasibility_pump.cu ${CMAKE_CURRENT_SOURCE_DIR}/local_search/line_segment_search/line_segment_search.cu ${CMAKE_CURRENT_SOURCE_DIR}/presolve/bounds_presolve.cu @@ -42,12 +47,18 @@ list(PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/presolve/load_balanced_bounds_presolve.cu ${CMAKE_CURRENT_SOURCE_DIR}/presolve/multi_probe.cu ${CMAKE_CURRENT_SOURCE_DIR}/presolve/probing_cache.cu - ${CMAKE_CURRENT_SOURCE_DIR}/presolve/third_party_presolve.cpp ${CMAKE_CURRENT_SOURCE_DIR}/presolve/trivial_presolve.cu ${CMAKE_CURRENT_SOURCE_DIR}/problem/load_balanced_problem.cu ${CMAKE_CURRENT_SOURCE_DIR}/feasibility_jump/feasibility_jump.cu ${CMAKE_CURRENT_SOURCE_DIR}/feasibility_jump/feasibility_jump_kernels.cu - ${CMAKE_CURRENT_SOURCE_DIR}/solution/solution.cu) +) + +# Choose which files to include based on build mode +if(BUILD_LP_ONLY) + set(MIP_SRC_FILES ${MIP_LP_NECESSARY_FILES}) +else() + set(MIP_SRC_FILES ${MIP_LP_NECESSARY_FILES} ${MIP_NON_LP_FILES}) +endif() set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${MIP_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 6e413319b..691b6992e 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -13,28 +13,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -add_library(cuopttestutils STATIC - routing/utilities/check_constraints.cu -) +if(BUILD_TESTS) + add_library(cuopttestutils STATIC + routing/utilities/check_constraints.cu + ) -target_compile_options(cuopttestutils - PUBLIC "$<$:${CUOPT_CXX_FLAGS}>" - "$:${CUOPT_CUDA_FLAGS}>>" -) + target_compile_options(cuopttestutils + PUBLIC "$<$:${CUOPT_CXX_FLAGS}>" + "$:${CUOPT_CUDA_FLAGS}>>" + ) -target_include_directories(cuopttestutils - PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/../src" - "${CMAKE_CURRENT_SOURCE_DIR}" -) + target_include_directories(cuopttestutils + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../src" + "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + target_link_libraries(cuopttestutils + PUBLIC + cuopt + GTest::gmock + GTest::gtest + papilo-core + ) +endif() -target_link_libraries(cuopttestutils - PUBLIC - cuopt - GTest::gmock - GTest::gtest - papilo-core -) set(CUOPT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -82,12 +85,18 @@ if(RAPIDS_DATASET_ROOT_DIR) endif(RAPIDS_DATASET_ROOT_DIR) # ## test sources -add_subdirectory(routing) -add_subdirectory(linear_programming) -add_subdirectory(distance_engine) -add_subdirectory(mip) -add_subdirectory(dual_simplex) -add_subdirectory(examples) -add_subdirectory(utilities) +if(BUILD_TESTS) + if(NOT SKIP_ROUTING_BUILD) + add_subdirectory(routing) + add_subdirectory(distance_engine) + add_subdirectory(examples) + endif() + if(NOT BUILD_LP_ONLY) + add_subdirectory(mip) + endif() + add_subdirectory(linear_programming) + add_subdirectory(dual_simplex) + add_subdirectory(utilities) -enable_testing() + enable_testing() +endif()