diff --git a/CMakeLists.txt b/CMakeLists.txt index 50c95d0f..703a8eae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,19 @@ # Disable in-source builds to prevent source tree corruption -if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") - message(FATAL_ERROR " +if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") + message( + FATAL_ERROR + " FATAL: In-source builds are not allowed. You should create a separate directory for build files. -") +" + ) endif() cmake_minimum_required(VERSION 3.24) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" +) project(TrajoptLib LANGUAGES CXX) @@ -23,20 +29,25 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # The RPATH to be used when installing, but only if it's not a system directory -list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) -if ("${isSystemDir}" STREQUAL "-1") - list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +list( + FIND + CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES + "${CMAKE_INSTALL_PREFIX}/lib" + isSystemDir +) +if("${isSystemDir}" STREQUAL "-1") + list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif() # Set default build type to release with debug info (i.e. release mode # optimizations are performed, but debug info still exists). -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) endif() # Generate compile_commands.json by default -if (NOT CMAKE_EXPORT_COMPILE_COMMANDS) - set(CMAKE_EXPORT_COMPILE_COMMANDS "YES" CACHE STRING "" FORCE) +if(NOT CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_EXPORT_COMPILE_COMMANDS "YES" CACHE STRING "" FORCE) endif() # Control where the static and shared libraries are built so that on Windows, @@ -54,9 +65,7 @@ include(TrajoptLibCompilerFlags) file(GLOB_RECURSE src src/*.cpp) add_library(TrajoptLib ${src}) trajoptlib_compiler_flags(TrajoptLib) -target_include_directories(TrajoptLib - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_include_directories(TrajoptLib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) @@ -72,18 +81,20 @@ set(BUILD_SHARED_LIBS_SAVE ${BUILD_SHARED_LIBS}) set(BUILD_SHARED_LIBS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS_SAVE}) set(FMT_INSTALL ON) -FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG 10.1.1 +fetchcontent_declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 10.1.1 ) -FetchContent_MakeAvailable(fmt) +fetchcontent_makeavailable(fmt) set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVE}) -if (${OPTIMIZER_BACKEND} STREQUAL "casadi" AND - ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND - ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - target_compile_definitions(fmt PRIVATE _GLIBCXX_USE_CXX11_ABI=0) +if( + ${OPTIMIZER_BACKEND} STREQUAL "casadi" + AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" + AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" +) + target_compile_definitions(fmt PRIVATE _GLIBCXX_USE_CXX11_ABI=0) endif() target_link_libraries(TrajoptLib PUBLIC fmt) @@ -92,12 +103,12 @@ target_link_libraries(TrajoptLib PUBLIC fmt) set(BUILD_SHARED_LIBS_SAVE ${BUILD_SHARED_LIBS}) set(BUILD_SHARED_LIBS OFF) set(JSON_Install ON) -FetchContent_Declare( - nlohmann_json - GIT_REPOSITORY https://github.com/nlohmann/json - GIT_TAG v3.11.2 +fetchcontent_declare( + nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.2 ) -FetchContent_MakeAvailable(nlohmann_json) +fetchcontent_makeavailable(nlohmann_json) set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVE}) target_link_libraries(TrajoptLib PUBLIC nlohmann_json) @@ -105,187 +116,244 @@ target_link_libraries(TrajoptLib PUBLIC nlohmann_json) set(OPTIMIZER_BACKEND "casadi" CACHE STRING "Optimizer backend") set_property(CACHE OPTIMIZER_BACKEND PROPERTY STRINGS casadi sleipnir) -if (${OPTIMIZER_BACKEND} STREQUAL "casadi") - message(STATUS "Using CasADi optimizer") - include(FetchCasADi) - fetch_casadi() - target_compile_definitions(TrajoptLib PRIVATE OPTIMIZER_BACKEND_CASADI) - target_include_directories(TrajoptLib SYSTEM PRIVATE ${CASADI_INCLUDEDIR}) - target_link_directories(TrajoptLib PRIVATE ${CASADI_LIBDIR}) - target_link_libraries(TrajoptLib PRIVATE casadi) - - # Add current directory to RPATH - if (APPLE) - set_property(TARGET TrajoptLib - APPEND PROPERTY INSTALL_RPATH - "@loader_path/../lib;@loader_path" - ) - elseif (UNIX) - set_property(TARGET TrajoptLib - APPEND PROPERTY INSTALL_RPATH - "$ORIGIN/../lib;$ORIGIN" - ) - endif() - - # Install CasADi libraries since FetchContent setting that up properly - install(FILES ${CASADI_INSTALL_LIBS} DESTINATION ${CASADI_INSTALL_DEST}) +if(${OPTIMIZER_BACKEND} STREQUAL "casadi") + message(STATUS "Using CasADi optimizer") + include(FetchCasADi) + fetch_casadi() + target_compile_definitions(TrajoptLib PRIVATE OPTIMIZER_BACKEND_CASADI) + target_include_directories(TrajoptLib SYSTEM PRIVATE ${CASADI_INCLUDEDIR}) + target_link_directories(TrajoptLib PRIVATE ${CASADI_LIBDIR}) + target_link_libraries(TrajoptLib PRIVATE casadi) + + # Add current directory to RPATH + if(APPLE) + set_property( + TARGET TrajoptLib + APPEND + PROPERTY INSTALL_RPATH "@loader_path/../lib;@loader_path" + ) + elseif(UNIX) + set_property( + TARGET TrajoptLib + APPEND + PROPERTY INSTALL_RPATH "$ORIGIN/../lib;$ORIGIN" + ) + endif() + # Install CasADi libraries since FetchContent setting that up properly + install(FILES ${CASADI_INSTALL_LIBS} DESTINATION ${CASADI_INSTALL_DEST}) elseif(${OPTIMIZER_BACKEND} STREQUAL "sleipnir") - message(STATUS "Using Sleipnir optimizer") - include(FetchSleipnir) - fetch_sleipnir() - target_compile_definitions(TrajoptLib PRIVATE OPTIMIZER_BACKEND_SLEIPNIR) - target_link_libraries(TrajoptLib PRIVATE Sleipnir) - - # Install Sleipnir manually because EXCLUDE_FROM_ALL was used during import - install(TARGETS Sleipnir) + message(STATUS "Using Sleipnir optimizer") + include(FetchSleipnir) + fetch_sleipnir() + target_compile_definitions(TrajoptLib PRIVATE OPTIMIZER_BACKEND_SLEIPNIR) + target_link_libraries(TrajoptLib PRIVATE Sleipnir) + + # Install Sleipnir manually because EXCLUDE_FROM_ALL was used during import + install(TARGETS Sleipnir) endif() -target_include_directories(TrajoptLib - PUBLIC - $ - $) - -install(TARGETS TrajoptLib - EXPORT TrajoptLibTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include) -export(TARGETS TrajoptLib - FILE TrajoptLib.cmake - NAMESPACE TrajoptLib::) +target_include_directories( + TrajoptLib + PUBLIC + $ + $ +) + +install( + TARGETS TrajoptLib + EXPORT TrajoptLibTargets + LIBRARY + DESTINATION lib + ARCHIVE + DESTINATION lib + RUNTIME + DESTINATION bin + INCLUDES DESTINATION include +) +export(TARGETS TrajoptLib FILE TrajoptLib.cmake NAMESPACE TrajoptLib::) install(DIRECTORY include/ DESTINATION "include") -install(EXPORT TrajoptLibTargets - FILE TrajoptLib.cmake - NAMESPACE TrajoptLib:: - DESTINATION lib/cmake/TrajoptLib) +install( + EXPORT TrajoptLibTargets + FILE TrajoptLib.cmake + NAMESPACE TrajoptLib:: + DESTINATION lib/cmake/TrajoptLib +) include(CMakePackageConfigHelpers) # Generate the config file that includes the exports configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/TrajoptLibConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/TrajoptLibConfig.cmake - INSTALL_DESTINATION "lib/cmake/TrajoptLib" - NO_SET_AND_CHECK_MACRO - NO_CHECK_REQUIRED_COMPONENTS_MACRO) + ${CMAKE_CURRENT_SOURCE_DIR}/TrajoptLibConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/TrajoptLibConfig.cmake + INSTALL_DESTINATION "lib/cmake/TrajoptLib" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) # Install the config file -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/TrajoptLibConfig.cmake - DESTINATION lib/cmake/TrajoptLib) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/TrajoptLibConfig.cmake + DESTINATION lib/cmake/TrajoptLib +) # GoogleTest dependency (static linkage) set(BUILD_SHARED_LIBS_SAVE ${BUILD_SHARED_LIBS}) set(BUILD_SHARED_LIBS OFF) option(INSTALL_GMOCK "Install GoogleTest's GMock" OFF) option(INSTALL_GTEST "Install GoogleTest's GTest" OFF) -FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG v1.14.0 - CMAKE_ARGS "-DCMAKE_BUILD_TYPE=ReleaseWithDebInfo" - FIND_PACKAGE_ARGS NAMES GTest +fetchcontent_declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 + CMAKE_ARGS + "-DCMAKE_BUILD_TYPE=ReleaseWithDebInfo" + FIND_PACKAGE_ARGS NAMES GTest ) -FetchContent_MakeAvailable(googletest) +fetchcontent_makeavailable(googletest) set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVE}) include(CMakeDependentOption) -cmake_dependent_option(BUILD_TESTING "Enable creation of tests." OFF "PROJECT_IS_TOP_LEVEL" OFF) -if (BUILD_TESTING) - enable_testing() - include(GoogleTest) +cmake_dependent_option( + BUILD_TESTING + "Enable creation of tests." + OFF + "PROJECT_IS_TOP_LEVEL" + OFF +) +if(BUILD_TESTING) + enable_testing() + include(GoogleTest) endif() # Build TrajoptLib tests -if (BUILD_TESTING) - file(GLOB_RECURSE TrajoptLib_test_src test/src/*.cpp) - add_executable(TrajoptLibTest ${TrajoptLib_test_src}) - TrajoptLib_compiler_flags(TrajoptLibTest) - target_include_directories(TrajoptLibTest - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_CURRENT_SOURCE_DIR}/test/include - ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/units/include) - target_link_libraries(TrajoptLibTest - PRIVATE - TrajoptLib - fmt::fmt - GTest::gtest - GTest::gtest_main) - if (NOT CMAKE_TOOLCHAIN_FILE) - gtest_discover_tests(TrajoptLibTest) - endif() +if(BUILD_TESTING) + file(GLOB_RECURSE TrajoptLib_test_src test/src/*.cpp) + add_executable(TrajoptLibTest ${TrajoptLib_test_src}) + trajoptlib_compiler_flags(TrajoptLibTest) + target_include_directories( + TrajoptLibTest + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/test/include + ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/units/include + ) + target_link_libraries( + TrajoptLibTest + PRIVATE TrajoptLib fmt::fmt GTest::gtest GTest::gtest_main + ) + if(NOT CMAKE_TOOLCHAIN_FILE) + gtest_discover_tests(TrajoptLibTest) + endif() endif() - - # Build examples and example tests include(TrajoptLibSubdirList) trajoptlib_subdir_list(EXAMPLES ${CMAKE_CURRENT_SOURCE_DIR}/examples) foreach(example ${EXAMPLES}) - # Build example - file(GLOB_RECURSE sources examples/${example}/src/*.cpp) - add_executable(${example} ${sources}) - trajoptlib_compiler_flags(${example}) - target_include_directories(${example} - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/include) - target_link_libraries(${example} PRIVATE TrajoptLib) - - # Build example test if files exist for it - if (BUILD_TESTING AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/test) - file(GLOB_RECURSE test_sources examples/${example}/test/*.cpp) - add_executable(${example}Test ${sources} ${test_sources}) - target_include_directories(${example}Test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/src - ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/test) - trajoptlib_compiler_flags(${example}Test) - target_compile_definitions(${example}Test PUBLIC RUNNING_TESTS) - target_include_directories(${example}Test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/include) - target_link_libraries(${example}Test - PRIVATE - TrajoptLib - GTest::gtest - GTest::gtest_main) - if (NOT CMAKE_TOOLCHAIN_FILE) - gtest_discover_tests(${example}Test) + # Build example + file(GLOB_RECURSE sources examples/${example}/src/*.cpp) + add_executable(${example} ${sources}) + trajoptlib_compiler_flags(${example}) + target_include_directories( + ${example} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/include + ) + target_link_libraries(${example} PRIVATE TrajoptLib) + + # Build example test if files exist for it + if( + BUILD_TESTING + AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/test + ) + file(GLOB_RECURSE test_sources examples/${example}/test/*.cpp) + add_executable(${example}Test ${sources} ${test_sources}) + target_include_directories( + ${example}Test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/src + ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/test + ) + trajoptlib_compiler_flags(${example}Test) + target_compile_definitions(${example}Test PUBLIC RUNNING_TESTS) + target_include_directories( + ${example}Test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/examples/${example}/include + ) + target_link_libraries( + ${example}Test + PRIVATE TrajoptLib GTest::gtest GTest::gtest_main + ) + if(NOT CMAKE_TOOLCHAIN_FILE) + gtest_discover_tests(${example}Test) + endif() endif() - endif() endforeach() # Build the Java bindings option(WITH_JAVA "Build Java bindings" OFF) -cmake_dependent_option(JAVA_INSTALL_JAR "Install jar file." ON "WITH_JAVA" ON) - -if (WITH_JAVA) - add_library(TrajoptLib-java SHARED ${CMAKE_CURRENT_SOURCE_DIR}/jni/TrajoptLibJNI.cpp) - target_link_libraries(TrajoptLib-java PRIVATE TrajoptLib) - target_include_directories(TrajoptLib-java PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/jni.h) - if (${CMAKE_SYSTEM_NAME} MATCHES "MINGW" OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" OR WIN32) - target_include_directories(TrajoptLib-java PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/win32) - elseif (APPLE) - target_include_directories(TrajoptLib-java PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/darwin) - elseif (UNIX) - target_include_directories(TrajoptLib-java PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/linux) - endif() - include(InstallJavaLibs) - installjavalibs() - - # Build Jar containing embedded native libraries - if (JAVA_INSTALL_JAR) - if (UNIX) - install(CODE "execute_process(COMMAND ./gradlew jar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/java)") - elseif(${CMAKE_SYSTEM_NAME} MATCHES "MINGW" OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" OR WIN32) - install(CODE "execute_process(COMMAND .\\gradlew.bat jar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/java)") +cmake_dependent_option( + JAVA_INSTALL_JAR + "Install jar file." + ON + "WITH_JAVA" + ON +) + +if(WITH_JAVA) + add_library( + TrajoptLib-java + SHARED + ${CMAKE_CURRENT_SOURCE_DIR}/jni/TrajoptLibJNI.cpp + ) + target_link_libraries(TrajoptLib-java PRIVATE TrajoptLib) + target_include_directories( + TrajoptLib-java + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/jni.h + ) + if( + ${CMAKE_SYSTEM_NAME} MATCHES "MINGW" + OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" + OR WIN32 + ) + target_include_directories( + TrajoptLib-java + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/win32 + ) + elseif(APPLE) + target_include_directories( + TrajoptLib-java + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/darwin + ) + elseif(UNIX) + target_include_directories( + TrajoptLib-java + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/jni/linux + ) + endif() + include(InstallJavaLibs) + installjavalibs() + + # Build Jar containing embedded native libraries + if(JAVA_INSTALL_JAR) + if(UNIX) + install( + CODE + "execute_process(COMMAND ./gradlew jar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/java)" + ) + elseif( + ${CMAKE_SYSTEM_NAME} MATCHES "MINGW" + OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" + OR WIN32 + ) + install( + CODE + "execute_process(COMMAND .\\gradlew.bat jar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/java)" + ) + endif() + file(GLOB jar_files "${CMAKE_CURRENT_SOURCE_DIR}/java/build/libs/*jar") + install(FILES ${jar_files} DESTINATION java) endif() - file(GLOB jar_files "${CMAKE_CURRENT_SOURCE_DIR}/java/build/libs/*jar") - install(FILES ${jar_files} DESTINATION java) - endif() endif() diff --git a/cmake/modules/FetchCasADi.cmake b/cmake/modules/FetchCasADi.cmake index d25a5792..631f55f3 100644 --- a/cmake/modules/FetchCasADi.cmake +++ b/cmake/modules/FetchCasADi.cmake @@ -1,89 +1,111 @@ macro(fetch_casadi) - cmake_POLICY(SET CMP0135 NEW) - set(CASADI_LIBDIR ${CMAKE_BINARY_DIR}/_deps/casadi-src/casadi) - set(CASADI_INCLUDEDIR ${CMAKE_BINARY_DIR}/_deps/casadi-src/casadi/include) - if (${CMAKE_SYSTEM_NAME} MATCHES "MINGW" OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" OR WIN32) - message(STATUS "Building for Windows") - set(CASADI_URL https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-windows64-py311.zip) - set(CASADI_INSTALL_LIBS - ${CASADI_LIBDIR}/libcasadi-tp-openblas.dll - ${CASADI_LIBDIR}/libcasadi.dll - ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dll - ${CASADI_LIBDIR}/libcoinmetis-2.dll - ${CASADI_LIBDIR}/libcoinmumps-3.dll - ${CASADI_LIBDIR}/libgcc_s_seh-1.dll - ${CASADI_LIBDIR}/libgfortran-5.dll - ${CASADI_LIBDIR}/libipopt-3.dll - ${CASADI_LIBDIR}/libquadmath-0.dll - ${CASADI_LIBDIR}/libstdc++-6.dll - ${CASADI_LIBDIR}/libwinpthread-1.dll) - set(CASADI_INSTALL_DEST "bin") - elseif (APPLE) - if (CMAKE_APPLE_SILICON_PROCESSOR MATCHES "arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64") - message(STATUS "Building for macOS arm64") - set(CASADI_URL https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-osx_arm64-py311.zip) - set(CASADI_INSTALL_LIBS - ${CASADI_LIBDIR}/libcasadi.3.7.dylib - ${CASADI_LIBDIR}/libc++.1.0.dylib - ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dylib - ${CASADI_LIBDIR}/libipopt.3.dylib - ${CASADI_LIBDIR}/libcoinmumps.3.dylib - ${CASADI_LIBDIR}/libcoinmetis.2.dylib - ${CASADI_LIBDIR}/libgfortran.5.dylib - ${CASADI_LIBDIR}/libquadmath.0.dylib - ${CASADI_LIBDIR}/libgcc_s.1.1.dylib) - elseif(CMAKE_APPLE_SILICON_PROCESSOR MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") - message(STATUS "Building for macOS x86_64") - set(CASADI_URL https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-osx64-py311.zip) - set(CASADI_INSTALL_LIBS - ${CASADI_LIBDIR}/libcasadi.3.7.dylib - ${CASADI_LIBDIR}/libc++.1.0.dylib - ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dylib - ${CASADI_LIBDIR}/libipopt.3.dylib - ${CASADI_LIBDIR}/libcoinmumps.3.dylib - ${CASADI_LIBDIR}/libcoinmetis.2.dylib - ${CASADI_LIBDIR}/libgfortran.5.dylib - ${CASADI_LIBDIR}/libquadmath.0.dylib - ${CASADI_LIBDIR}/libgcc_s.1.dylib - ${CASADI_LIBDIR}/libgcc_s.1.1.dylib) + cmake_policy(SET CMP0135 NEW) + set(CASADI_LIBDIR ${CMAKE_BINARY_DIR}/_deps/casadi-src/casadi) + set(CASADI_INCLUDEDIR ${CMAKE_BINARY_DIR}/_deps/casadi-src/casadi/include) + if( + ${CMAKE_SYSTEM_NAME} MATCHES "MINGW" + OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" + OR WIN32 + ) + message(STATUS "Building for Windows") + set(CASADI_URL + https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-windows64-py311.zip + ) + set(CASADI_INSTALL_LIBS + ${CASADI_LIBDIR}/libcasadi-tp-openblas.dll + ${CASADI_LIBDIR}/libcasadi.dll + ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dll + ${CASADI_LIBDIR}/libcoinmetis-2.dll + ${CASADI_LIBDIR}/libcoinmumps-3.dll + ${CASADI_LIBDIR}/libgcc_s_seh-1.dll + ${CASADI_LIBDIR}/libgfortran-5.dll + ${CASADI_LIBDIR}/libipopt-3.dll + ${CASADI_LIBDIR}/libquadmath-0.dll + ${CASADI_LIBDIR}/libstdc++-6.dll + ${CASADI_LIBDIR}/libwinpthread-1.dll + ) + set(CASADI_INSTALL_DEST "bin") + elseif(APPLE) + if( + CMAKE_APPLE_SILICON_PROCESSOR MATCHES "arm64" + OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64" + ) + message(STATUS "Building for macOS arm64") + set(CASADI_URL + https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-osx_arm64-py311.zip + ) + set(CASADI_INSTALL_LIBS + ${CASADI_LIBDIR}/libcasadi.3.7.dylib + ${CASADI_LIBDIR}/libc++.1.0.dylib + ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dylib + ${CASADI_LIBDIR}/libipopt.3.dylib + ${CASADI_LIBDIR}/libcoinmumps.3.dylib + ${CASADI_LIBDIR}/libcoinmetis.2.dylib + ${CASADI_LIBDIR}/libgfortran.5.dylib + ${CASADI_LIBDIR}/libquadmath.0.dylib + ${CASADI_LIBDIR}/libgcc_s.1.1.dylib + ) + elseif( + CMAKE_APPLE_SILICON_PROCESSOR MATCHES "x86_64" + OR CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" + ) + message(STATUS "Building for macOS x86_64") + set(CASADI_URL + https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-osx64-py311.zip + ) + set(CASADI_INSTALL_LIBS + ${CASADI_LIBDIR}/libcasadi.3.7.dylib + ${CASADI_LIBDIR}/libc++.1.0.dylib + ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.dylib + ${CASADI_LIBDIR}/libipopt.3.dylib + ${CASADI_LIBDIR}/libcoinmumps.3.dylib + ${CASADI_LIBDIR}/libcoinmetis.2.dylib + ${CASADI_LIBDIR}/libgfortran.5.dylib + ${CASADI_LIBDIR}/libquadmath.0.dylib + ${CASADI_LIBDIR}/libgcc_s.1.dylib + ${CASADI_LIBDIR}/libgcc_s.1.1.dylib + ) + endif() + set(CASADI_INSTALL_DEST "lib") + elseif(UNIX) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64") + message(STATUS "Building for Linux arm64") + set(CASADI_URL + https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-linux-aarch64-py311.zip + ) + set(CASADI_INSTALL_LIBS + ${CASADI_LIBDIR}/libcasadi.so.3.7 + ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.so + ${CASADI_LIBDIR}/libipopt.so.3 + ${CASADI_LIBDIR}/libcoinmumps.so.3 + ${CASADI_LIBDIR}/libcoinmetis.so.2 + ${CASADI_LIBDIR}/libgfortran-040039e1.so.5.0.0 + ${CASADI_LIBDIR}/libquadmath-96973f99.so.0.0.0 + ${CASADI_LIBDIR}/libcasadi-tp-openblas.so.0 + ) + else() + message(STATUS "Building for Linux x64") + set(CASADI_URL + https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-linux64-py311.zip + ) + set(CASADI_INSTALL_LIBS + ${CASADI_LIBDIR}/libcasadi.so.3.7 + ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.so + ${CASADI_LIBDIR}/libipopt.so.3 + ${CASADI_LIBDIR}/libcoinmumps.so.3 + ${CASADI_LIBDIR}/libcoinmetis.so.2 + ${CASADI_LIBDIR}/libgfortran-040039e1.so.5.0.0 + ${CASADI_LIBDIR}/libquadmath-96973f99.so.0.0.0 + ${CASADI_LIBDIR}/libcasadi-tp-openblas.so.0 + ) + endif() + set(CASADI_INSTALL_DEST "lib") endif() - set(CASADI_INSTALL_DEST "lib") - elseif (UNIX) - if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64") - message(STATUS "Building for Linux arm64") - set(CASADI_URL https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-linux-aarch64-py311.zip) - set(CASADI_INSTALL_LIBS - ${CASADI_LIBDIR}/libcasadi.so.3.7 - ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.so - ${CASADI_LIBDIR}/libipopt.so.3 - ${CASADI_LIBDIR}/libcoinmumps.so.3 - ${CASADI_LIBDIR}/libcoinmetis.so.2 - ${CASADI_LIBDIR}/libgfortran-040039e1.so.5.0.0 - ${CASADI_LIBDIR}/libquadmath-96973f99.so.0.0.0 - ${CASADI_LIBDIR}/libcasadi-tp-openblas.so.0) - else() - message(STATUS "Building for Linux x64") - set(CASADI_URL https://github.com/casadi/casadi/releases/download/3.6.4/casadi-3.6.4-linux64-py311.zip) - set(CASADI_INSTALL_LIBS - ${CASADI_LIBDIR}/libcasadi.so.3.7 - ${CASADI_LIBDIR}/libcasadi_nlpsol_ipopt.so - ${CASADI_LIBDIR}/libipopt.so.3 - ${CASADI_LIBDIR}/libcoinmumps.so.3 - ${CASADI_LIBDIR}/libcoinmetis.so.2 - ${CASADI_LIBDIR}/libgfortran-040039e1.so.5.0.0 - ${CASADI_LIBDIR}/libquadmath-96973f99.so.0.0.0 - ${CASADI_LIBDIR}/libcasadi-tp-openblas.so.0) - endif() - set(CASADI_INSTALL_DEST "lib") - endif() - message(STATUS "Downloading CasADi from ${CASADI_URL}") + message(STATUS "Downloading CasADi from ${CASADI_URL}") - include(FetchContent) + include(FetchContent) - FetchContent_Declare( - casadi - URL ${CASADI_URL} - ) + fetchcontent_declare(casadi URL ${CASADI_URL}) - FetchContent_MakeAvailable(casadi) + fetchcontent_makeavailable(casadi) endmacro() diff --git a/cmake/modules/FetchSleipnir.cmake b/cmake/modules/FetchSleipnir.cmake index 7961ca40..78e81f94 100644 --- a/cmake/modules/FetchSleipnir.cmake +++ b/cmake/modules/FetchSleipnir.cmake @@ -1,15 +1,19 @@ macro(fetch_sleipnir) - include(FetchContent) + include(FetchContent) - FetchContent_Declare( - Sleipnir - GIT_REPOSITORY https://github.com/SleipnirGroup/Sleipnir.git - GIT_TAG 0d20a9f712f1e997f734038a977392d8bc6a19f4 - ) + fetchcontent_declare( + Sleipnir + GIT_REPOSITORY https://github.com/SleipnirGroup/Sleipnir.git + GIT_TAG 0d20a9f712f1e997f734038a977392d8bc6a19f4 + ) - FetchContent_GetProperties(Sleipnir) - if(NOT Sleipnir_POPULATED) - FetchContent_Populate(Sleipnir) - add_subdirectory(${sleipnir_SOURCE_DIR} ${sleipnir_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() + fetchcontent_getproperties(Sleipnir) + if(NOT Sleipnir_POPULATED) + fetchcontent_populate(Sleipnir) + add_subdirectory( + ${sleipnir_SOURCE_DIR} + ${sleipnir_BINARY_DIR} + EXCLUDE_FROM_ALL + ) + endif() endmacro() diff --git a/cmake/modules/InstallJavaLibs.cmake b/cmake/modules/InstallJavaLibs.cmake index fcc6f5e0..c8f9a8f8 100644 --- a/cmake/modules/InstallJavaLibs.cmake +++ b/cmake/modules/InstallJavaLibs.cmake @@ -1,37 +1,54 @@ macro(installjavalibs) - set(JAVA_LIB_TARGET_PATH ${CMAKE_CURRENT_SOURCE_DIR}/java/src/main/resources) - if (${CMAKE_SYSTEM_NAME} MATCHES "MINGW" OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" OR WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/windows/x86_64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/windows/x86) + set(JAVA_LIB_TARGET_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/java/src/main/resources + ) + if( + ${CMAKE_SYSTEM_NAME} MATCHES "MINGW" + OR ${CMAKE_SYSTEM_NAME} MATCHES "MSYS" + OR WIN32 + ) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/windows/x86_64) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/windows/x86) + endif() + elseif(APPLE) + if(CMAKE_APPLE_SILICON_PROCESSOR MATCHES "arm64") + set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/osx/arm64) + elseif(CMAKE_APPLE_SILICON_PROCESSOR MATCHES "x86_64") + set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/osx/x86_64) + endif() + elseif(UNIX) + set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/linux/x86_64) endif() - elseif (APPLE) - if (CMAKE_APPLE_SILICON_PROCESSOR MATCHES "arm64") - set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/osx/arm64) - elseif(CMAKE_APPLE_SILICON_PROCESSOR MATCHES "x86_64") - set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/osx/x86_64) - endif() - elseif (UNIX) - set(JAVA_LIB_TARGET_PATH ${JAVA_LIB_TARGET_PATH}/linux/x86_64) - endif() - message(STATUS "Path to use for java: ${JAVA_LIB_TARGET_PATH}") - install(TARGETS TrajoptLib - LIBRARY DESTINATION ${JAVA_LIB_TARGET_PATH} - RUNTIME DESTINATION ${JAVA_LIB_TARGET_PATH}) - install(TARGETS TrajoptLib-java - LIBRARY DESTINATION ${JAVA_LIB_TARGET_PATH} - RUNTIME DESTINATION ${JAVA_LIB_TARGET_PATH}) + message(STATUS "Path to use for java: ${JAVA_LIB_TARGET_PATH}") + install( + TARGETS TrajoptLib + LIBRARY + DESTINATION ${JAVA_LIB_TARGET_PATH} + RUNTIME + DESTINATION ${JAVA_LIB_TARGET_PATH} + ) + install( + TARGETS TrajoptLib-java + LIBRARY + DESTINATION ${JAVA_LIB_TARGET_PATH} + RUNTIME + DESTINATION ${JAVA_LIB_TARGET_PATH} + ) - if (OPTIMIZER_BACKEND STREQUAL "casadi") - install(FILES ${CASADI_INSTALL_LIBS} DESTINATION ${JAVA_LIB_TARGET_PATH}) - endif() + if(OPTIMIZER_BACKEND STREQUAL "casadi") + install( + FILES ${CASADI_INSTALL_LIBS} + DESTINATION ${JAVA_LIB_TARGET_PATH} + ) + endif() - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/GenerateJNILibsJSON.cmake.in" - "${CMAKE_BINARY_DIR}/GenerateJNILibsJSON.cmake" - @ONLY - ) - install(SCRIPT "${CMAKE_BINARY_DIR}/GenerateJNILibsJSON.cmake") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/GenerateJNILibsJSON.cmake.in" + "${CMAKE_BINARY_DIR}/GenerateJNILibsJSON.cmake" + @ONLY + ) + install(SCRIPT "${CMAKE_BINARY_DIR}/GenerateJNILibsJSON.cmake") endmacro() diff --git a/cmake/modules/TrajoptLibCompilerFlags.cmake b/cmake/modules/TrajoptLibCompilerFlags.cmake index c57b364c..48e787f9 100644 --- a/cmake/modules/TrajoptLibCompilerFlags.cmake +++ b/cmake/modules/TrajoptLibCompilerFlags.cmake @@ -1,50 +1,88 @@ macro(trajoptlib_compiler_flags target) - if (NOT MSVC) - target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter -Wno-missing-braces) + if(NOT MSVC) + target_compile_options( + ${target} + PRIVATE + -Wall + -pedantic + -Wextra + -Werror + -Wno-unused-parameter + -Wno-missing-braces + ) - # clang 18 warns on `operator"" _a` in dependencies - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "18") - target_compile_options(${target} PRIVATE -Wno-deprecated-literal-operator) - endif() + # clang 18 warns on `operator"" _a` in dependencies + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "18" + ) + target_compile_options( + ${target} + PRIVATE -Wno-deprecated-literal-operator + ) + endif() - if (${OPTIMIZER_BACKEND} STREQUAL "casadi" AND - ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND - ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - target_compile_definitions(${target} PRIVATE _GLIBCXX_USE_CXX11_ABI=0) - endif() + if( + ${OPTIMIZER_BACKEND} STREQUAL "casadi" + AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" + AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" + ) + target_compile_definitions( + ${target} + PRIVATE _GLIBCXX_USE_CXX11_ABI=0 + ) + endif() - # Disable warning false positives in Eigen - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "8") - target_compile_options(${target} PRIVATE -Wno-class-memaccess) - endif() - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "11") - target_compile_options(${target} PRIVATE -Wno-maybe-uninitialized) - endif() - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "12") - target_compile_options(${target} PRIVATE -Wno-array-bounds) - endif() + # Disable warning false positives in Eigen + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "8" + ) + target_compile_options(${target} PRIVATE -Wno-class-memaccess) + endif() + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "11" + ) + target_compile_options(${target} PRIVATE -Wno-maybe-uninitialized) + endif() + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "12" + ) + target_compile_options(${target} PRIVATE -Wno-array-bounds) + endif() - # Disable deprecated-anon-enum-enum-conversion warning in Eigen - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "13") - target_compile_options(${target} PRIVATE -Wno-deprecated-anon-enum-enum-conversion) - endif() + # Disable deprecated-anon-enum-enum-conversion warning in Eigen + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "13" + ) + target_compile_options( + ${target} + PRIVATE -Wno-deprecated-anon-enum-enum-conversion + ) + endif() - # Disable warning false positives in fmt - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND - ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "13") - target_compile_options(${target} PRIVATE -Wno-dangling-reference -Wno-stringop-overflow) + # Disable warning false positives in fmt + if( + ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" + AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "13" + ) + target_compile_options( + ${target} + PRIVATE -Wno-dangling-reference -Wno-stringop-overflow + ) + endif() + else() + target_compile_options( + ${target} + PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /WX + ) endif() - else() - target_compile_options(${target} PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /WX) - endif() - target_compile_features(${target} PUBLIC cxx_std_20) - if (MSVC) - target_compile_options(${target} PUBLIC /bigobj) - endif() + target_compile_features(${target} PUBLIC cxx_std_20) + if(MSVC) + target_compile_options(${target} PUBLIC /bigobj) + endif() endmacro() diff --git a/cmake/modules/TrajoptLibSubdirList.cmake b/cmake/modules/TrajoptLibSubdirList.cmake index d43186cb..e64b797f 100644 --- a/cmake/modules/TrajoptLibSubdirList.cmake +++ b/cmake/modules/TrajoptLibSubdirList.cmake @@ -1,10 +1,10 @@ macro(trajoptlib_subdir_list result curdir) - file(GLOB children RELATIVE ${curdir} ${curdir}/*) - set(dirlist "") - foreach(child ${children}) - if (IS_DIRECTORY ${curdir}/${child}) - LIST(APPEND dirlist ${child}) - endif() - endforeach() - set(${result} ${dirlist}) + file(GLOB children RELATIVE ${curdir} ${curdir}/*) + set(dirlist "") + foreach(child ${children}) + if(IS_DIRECTORY ${curdir}/${child}) + list(APPEND dirlist ${child}) + endif() + endforeach() + set(${result} ${dirlist}) endmacro() diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index ab42560c..399366d4 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -project (trajoptlib-node) +project(trajoptlib-node) add_definitions(-DNAPI_VERSION=7) @@ -29,22 +29,31 @@ target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB}) set(OPTIMIZER_BACKEND casadi) set(CMAKE_APPLE_SILICON_PROCESSOR arm64) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../build EXCLUDE_FROM_ALL) +add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../build + EXCLUDE_FROM_ALL +) target_link_libraries(${PROJECT_NAME} PRIVATE TrajoptLib) if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET) - # Generate node.lib - execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS}) + # Generate node.lib + execute_process( + COMMAND + ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} + /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS} + ) endif() # Include N-API wrappers # $ node -p "require('node-addon-api').include" # "/home/will/projects/financialcpp/financialcpp/node_modules/node-addon-api" -execute_process(COMMAND node -p "require('node-addon-api').include" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE NODE_ADDON_API_DIR - ) +execute_process( + COMMAND node -p "require('node-addon-api').include" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE NODE_ADDON_API_DIR +) # strip `"` and `\n` from the output above string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})