diff options
| author | Glenn Smith <glenn@vector35.com> | 2022-02-01 16:34:18 -0500 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2022-02-02 19:22:08 -0500 |
| commit | b8af211f9a3647687c7e45c0fd04b0768df87ffe (patch) | |
| tree | 64f13fe262399189d70aadf33e1c6e33f0a74c3e | |
| parent | 5f5785fd2b1cee6bc9a082e1209de00b1497d410 (diff) | |
Fancier CMake: find scripts, out-of-tree example builds
23 files changed, 492 insertions, 225 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b504c1b4..029c53c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) -project(binaryninjaapi) +project(binaryninjaapi CXX C) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") option(BN_API_BUILD_EXAMPLES "Builds example plugins" OFF) @@ -14,35 +15,6 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) endif() endif() -if(WIN32) - if(NOT BN_INSTALL_DIR) - set(BN_INSTALL_DIR "C:\\Program Files\\Vector35\\BinaryNinja" - CACHE PATH "Binary Ninja installation directory") - endif() - set(BN_INSTALL_BIN_DIR "${BN_INSTALL_DIR}" - CACHE PATH "Binary Ninja binary directory") - set(BN_USER_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins" - CACHE PATH "Binary Ninja user plugins directory") -elseif(APPLE) - if(NOT BN_INSTALL_DIR) - set(BN_INSTALL_DIR "/Applications/Binary Ninja.app" - CACHE PATH "Binary Ninja installation directory") - endif() - set(BN_INSTALL_BIN_DIR "${BN_INSTALL_DIR}/Contents/MacOS" - CACHE PATH "Binary Ninja binary directory") - set(BN_USER_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins" - CACHE PATH "Binary Ninja user plugins directory") -else() - if(NOT BN_INSTALL_DIR) - set(BN_INSTALL_DIR "$ENV{HOME}/binaryninja" - CACHE PATH "Binary Ninja installation directory") - endif() - set(BN_INSTALL_BIN_DIR "${BN_INSTALL_DIR}" - CACHE PATH "Binary Ninja binary directory") - set(BN_USER_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins" - CACHE PATH "Binary Ninja user plugins directory") -endif() - file(GLOB BN_API_SOURCES *.cpp *.h json/json.h json/json-forwards.h) if(NOT DEMO) list(APPEND BN_API_SOURCES json/jsoncpp.cpp) @@ -53,70 +25,64 @@ add_library(binaryninjaapi STATIC ${BN_API_SOURCES}) target_include_directories(binaryninjaapi PUBLIC ${PROJECT_SOURCE_DIR}) -# We only need to find the core and UI when we also build the examples -if((NOT BN_CORE_LIBRARY) AND (NOT BN_INTERNAL_BUILD)) - find_library(BN_CORE_LIBRARY REQUIRED - NAMES binaryninjacore libbinaryninjacore.so.1 - PATHS ${BN_INSTALL_BIN_DIR}) +find_package(BinaryNinjaCore REQUIRED) +target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) +target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) +target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) - if(BN_CORE_LIBRARY) - message(STATUS "Binary Ninja Core: ${BN_CORE_LIBRARY}") - else() - message(FATAL_ERROR "Binary Ninja Core Not Found") - endif() -endif() +set_target_properties(binaryninjaapi PROPERTIES + CXX_STANDARD 17 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out) if(NOT HEADLESS) - if((NOT BN_UI_LIBRARY) AND (NOT BN_INTERNAL_BUILD)) - find_library(BN_UI_LIBRARY REQUIRED - NAMES binaryninjaui libbinaryninjaui.so.1 - PATHS ${BN_INSTALL_BIN_DIR}) + if(NOT BN_INTERNAL_BUILD) + # For backwards compatibility, include binaryninjaui in the api module + # If you don't need it, you can safely ignore these warnings - if(BN_UI_LIBRARY) - message(STATUS "Binary Ninja UI: ${BN_UI_LIBRARY}") + find_package(BinaryNinjaUI) + if(BinaryNinjaUI_FOUND) + # Precompiled ui library + add_library(binaryninjaui INTERFACE) + target_link_libraries(binaryninjaui INTERFACE ${BinaryNinjaUI_LIBRARIES}) + target_link_directories(binaryninjaui INTERFACE ${BinaryNinjaUI_LIBRARY_DIRS}) + target_compile_definitions(binaryninjaui INTERFACE ${BinaryNinjaUI_DEFINITIONS}) + + # UI headers are in here + target_include_directories(binaryninjaui INTERFACE ${PROJECT_SOURCE_DIR}/ui) else() - message(FATAL_ERROR "Binary Ninja UI Not Found") + # Add a fake target for binaryninjaui to intentionally break anything that tries to link against it, + # since the find script failed and your build would otherwise break in less obvious places. + add_custom_target(binaryninjaui + COMMAND ${CMAKE_COMMAND} -E false) + message(WARNING "Binary Ninja UI not found but -DHEADLESS was not specified. You will not be able to build UI plugins.") endif() - endif() -endif() - -if(NOT BN_INTERNAL_BUILD) - target_link_libraries(binaryninjaapi PUBLIC ${BN_CORE_LIBRARY}) - target_link_directories(binaryninjaapi PUBLIC ${BN_INSTALL_BIN_DIR}) -else() - target_link_libraries(binaryninjaapi PUBLIC binaryninjacore) -endif() - -if(NOT HEADLESS) - target_include_directories(binaryninjaapi PUBLIC ${PROJECT_SOURCE_DIR}/ui) - - if(NOT BN_INTERNAL_BUILD) - target_link_libraries(binaryninjaapi PUBLIC ${BN_UI_LIBRARY}) - target_link_directories(binaryninjaapi PUBLIC ${BN_INSTALL_BIN_DIR}) else() # Nothing endif() endif() -set_target_properties(binaryninjaapi PROPERTIES - CXX_STANDARD 17 - CXX_VISIBILITY_PRESET hidden - CXX_STANDARD_REQUIRED ON - VISIBILITY_INLINES_HIDDEN ON - POSITION_INDEPENDENT_CODE ON - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out) - function(bn_install_plugin target) if(NOT BN_INTERNAL_BUILD) + # Get API source directory so we can find BinaryNinjaCore + get_target_property(BN_API_SOURCE_DIR binaryninjaapi SOURCE_DIR) + message(STATUS "${BN_API_SOURCE_DIR}") + list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake") + + # BinaryNinjaCore has the user plugins dir define that we want + find_package(BinaryNinjaCore REQUIRED) if(WIN32) install(TARGETS ${target} RUNTIME - DESTINATION ${BN_USER_PLUGINS_DIR}) + DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) install(FILES $<TARGET_PDB_FILE:${target}> - DESTINATION ${BN_USER_PLUGINS_DIR} OPTIONAL) + DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) else() install(TARGETS ${target} LIBRARY - DESTINATION ${BN_USER_PLUGINS_DIR}) + DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) endif() endif() endfunction() diff --git a/Makefile.win b/Makefile.win deleted file mode 100644 index 6073acda..00000000 --- a/Makefile.win +++ /dev/null @@ -1,67 +0,0 @@ -CFLAGS = /EHsc /DWIN32 /nologo - -TARGETDIR = bin -TARGETNAME = libbinaryninjaapi.lib -TARGET = .\$(TARGETDIR)\$(TARGETNAME) - -OBJS = \ - architecture.obj \ - backgroundtask.obj \ - basicblock.obj \ - binaryninjaapi.obj \ - binaryreader.obj \ - binaryview.obj \ - binaryviewtype.obj \ - binarywriter.obj \ - callingconvention.obj \ - databuffer.obj \ - datarenderer.obj \ - downloadprovider.obj \ - demangle.obj \ - fileaccessor.obj \ - filemetadata.obj \ - flowgraph.obj \ - flowgraphnode.obj \ - function.obj \ - functionrecognizer.obj \ - highlevelil.obj \ - highlevelilinstruction.obj \ - interaction.obj \ - linearviewcursor.obj \ - linearviewobject.obj \ - log.obj \ - lowlevelil.obj \ - lowlevelilinstruction.obj \ - mainthread.obj \ - mediumlevelil.obj \ - mediumlevelilinstruction.obj \ - metadata.obj \ - platform.obj \ - plugin.obj \ - pluginmanager.obj \ - relocationhandler.obj \ - scriptingprovider.obj \ - settings.obj \ - tempfile.obj \ - transform.obj \ - type.obj \ - undoaction.obj \ - update.obj \ - user.obj \ - jsoncpp.obj - -$(TARGET): $(OBJS) - if not exist $(TARGETDIR) mkdir $(TARGETDIR) - lib $(OBJS) /OUT:$(TARGET) - -jsoncpp.obj: json\jsoncpp.cpp - cl $(CFLAGS) /I. /c json\jsoncpp.cpp - -# nmake "inference rules" are gnu make "pattern rules" -.cpp.obj: - cl $(CFLAGS) /c $< - -clean: - if exist *.obj del *.obj - if exist $(TARGETDIR) del /Q /S $(TARGETDIR) - diff --git a/cmake/FindBinaryNinjaCore.cmake b/cmake/FindBinaryNinjaCore.cmake new file mode 100644 index 00000000..e497e794 --- /dev/null +++ b/cmake/FindBinaryNinjaCore.cmake @@ -0,0 +1,111 @@ +# Try to find a Binary Ninja installation +# Once done this will define +# BinaryNinjaCore_FOUND - If Binary Ninja Core is found +# BinaryNinjaCore_ROOT_DIR - The installation path of Binary Ninja +# BinaryNinjaCore_USER_PLUGINS_DIR - The path for user plugins +# BinaryNinjaCore_INCLUDE_DIRS - The directories to include for compiling core plugins +# BinaryNinjaCore_LIBRARIES - The libraries for linking core plugins +# BinaryNinjaCore_LIBRARY_DIRS - The link paths required for core plugins +# BinaryNinjaCore_DEFINITIONS - Compiler switches required for core plugins +# +# According to Good CMake Hygiene, we should use BinaryNinjaCore_<VAR> named variables. +# Existing plugins likely use BN_<VAR> names already, so both are provided. + +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + +if(NOT BN_INTERNAL_BUILD) + set(PATH_HINTS "$ENV{BN_INSTALL_DIR}") + if(WIN32) + # System-wide install + list(APPEND PATH_HINTS "C:\\Program Files\\Vector35\\BinaryNinja") + # User install + list(APPEND PATH_HINTS "$ENV{LocalAppData}\\Vector35\\BinaryNinja") + elseif(APPLE) + list(APPEND PATH_HINTS "/Applications/Binary Ninja.app/Contents/MacOS") + list(APPEND PATH_HINTS "$ENV{HOME}/Applications/Binary Ninja.app/Contents/MacOS") + list(APPEND PATH_HINTS "$ENV{BN_INSTALL_DIR}/Contents/MacOS") + else() + list(APPEND PATH_HINTS "$ENV{HOME}/binaryninja") + endif() + + find_library(CORE_LIBRARY + NAMES binaryninjacore libbinaryninjacore.so.1 + HINTS ${PATH_HINTS}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(BinaryNinjaCore + FOUND_VAR BinaryNinjaCore_FOUND + REQUIRED_VARS CORE_LIBRARY + FAIL_MESSAGE "Could NOT find Binary Ninja installation. Please configure with -DBN_INSTALL_DIR=<path to Binary Ninja> or set the BN_INSTALL_DIR environment variable.") + + message(STATUS "Found Binary Ninja Core: ${CORE_LIBRARY}") + + set(BinaryNinjaCore_INCLUDE_DIRS "") + set(BinaryNinjaCore_LIBRARIES "${CORE_LIBRARY}") + set(BinaryNinjaCore_DEFINITIONS "") + + get_filename_component(INSTALL_BIN_DIR "${CORE_LIBRARY}" DIRECTORY) + message(STATUS "Binary Ninja Link Dirs: ${INSTALL_BIN_DIR}") + + if(WIN32) + set(BinaryNinjaCore_LIBRARY_DIRS "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{APPDATA}\\Binary Ninja\\plugins") + elseif(APPLE) + set(BinaryNinjaCore_LIBRARY_DIRS "${INSTALL_BIN_DIR}") + # Binary Ninja.app/Contents/MacOS/binaryninja -> Binary Ninja.app/ + get_filename_component(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}" DIRECTORY) + get_filename_component(BinaryNinjaCore_ROOT_DIR "${BinaryNinjaCore_ROOT_DIR}" DIRECTORY) + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins") + else() + set(BinaryNinjaCore_LIBRARY_DIRS "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins") + endif() + + message(STATUS "Binary Ninja Install Dir: ${BinaryNinjaCore_ROOT_DIR}") + message(STATUS "Binary Ninja User Plugins Dir: ${BinaryNinjaCore_USER_PLUGINS_DIR}") + + # Compatibility + set(BN_FOUND "${BinaryNinjaCore_FOUND}") + set(BN_INSTALL_DIR "${BinaryNinjaCore_ROOT_DIR}") + set(BN_INSTALL_BIN_DIR "${INSTALL_BIN_DIR}") + set(BN_USER_PLUGINS_DIR "${BinaryNinjaCore_USER_PLUGINS_DIR}") + set(BN_CORE_LIBRARY "${CORE_LIBRARY}") + set(BN_CORE_DEFINITIONS "${BinaryNinjaCore_DEFINITIONS}") +else() + # Internal build + set(INSTALL_BIN_DIR "${BN_CORE_OUTPUT_DIR}") + + if(WIN32) + set(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{APPDATA}\\Binary Ninja\\plugins") + elseif(APPLE) + # Binary Ninja.app/Contents/MacOS/binaryninja -> Binary Ninja.app/ + get_filename_component(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}" DIRECTORY) + get_filename_component(BinaryNinjaCore_ROOT_DIR "${BinaryNinjaCore_ROOT_DIR}" DIRECTORY) + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins") + else() + set(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_USER_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins") + endif() + + set(BinaryNinjaCore_FOUND 1) + set(BinaryNinjaCore_ROOT_DIR "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_INCLUDE_DIRS "") + set(BinaryNinjaCore_LIBRARIES binaryninjacore) + set(BinaryNinjaCore_LIBRARY_DIRS "${INSTALL_BIN_DIR}") + set(BinaryNinjaCore_DEFINITIONS "") + + message(STATUS "Found Binary Ninja Core: binaryninjacore") + message(STATUS "Binary Ninja Link Dirs: ${INSTALL_BIN_DIR}") + message(STATUS "Binary Ninja Install Dir: ${BinaryNinjaCore_ROOT_DIR}") + message(STATUS "Binary Ninja User Plugins Dir: ${BinaryNinjaCore_USER_PLUGINS_DIR}") + + set(BN_FOUND "${BinaryNinjaCore_FOUND}") + set(BN_INSTALL_DIR "${BinaryNinjaCore_ROOT_DIR}") + set(BN_INSTALL_BIN_DIR "${INSTALL_BIN_DIR}") + set(BN_USER_PLUGINS_DIR "${BinaryNinjaCore_USER_PLUGINS_DIR}") + set(BN_CORE_LIBRARY binaryninjacore) + set(BN_CORE_DEFINITIONS "${BinaryNinjaCore_DEFINITIONS}") +endif() diff --git a/cmake/FindBinaryNinjaUI.cmake b/cmake/FindBinaryNinjaUI.cmake new file mode 100644 index 00000000..608d2d87 --- /dev/null +++ b/cmake/FindBinaryNinjaUI.cmake @@ -0,0 +1,63 @@ +# Try to find Binary Ninja UI +# Once done this will define +# BinaryNinjaUI_FOUND - If Binary Ninja UI is found +# BinaryNinjaUI_INCLUDE_DIRS - The directories to include for compiling UI plugins +# BinaryNinjaUI_LIBRARIES - The libraries for linking UI plugins +# BinaryNinjaUI_LIBRARY_DIRS - The link paths required for ui plugins +# BinaryNinjaUI_DEFINITIONS - Compiler switches required for UI plugins + +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + +find_package(BinaryNinjaCore REQUIRED) + +find_library(UI_LIBRARY + NAMES binaryninjaui libbinaryninjaui.so.1 + HINTS ${BinaryNinjaCore_LIBRARY_DIRS}) + +# Use qmake to find the qt6 cmake libs, if we have it in PATH +find_program(QMAKE_COMMAND qmake) +if(QMAKE_COMMAND) + # qmake will tell us where the libs are! + execute_process( + COMMAND ${QMAKE_COMMAND} -query QT_INSTALL_LIBS + OUTPUT_VARIABLE QT_LIB_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Qt cmake files are in QT_INSTALL_LIBS/cmake + set(QT_CMAKE_PATH "${QT_LIB_PATH}/cmake") + message(STATUS "Found Qt CMake path: ${QT_CMAKE_PATH}") + list(APPEND CMAKE_MODULE_PATH ${QT_CMAKE_PATH}) +endif() + +# Also find Qt6 which is required +find_package(Qt6 COMPONENTS Core Gui Widgets) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BinaryNinjaUI + FOUND_VAR BinaryNinjaUI_FOUND + REQUIRED_VARS UI_LIBRARY Qt6_FOUND + FAIL_MESSAGE "Could NOT find Binary Ninja UI installation. Check that you are using a valid Binary Ninja, non-headless install, and qmake is in your PATH.") + +if(NOT Qt6_FOUND) + message(WARNING "Could not find Qt6! Make sure qmake is in your PATH.") +else() + message(STATUS "Found Binary Ninja UI: ${UI_LIBRARY}") +endif() + +# UI headers are added in the api cmake +set(BinaryNinjaUI_INCLUDE_DIRS "") + +set(BinaryNinjaUI_LIBRARIES "${UI_LIBRARY}") +list(APPEND BinaryNinjaUI_LIBRARIES Qt6::Core) +list(APPEND BinaryNinjaUI_LIBRARIES Qt6::Gui) +list(APPEND BinaryNinjaUI_LIBRARIES Qt6::Widgets) +set(BinaryNinjaUI_DEFINITIONS "") +set(BinaryNinjaUI_LIBRARY_DIRS "${BinaryNinjaCore_LIBRARY_DIRS}") + +# Compatibility +set(BN_UI_LIBRARY "${UI_LIBRARY}") +set(BN_UI_LIBRARY_DIRS "${BinaryNinjaUI_LIBRARY_DIRS}") +set(BN_UI_DEFINITIONS "${BinaryNinjaUI_DEFINITIONS}") + + + diff --git a/examples/bin-info/CMakeLists.txt b/examples/bin-info/CMakeLists.txt index 708136c0..4f0815ac 100644 --- a/examples/bin-info/CMakeLists.txt +++ b/examples/bin-info/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(bin-info CXX) +project(bin-info CXX C) add_executable(${PROJECT_NAME} src/bin-info.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/bin-info/Makefile.win b/examples/bin-info/Makefile.win deleted file mode 100644 index b65bfb86..00000000 --- a/examples/bin-info/Makefile.win +++ /dev/null @@ -1,9 +0,0 @@ -BINJA_API_INC_PATH = ..\..\ -BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib -BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" - -FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) - -bininfo: ./src/bin-info.cpp - if not exist bin mkdir bin - cl ./src/bin-info.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/breakpoint/CMakeLists.txt b/examples/breakpoint/CMakeLists.txt index 0ec4cb0d..8ede6524 100644 --- a/examples/breakpoint/CMakeLists.txt +++ b/examples/breakpoint/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(breakpoint CXX) +project(breakpoint CXX C) add_library(${PROJECT_NAME} SHARED src/breakpoint.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/breakpoint/Makefile.win b/examples/breakpoint/Makefile.win deleted file mode 100644 index 00cbbfa1..00000000 --- a/examples/breakpoint/Makefile.win +++ /dev/null @@ -1,16 +0,0 @@ -BINJA_API_INC_PATH = ..\..\ -BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib -BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" - -FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) - -bininfo.dll: ./src/breakpoint.cpp - if not exist bin mkdir bin - cl ./src/breakpoint.cpp /LD $(FLAGS) /OUT:.\bin\breakpoint.dll - -clean: - if exist *.obj del *.obj - if exist *.exp del *.exp - if exist *.lib del *.lib - if exist *.dll del *.dll - if exist .\bin del /S /Q bin diff --git a/examples/cmdline_disasm/CMakeLists.txt b/examples/cmdline_disasm/CMakeLists.txt index e4b14da5..2657b920 100644 --- a/examples/cmdline_disasm/CMakeLists.txt +++ b/examples/cmdline_disasm/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(cmdline_disasm CXX) +project(cmdline_disasm CXX C) add_executable(${PROJECT_NAME} src/disasm.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt index 899fc8d1..6c57dfd5 100644 --- a/examples/llil_parser/CMakeLists.txt +++ b/examples/llil_parser/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(llil_parser CXX) +project(llil_parser CXX C) add_executable(${PROJECT_NAME} src/llil_parser.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/llil_parser/Makefile.win b/examples/llil_parser/Makefile.win deleted file mode 100644 index fb714c0b..00000000 --- a/examples/llil_parser/Makefile.win +++ /dev/null @@ -1,9 +0,0 @@ -BINJA_API_INC_PATH = ..\..\ -BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib -BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" - -FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) - -bininfo: ./src/llil_parser.cpp - if not exist bin mkdir bin - cl ./src/llil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/mlil_parser/CMakeLists.txt b/examples/mlil_parser/CMakeLists.txt index a06a8c8e..ae4947a7 100644 --- a/examples/mlil_parser/CMakeLists.txt +++ b/examples/mlil_parser/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(mlil_parser CXX) +project(mlil_parser CXX C) add_executable(${PROJECT_NAME} src/mlil_parser.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/mlil_parser/Makefile.win b/examples/mlil_parser/Makefile.win deleted file mode 100644 index 92718ac0..00000000 --- a/examples/mlil_parser/Makefile.win +++ /dev/null @@ -1,9 +0,0 @@ -BINJA_API_INC_PATH = ..\..\ -BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib -BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" - -FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) - -bininfo: ./src/mlil_parser.cpp - if not exist bin mkdir bin - cl ./src/mlil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/print_syscalls/CMakeLists.txt b/examples/print_syscalls/CMakeLists.txt index 9ef029bb..acdc4073 100644 --- a/examples/print_syscalls/CMakeLists.txt +++ b/examples/print_syscalls/CMakeLists.txt @@ -1,10 +1,21 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(print_syscalls CXX) +project(print_syscalls CXX C) add_executable(${PROJECT_NAME} src/arm-syscall.cpp) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/examples/print_syscalls/Makefile.win b/examples/print_syscalls/Makefile.win deleted file mode 100644 index afc0cbd8..00000000 --- a/examples/print_syscalls/Makefile.win +++ /dev/null @@ -1,9 +0,0 @@ -BINJA_API_INC_PATH = ..\..\ -BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib -BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" - -FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) - -print_syscalls: ./src/arm-syscall.cpp - if not exist bin mkdir bin - cl ./src/arm-syscall.cpp $(FLAGS) /Fe:.\bin\print_syscalls diff --git a/examples/triage/CMakeLists.txt b/examples/triage/CMakeLists.txt index 05dd03ce..ca47f8f9 100644 --- a/examples/triage/CMakeLists.txt +++ b/examples/triage/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) option(QT6 "Target Qt 6" OFF) -project(triage) +project(triage CXX C) if(NOT QT6) set(CMAKE_OSX_ARCHITECTURES x86_64) @@ -18,6 +18,17 @@ else() add_library(triage SHARED ${SOURCES}) endif() +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(triage binaryninjaapi binaryninjaui) set_target_properties(triage PROPERTIES diff --git a/examples/uinotification/CMakeLists.txt b/examples/uinotification/CMakeLists.txt index df9bdbdc..552387dd 100644 --- a/examples/uinotification/CMakeLists.txt +++ b/examples/uinotification/CMakeLists.txt @@ -2,32 +2,31 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) option(QT6 "Target Qt 6" OFF) -project(uinotification) +project(uinotification CXX C) if(NOT QT6) set(CMAKE_OSX_ARCHITECTURES x86_64) endif() -if(QT6) - find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED) -else() - find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) -endif() - file(GLOB SOURCES *.cpp *.h) add_library(uinotification SHARED ${SOURCES}) -if(QT6) - target_link_libraries(uinotification binaryninjaapi binaryninjaui - Qt6::Core Qt6::Gui Qt6::Widgets) -else() - target_link_libraries(uinotification binaryninjaapi binaryninjaui - Qt5::Core Qt5::Gui Qt5::Widgets) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) endif() +target_link_libraries(uinotification binaryninjaapi binaryninjaui) + set_target_properties(uinotification PROPERTIES CXX_STANDARD 17 CXX_VISIBILITY_PRESET hidden diff --git a/examples/workflows/inliner/CMakeLists.txt b/examples/workflows/inliner/CMakeLists.txt index c42d580e..0a271d4b 100644 --- a/examples/workflows/inliner/CMakeLists.txt +++ b/examples/workflows/inliner/CMakeLists.txt @@ -9,6 +9,17 @@ file(GLOB SOURCES add_library(workflow_inliner SHARED ${SOURCES}) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(workflow_inliner binaryninjaapi) set_target_properties(workflow_inliner PROPERTIES diff --git a/examples/workflows/objectivec/CMakeLists.txt b/examples/workflows/objectivec/CMakeLists.txt index f5f8ea5e..a4c0198a 100644 --- a/examples/workflows/objectivec/CMakeLists.txt +++ b/examples/workflows/objectivec/CMakeLists.txt @@ -9,6 +9,17 @@ file(GLOB SOURCES add_library(workflow_objectivec SHARED ${SOURCES}) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(workflow_objectivec binaryninjaapi) set_target_properties(workflow_objectivec PROPERTIES diff --git a/examples/workflows/tailcall/CMakeLists.txt b/examples/workflows/tailcall/CMakeLists.txt index fa322684..6d7e5eb0 100644 --- a/examples/workflows/tailcall/CMakeLists.txt +++ b/examples/workflows/tailcall/CMakeLists.txt @@ -9,6 +9,17 @@ file(GLOB SOURCES add_library(workflow_tailcall SHARED ${SOURCES}) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(workflow_tailcall binaryninjaapi) set_target_properties(workflow_tailcall PROPERTIES diff --git a/examples/x86_extension/CMakeLists.txt b/examples/x86_extension/CMakeLists.txt index 8980ca60..9faf9c88 100644 --- a/examples/x86_extension/CMakeLists.txt +++ b/examples/x86_extension/CMakeLists.txt @@ -1,12 +1,23 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(x86_extension CXX) +project(x86_extension CXX C) add_library(${PROJECT_NAME} SHARED src/x86_extension.cpp src/asmx86/asmx86.c src/asmx86/asmx86.h) +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_DIR} + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + target_link_libraries(${PROJECT_NAME} binaryninjaapi) diff --git a/rust/examples/basic_script/CMakeLists.txt b/rust/examples/basic_script/CMakeLists.txt index a8b8e443..0aaa1a9c 100644 --- a/rust/examples/basic_script/CMakeLists.txt +++ b/rust/examples/basic_script/CMakeLists.txt @@ -25,9 +25,29 @@ endif() set(OUTPUT_FILE basic_script${CMAKE_EXECUTABLE_SUFFIX}) set(OUTPUT_PATH ${CMAKE_BINARY_DIR}/out/bin/${OUTPUT_FILE}) + +if(NOT BN_API_BUILD_EXAMPLES) + # Out-of-tree build + find_path( + BN_API_DIR + NAMES binaryninjaapi.h + HINTS ../../.. binaryninjaapi + REQUIRED + ) + add_subdirectory(${BN_API_DIR} api) +endif() + add_custom_target(test_headless ALL DEPENDS ${OUTPUT_PATH}) add_dependencies(test_headless binaryninjaapi) +# Get API source directory so we can find BinaryNinjaCore +get_target_property(BN_API_SOURCE_DIR binaryninjaapi SOURCE_DIR) +message(STATUS "${BN_API_SOURCE_DIR}") +list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake") + +# BinaryNinjaCore has the user plugins dir define that we want +find_package(BinaryNinjaCore REQUIRED) + find_program(RUSTUP_PATH rustup REQUIRED HINTS ~/.cargo/bin) set(RUSTUP_COMMAND ${RUSTUP_PATH} run ${CARGO_API_VERSION} cargo build) @@ -44,13 +64,13 @@ if(APPLE) add_custom_command( OUTPUT ${OUTPUT_PATH} COMMAND ${CMAKE_COMMAND} -E env - MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} + MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_INSTALL_BIN_DIR} ${RUSTUP_COMMAND} --target=aarch64-apple-darwin ${CARGO_OPTS} COMMAND ${CMAKE_COMMAND} -E env - MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} + MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_INSTALL_BIN_DIR} ${RUSTUP_COMMAND} --target=x86_64-apple-darwin ${CARGO_OPTS} - COMMAND cp ${AARCH64_LIB_PATH} ${OUTPUT_PATH}-aarch - COMMAND cp ${X86_64_LIB_PATH} ${OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E copy ${AARCH64_LIB_PATH} ${OUTPUT_PATH}-aarch + COMMAND ${CMAKE_COMMAND} -E copy ${X86_64_LIB_PATH} ${OUTPUT_PATH} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}) else() @@ -63,24 +83,24 @@ if(APPLE) add_custom_command( OUTPUT ${OUTPUT_PATH} COMMAND ${CMAKE_COMMAND} -E env - MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} + MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_INSTALL_BIN_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS} - COMMAND cp ${LIB_PATH} ${OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E copy ${LIB_PATH} ${OUTPUT_PATH} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}) endif() elseif(WIN32) add_custom_command( OUTPUT ${OUTPUT_PATH} - COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS} - COMMAND cp ${TARGET_DIR}/${OUTPUT_FILE} ${OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_INSTALL_BIN_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS} + COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_FILE} ${OUTPUT_PATH} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}) else() add_custom_command( OUTPUT ${OUTPUT_PATH} - COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS} - COMMAND cp ${TARGET_DIR}/${OUTPUT_FILE} ${OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_INSTALL_BIN_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS} + COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_FILE} ${OUTPUT_PATH} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}) endif() diff --git a/scripts/test_build_extern.py b/scripts/test_build_extern.py new file mode 100644 index 00000000..876b1581 --- /dev/null +++ b/scripts/test_build_extern.py @@ -0,0 +1,106 @@ +import argparse +import glob +import os +from pathlib import Path +import platform +import shutil +import subprocess +import sys +import tempfile + +import argparse + +parser = argparse.ArgumentParser( + description='Test building the API repo and plugins out-of-tree (for CI checking of end-user workflow)' +) +parser.add_argument('--headless', default=False, action='store_true', help='Only include headless plugins') +parser.add_argument('-j', '--parallel', default=4, help='Number of parallel jobs to tell cmake to run.') +args = parser.parse_args() + +try: + # Make sure we have clang! + subprocess.check_call(['clang', '-v']) +except subprocess.SubprocessError as e: + print("Clang not found! Please install clang and add it to PATH") + sys.exit(1) + +if not args.headless: + try: + # Also Qt + subprocess.check_call(['qmake', '--version']) + except subprocess.SubprocessError as e: + print("qmake not found! Please install Qt and add it to PATH") + sys.exit(1) + +api_base = Path(__file__).parent.parent.absolute() + +configure_args = [] +build_args = [] +configure_env = os.environ.copy() + +if platform.system() == "Windows": + configure_env['CXXFLAGS'] = f'/MP{args.parallel}' + configure_env['CFLAGS'] = f'/MP{args.parallel}' +else: + build_args.extend(['-j', str(args.parallel)]) + +if args.headless: + configure_args.extend(['-DHEADLESS=1']) +else: + configure_args.extend(['-DQT6=1', ]) + +# Copy api out of the source tree and build it externally +with tempfile.TemporaryDirectory() as tempdir: + temp_api_base = Path(tempdir) / 'binaryninjaapi' + print(f'Copy {api_base} => {temp_api_base}') + shutil.copytree(api_base, temp_api_base) + + # Clean up dirty repo + if (temp_api_base / 'build').exists(): + shutil.rmtree(temp_api_base / 'build') + + # Now try to build + try: + subprocess.check_call(['cmake', '-B', 'build'] + configure_args, cwd=temp_api_base, env=configure_env) + subprocess.check_call(['cmake', '--build', 'build'] + build_args, cwd=temp_api_base) + finally: + if (temp_api_base / 'build').exists(): + shutil.rmtree(temp_api_base / 'build') + + # Now try to build examples (in-tree) + try: + subprocess.check_call(['cmake', '-B', 'build', '-DBN_API_BUILD_EXAMPLES=1'] + configure_args, cwd=temp_api_base, + env=configure_env) + subprocess.check_call(['cmake', '--build', 'build'] + build_args, cwd=temp_api_base) + finally: + if (temp_api_base / 'build').exists(): + shutil.rmtree(temp_api_base / 'build') + + # Now try to build examples (out-of-tree) + for f in glob.glob(str(api_base / 'examples' / '**' / 'CMakeLists.txt'), recursive=True): + example_base = Path(f).parent + if example_base == api_base / 'examples': + continue + + # Check for headless + if args.headless: + with open(f, 'r') as cmake_file: + # Assume any ui plugin has 'binaryninjaui' in its contents + if 'binaryninjaui' in cmake_file.read(): + continue + + with tempfile.TemporaryDirectory() as tempexdir: + temp_example_base = Path(tempexdir) / example_base.name + print(f'Copy {example_base} => {temp_example_base}') + shutil.copytree(example_base, temp_example_base) + + if (temp_example_base / 'build').exists(): + shutil.rmtree(temp_example_base / 'build') + + try: + subprocess.check_call(['cmake', '-B', 'build', f'-DBN_API_DIR={temp_api_base}'] + configure_args, + cwd=temp_example_base, env=configure_env) + subprocess.check_call(['cmake', '--build', 'build'] + build_args, cwd=temp_example_base) + finally: + if (temp_example_base / 'build').exists(): + shutil.rmtree(temp_example_base / 'build') |
