Skip to content

Conversation

@Johanmyst
Copy link
Contributor

As per @yuleisui's request in this pull request (1697), this pull request contains the various fixes, improvements, and other changes related to the build system.

If you'd like, I could add a section to the setup guide wiki page to explain installing & using SVF's CMake packages. Additionally, I could also add a new page detailing how to use SVF from within an out-of-tree LLVM pass directly from the default clang pass-pipeline (i.e., analyse & possibly modify a module using information from SVF's analyses during regular compilation (by simply adding a --Wl,--load-pass-plugin=libSVFUser.so)?

📝 Overview

This PR consolidates one orthogonal areas of work into one release:

  • Build System: make installs relocatable, expose ABI flags, support in- and out-of-tree usage

For full details on each change, see the linked commits below.


🚀 Highlights

Area Summary Commit
Build System Relocatable installs, ABI-flag interface, in-/out-of-tree mode 583bff0

⚙️ Detailed Changes

1️⃣ Build System ([583bff0])

  • Directory layout: moved all CMake templates into cmake/
  • Relocatable install: properly support relocation correctly (cmake --install … --install-prefix=<prefix>)
  • ABI flags: expose minimum C++ standard, PIC, etc., via an (invisible) interface library
  • pkgconfig export: generate .pc with core flags (less complete than the CMake package)
  • In-tree usage: add_subdirectory(SVF) now works transparently
  • LTO guard: error out if compiler doesn’t support LTO
  • Dependency flags: propagate Z3/LLVM ABI flags on SVF::Core & SVF::LLVM
  • Conditional version export: only set SVF_VERSION in parent scope when parent CMake project exists

2️⃣ CI/Workflow Fix ([96c021b])

  • Always pass --ignore-errors unused to all lcov --remove … calls
  • Prevent workflow failures when no coverage data exists under /usr/* or other paths
  • Ensured error suppression is applied consistently

3️⃣ Automated CMake Formatting ([0bc1472])

  • Add .cmake-format.py so cmake-format can lint & format all CMake files
  • Ensures consistent styling across CMakeLists.txt, *.cmake, etc.

4️⃣ Existence-Check APIs ([ce288cf])

  • Introduce hasLLVMValue(), hasLHSTopLevelPtr(), etc., for getters that assert on missing entries
  • Avoids breaking existing API: getters still assert, but you can pre-check
  • Getters that return nullptr on missing entries are unmodified

5️⃣ WPA Backend Polymorphism ([93446f6])

  • Mark VersionedFlowSensitive’s printStat(), dumpTopLevelPtsTo(), solveAndWritePtsToFile(), readPtsFromFile(), etc., as public
  • Enables code like:
    SVF::BVDataPTAImpl *pta = nullptr;
    switch(backend) {
      case Andersen_BASE:   pta = new Andersen(...);            break;
      case VFS_WPA:         pta = new VersionedFlowSensitive(...); break;
      default:              /**/;                              break;
    }
    

6️⃣ Optimised SVFG Read/Write Fix ([def7c04])

  • Add builder argument to build optimised SVFG without command-line option (to support using SVF as a library)
  • Write unoptimised SVFG before optimisation
  • Read unoptimised SVFG, then apply optimisation
  • Resolves crashes when reading a post-optimised file

@Johanmyst
Copy link
Contributor Author

Also: note that the coverage checks fail for this pull request because a necessary fix (in this pull request (#1702)) to the coverage test flags is not included in this pull request. That pull request fixes the flags to ensure trying to delete coverage information when it doesn't exist doesn't throw a fatal error (as it does here).

@yuleisui
Copy link
Collaborator

yuleisui commented May 8, 2025

Will your new build system impact other projects using SVF as a library, such as

https://github.com/SVF-tools/SVF-example
https://github.com/SVF-tools/Software-Security-Analysis/tree/main

If so, please submit a pull request to fix their cmake on these projects.

@yuleisui
Copy link
Collaborator

yuleisui commented May 8, 2025

Also: note that the coverage checks fail for this pull request because a necessary fix (in this pull request (#1702)) to the coverage test flags is not included in this pull request. That pull request fixes the flags to ensure trying to delete coverage information when it doesn't exist doesn't throw a fatal error (as it does here).

Thanks for this note. It looks good now

Numerous fixes and improvements to the overall build system. Core changes include:
  - Moved CMake files (templates, input, etc.) into dedicated `cmake` subdirectory
  - Fixed relocatability of install tree (support for `cmake --install <build-dir> --install-prefix=<prefix>`)
  - Relocatable packages no longer depend on absolute paths of dependencies (i.e., Z3, LLVM)
  - SVF root, source, build, and install directories now exposed properly & correctly handle relocations
  - Required ABI flags of users (e.g., minimum C++ standard, PIC, etc.) now exposed through interface library (invisible)
  - Exported `pkconfig` package defines the core required flags
  - Explicit support for using SVF in-tree (i.e., building SVF from another project's `CMakeLists.txt` with `add_subdirectory(SVF)`)
  - Added IPO compiler support check when LTO is enabled (trying to use LTO if not supported throws a fatal error)
  - Required ABI flags of dependencies (i.e., Z3, LLVM) are now exposed publically on the CMake package's libraries (i.e., `SvfCore` and `SvfLLVM`; so they are inherited when using SVF with `find_package(SVF)` and `target_link_libraries(myLib <PUBLIC|PRIVATE|INTERFACE> SVF::Core SVF::LLVM)`)
  - Exposing SVF version to parent (i.e., updating `SVF_VERSION` defined in parent scope when adding SVF with `add_subdirectory(SVF)`) now conditional on there being a parent project to suppress warnings when not using SVF this way
@yuleisui
Copy link
Collaborator

yuleisui commented May 8, 2025

Also: note that the coverage checks fail for this pull request because a necessary fix (in this pull request (#1702)) to the coverage test flags is not included in this pull request. That pull request fixes the flags to ensure trying to delete coverage information when it doesn't exist doesn't throw a fatal error (as it does here).

Thanks for this note. It looks good no

Also: note that the coverage checks fail for this pull request because a necessary fix (in this pull request (#1702)) to the coverage test flags is not included in this pull request. That pull request fixes the flags to ensure trying to delete coverage information when it doesn't exist doesn't throw a fatal error (as it does here).

Thanks for this note. It looks good now

Oops, it still has this error after merging your first PR.

@Johanmyst
Copy link
Contributor Author

I rebased from upstream now; should pass now I think

@yuleisui
Copy link
Collaborator

yuleisui commented May 8, 2025

I rebased from upstream now; should pass now I think

Thanks. Could you take a look at SVF-example and SVF courses? We may need to change their make too.

@codecov
Copy link

codecov bot commented May 8, 2025

Codecov Report

Attention: Patch coverage is 50.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 63.67%. Comparing base (0f8a828) to head (812a9ca).
Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
svf/lib/Util/ExtAPI.cpp 50.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1703      +/-   ##
==========================================
- Coverage   63.68%   63.67%   -0.01%     
==========================================
  Files         244      244              
  Lines       25975    25980       +5     
  Branches     4574     4575       +1     
==========================================
+ Hits        16541    16543       +2     
- Misses       9434     9437       +3     
Files with missing lines Coverage Δ
svf/lib/Util/ExtAPI.cpp 39.32% <50.00%> (-2.25%) ⬇️

... and 22 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bjjwwang
Copy link
Contributor

bjjwwang commented May 9, 2025

image

image
Thanks for your pull request. Now I have some issue when I use the output of SVF as dependency to build other code. You could see compared to baseline, the new version misses some key environment variables.

@yuleisui
Copy link
Collaborator

yuleisui commented May 9, 2025

image

image Thanks for your pull request. Now I have some issue when I use the output of SVF as dependency to build other code. You could see compared to baseline, the new version misses some key environment variables.

@Johanmyst, we would like to merge your build system if you could take a look and fix the above issue. Looks to me that the current build system has to work together with the projects using SVF as a lib.

@Johanmyst
Copy link
Contributor Author

Thanks for your pull request. Now I have some issue when I use the output of SVF as dependency to build other code. You could see compared to baseline, the new version misses some key environment variables.

Thanks for testing & giving feedback! While some of these variables would be trivial to add back, I removed some others on purpose as they don't work well with how (modern) CMake is structured, specifically w.r.t. relocation.

More specifically, CMake is typically used by (1) configuring (cmake -G "Ninja" -B build ...), (2) building (cmake --build build), and (3) installing a package (cmake --install build). By default, the installation prefix used by CMake is /usr/local. When running cmake --install <build_dir>, executables will be installed to <prefix>/bin/..., libraries to <prefix>/lib/..., etc. CMake currently provides 3 ways to set the installation prefix:

  1. Passing --install-prefix <prefix> during configuration
  2. Passing -DCMAKE_INSTALL_PREFIX=<prefix> during configuration
  3. Passing --prefix <prefix> during installation

While prefixes set by (1) and (2) are visible during configuration, overriding the prefix at installation (3) is not. Consequently, any paths derived from the installation prefix during configuration (i.e., when the variables you highlighted are set) could be incorrect, possibly causing issues for end-users. This is why I removed the "hardcoded" (i.e., explicitly relying on ${CMAKE_INSTALL_PREFIX}) installation paths from the exported CMake package and instead relied on CMake's package configuration helpers.

In the changes I proposed, these paths are not necessary when using the SVF CMake package. Instead, SVF's CMake package can simply be found with find_package(SVF), after which it can be linked to any target with target_link_libraries(Foo SVF::Core SVF::LLVM). CMake will then internally resolve all compiler definitions, ABI flags, include paths, dependencies, library paths, and whatever else. Manually adding target_include_directories(Foo ${SVF_INSTALL_INCLUDE_DIR}) should thus never be necessary. Hence why I omitted this from my original pull request.

However, I suppose they also can't do any harm to include. I'll create a fairly simple modification to re-add those paths explicitly, including some other optimisations. I'll test it and add it to this pull request when I'm done!

This commit incorporates the requested changes to the build system & exported variables in the SVF CMake package.
Additionally, this commit contains some minor optimisations & improvements to the existing structure, such as eliminating one forgotten instance of explicitly using `$CMAKE_INSTALL_PREFIX`
@Johanmyst
Copy link
Contributor Author

I've integrated your requested changes and made sure all existing use cases are fully supported, please see [640b3c9] for details. The main changes are:

  • Defined explicit FindZ3.cmake module to reliably find system or local Z3 instance transparently
  • Fixed minor inconsistency in generated pkgconfig definition
  • Integrated requested changes and ensured all existing variables are supported as expected (but relocatable)
  • Updated CMake logging (existing still referenced some non-existent variables/missed new options)
  • Updated generated config.h with latest options & variables
  • Simplified LLVM linking to modern LLVM recommended way of linking
  • Minor formatting fixes

Please let me know if there are any other parts you'd prefer changed or would like further clarification on!

NB: Should I update the "Setup guide" wiki page to reflect this installation method & usage?

@yuleisui
Copy link
Collaborator

yuleisui commented May 10, 2025

  • Defined explicit FindZ3.cmake module to reliably find system or local Z3 instance transparently

Thanks. When locating z3, can you make sure we need to first search for the executable from Z3HOME, and then the system-installed one, to avoid version issues.

@bjjwwang
Copy link
Contributor

bjjwwang commented May 10, 2025

image
Sorry. Still some environment variable error.

SVF_DIR= <Your SVF Root Folder>
LLVM_DIR= <Should be SVF_DIR/llvm-16.0.0.obj>
Z3_DIR= <Should be SVF_DIR/z3.obj>

git clone https://github.com/SVF-tools/SVF-example
cd SVF-example
mkdir Release-build
cd Release-build
cmake .. -DSVF_DIR=$SVF_DIR -DLLVM_DIR=$LLVM_DIR -DZ3_DIR=$Z3_DIR

You could see this. Thank you so much.

@Johanmyst
Copy link
Contributor Author

  • Defined explicit FindZ3.cmake module to reliably find system or local Z3 instance transparently

Thanks. When locating z3, can you make sure we need to first search for the executable from Z3HOME, and then the system-installed one, to avoid version issues.

Sure, no problem

image Sorry. Still some environment variable error.

SVF_DIR= <Your SVF Root Folder>
LLVM_DIR= <Should be SVF_DIR/llvm-16.0.0.obj>
Z3_DIR= <Should be SVF_DIR/z3.obj>

git clone https://github.com/SVF-tools/SVF-example
cd SVF-example
mkdir Release-build
cd Release-build
cmake .. -DSVF_DIR=$SVF_DIR -DLLVM_DIR=$LLVM_DIR -DZ3_DIR=$Z3_DIR

You could see this. Thank you so much.

This error actually looks to be the result of using the SVF CMake package in the build tree instead of the installation tree. The find_package() macro in CMake first searches paths passed in HINTS, so this snippet will cause CMake to search for SVFConfig.cmake in $SVF_DIR/[Release|Debug]-build before any installation directories (e.g., the standard installation prefix /usr/local and thus finding /usr/local/lib/cmake/SVFConfig.cmake).

However, the CMake macros to create (relocatable) packages only run during installation, so the paths set here are not valid. Because set_and_check is used, an error is thrown. Previously, these paths were not relocatable and simply used the CMAKE_INSTALL_PREFIX available during configuration of the SVF build. While this meant they were set — and the manual linking by adding linker flags -lSvfLLVM and -lSvfCore — they would be incorrect and fail if a user were to change the installation prefix after configuration (e.g., with the standard command-line flags: cmake --install Release-build --prefix <new_prefix>). To ensure the CMake package behaves as expected, set_and_check verifies that the paths exist and are valid, so that any linking/searching done by CMake will happen as expected.

I've modified the using-SVF-as-a-library-example locally, and this minimal CMakeLists.txt works perfectly fine:

cmake_minimum_required(VERSION 3.23)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(
  SVF-example
  VERSION 1.0
  DESCRIPTION "An external project example using SVF as a library"
  HOMEPAGE_URL "https://github.com/SVF-tools/SVF-example"
  LANGUAGES C CXX)

# Find the SVF CMake package (pass $SVF_DIR as a (prioritised) hint) Set
# $SVF_DIR to the installation prefix used to install SVF
find_package(
  SVF
  3.0
  REQUIRED
  CONFIG
  HINTS
  ${SVF_DIR}
  $ENV{SVF_DIR})

# Define the primary (minimal) example using SVF as library in an executable
add_executable(svf-example src/bin-example.cpp)

# Only link against SVF; LLVM & Z3 dependencies are resolved internally
target_link_libraries(svf-example PRIVATE SVF::SvfCore SVF::SvfLLVM)

# Set the executable example to install to the local directory (as prefix)
install(TARGETS svf-example RUNTIME DESTINATION bin)

# Generate <prefix>/data/input.ll from src/input.c whenever BinExample is built
add_custom_command(
  TARGET svf-example
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_PREFIX}/data
  COMMAND
    clang -S -c -Xclang -disable-O0-optnone -fno-discard-value-names -emit-llvm
    ${CMAKE_CURRENT_SOURCE_DIR}/src/input.c -o
    ${CMAKE_INSTALL_PREFIX}/data/input.ll
  COMMAND opt -S -p=mem2reg ${CMAKE_INSTALL_PREFIX}/data/input.ll -o
          ${CMAKE_INSTALL_PREFIX}/data/input.ll
  COMMENT "→ generating LLVM IR for src/input.c → data/input.ll")

This script can simply be used like this:

# Configure, build, and install the example (also generated input.ll)
cmake -S ./ --install-prefix=$(pwd) -B build
cmake --build build
cmake --install build

# Run the example
./bin/svf-example ./data/input.ll

This assumes SVF was built and installed in the standard CMake way (which will install SVF to ~/SVF/install):

https://github.com/SVF-tools/SVF.git ~/SVF
cd ~/SVF
cmake -G "Ninja" -S ./ -B Release-build -DCMAKE_BUILD_TYPE=Release <other_options> --install-prefix=$(realpath ./install)
cmake --build Release-build
cmake --install Release-build

If the installation prefix was kept as the default (i.e., /usr/local), CMake would already find the SVF package. However, in this example I installed SVF to ~/SVF/install, so I'd need to make sure CMake can find the non-standard installation location, for example by adding ~/SVF/install to $CMAKE_PREFIX_PATH, passing ~/SVF/install to the find_package(SVF ...) invocation, or by setting $SVF_DIR to ~/SVF/install.

Of course, using SVF in its build tree is still possible by manually including & linking the build tree (e.g., when using SVF from a non-CMake build system) with environment variables like $PATH and $LD_LIBRARY_PATH, or by passing flags like -L<path/to/SVF/build>/lib or -I<path/to/SVF/build>/include. However, using the CMake package within the build tree is not how CMake is meant to be used and can lead to unexpected behaviours and errors, so I'm not sure supporting these cases silently is the best approach, especially since it requires breaking relocatability and default CMake flags for setting the installation prefix like --prefix. What do you think?

@yuleisui
Copy link
Collaborator

  • Defined explicit FindZ3.cmake module to reliably find system or local Z3 instance transparently

Thanks. When locating z3, can you make sure we need to first search for the executable from Z3HOME, and then the system-installed one, to avoid version issues.

Sure, no problem

image Sorry. Still some environment variable error.

SVF_DIR= <Your SVF Root Folder>
LLVM_DIR= <Should be SVF_DIR/llvm-16.0.0.obj>
Z3_DIR= <Should be SVF_DIR/z3.obj>

git clone https://github.com/SVF-tools/SVF-example
cd SVF-example
mkdir Release-build
cd Release-build
cmake .. -DSVF_DIR=$SVF_DIR -DLLVM_DIR=$LLVM_DIR -DZ3_DIR=$Z3_DIR

You could see this. Thank you so much.

This error actually looks to be the result of using the SVF CMake package in the build tree instead of the installation tree. The find_package() macro in CMake first searches paths passed in HINTS, so this snippet will cause CMake to search for SVFConfig.cmake in $SVF_DIR/[Release|Debug]-build before any installation directories (e.g., the standard installation prefix /usr/local and thus finding /usr/local/lib/cmake/SVFConfig.cmake).

However, the CMake macros to create (relocatable) packages only run during installation, so the paths set here are not valid. Because set_and_check is used, an error is thrown. Previously, these paths were not relocatable and simply used the CMAKE_INSTALL_PREFIX available during configuration of the SVF build. While this meant they were set — and the manual linking by adding linker flags -lSvfLLVM and -lSvfCore — they would be incorrect and fail if a user were to change the installation prefix after configuration (e.g., with the standard command-line flags: cmake --install Release-build --prefix <new_prefix>). To ensure the CMake package behaves as expected, set_and_check verifies that the paths exist and are valid, so that any linking/searching done by CMake will happen as expected.

I've modified the using-SVF-as-a-library-example locally, and this minimal CMakeLists.txt works perfectly fine:

cmake_minimum_required(VERSION 3.23)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(
  SVF-example
  VERSION 1.0
  DESCRIPTION "An external project example using SVF as a library"
  HOMEPAGE_URL "https://github.com/SVF-tools/SVF-example"
  LANGUAGES C CXX)

# Find the SVF CMake package (pass $SVF_DIR as a (prioritised) hint) Set
# $SVF_DIR to the installation prefix used to install SVF
find_package(
  SVF
  3.0
  REQUIRED
  CONFIG
  HINTS
  ${SVF_DIR}
  $ENV{SVF_DIR})

# Define the primary (minimal) example using SVF as library in an executable
add_executable(svf-example src/bin-example.cpp)

# Only link against SVF; LLVM & Z3 dependencies are resolved internally
target_link_libraries(svf-example PRIVATE SVF::SvfCore SVF::SvfLLVM)

# Set the executable example to install to the local directory (as prefix)
install(TARGETS svf-example RUNTIME DESTINATION bin)

# Generate <prefix>/data/input.ll from src/input.c whenever BinExample is built
add_custom_command(
  TARGET svf-example
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_PREFIX}/data
  COMMAND
    clang -S -c -Xclang -disable-O0-optnone -fno-discard-value-names -emit-llvm
    ${CMAKE_CURRENT_SOURCE_DIR}/src/input.c -o
    ${CMAKE_INSTALL_PREFIX}/data/input.ll
  COMMAND opt -S -p=mem2reg ${CMAKE_INSTALL_PREFIX}/data/input.ll -o
          ${CMAKE_INSTALL_PREFIX}/data/input.ll
  COMMENT "→ generating LLVM IR for src/input.c → data/input.ll")

This script can simply be used like this:

# Configure, build, and install the example (also generated input.ll)
cmake -S ./ --install-prefix=$(pwd) -B build
cmake --build build
cmake --install build

# Run the example
./bin/svf-example ./data/input.ll

This assumes SVF was built and installed in the standard CMake way (which will install SVF to ~/SVF/install):

https://github.com/SVF-tools/SVF.git ~/SVF
cd ~/SVF
cmake -G "Ninja" -S ./ -B Release-build -DCMAKE_BUILD_TYPE=Release <other_options> --install-prefix=$(realpath ./install)
cmake --build Release-build
cmake --install Release-build

If the installation prefix was kept as the default (i.e., /usr/local), CMake would already find the SVF package. However, in this example I installed SVF to ~/SVF/install, so I'd need to make sure CMake can find the non-standard installation location, for example by adding ~/SVF/install to $CMAKE_PREFIX_PATH, passing ~/SVF/install to the find_package(SVF ...) invocation, or by setting $SVF_DIR to ~/SVF/install.

Of course, using SVF in its build tree is still possible by manually including & linking the build tree (e.g., when using SVF from a non-CMake build system) with environment variables like $PATH and $LD_LIBRARY_PATH, or by passing flags like -L<path/to/SVF/build>/lib or -I<path/to/SVF/build>/include. However, using the CMake package within the build tree is not how CMake is meant to be used and can lead to unexpected behaviours and errors, so I'm not sure supporting these cases silently is the best approach, especially since it requires breaking relocatability and default CMake flags for setting the installation prefix like --prefix. What do you think?

@Johanmyst thanks, would you like to make a pull request to fix the current cmake on SVF-example

@Johanmyst
Copy link
Contributor Author

No problem, please see pull request #72 for the updates! Also, please note the comment I included there about SVF's NPM package.

@bjjwwang
Copy link
Contributor

bjjwwang commented May 22, 2025

0001-fix-for-external-dependency.patch
Could you apply this patch? some changes.

  1. refactor the cmake install folder.


|-- bin
|   |-- ae
|   |-- cfl
|   |-- dvf
|   |-- llvm2svf
|   |-- mta
|   |-- saber
|   |-- svf-ex
|   `-- wpa
|-- include
|   |-- AE
|   |   |-- Core
|   |   |   |-- AbstractState.h
|   |   |   |-- AbstractValue.h
|   |   |   |-- AddressValue.h
|   |   |   |-- ICFGWTO.h
|   |   |   |-- IntervalValue.h
|   |   |   |-- NumericValue.h
|   |   |   |-- RelExeState.h
|   |   |   `-- RelationSolver.h
|   |   `-- Svfexe
|   |       |-- AEDetector.h
|   |       |-- AbsExtAPI.h
|   |       `-- AbstractInterpretation.h
|   |-- CFL
|   |   |-- CFGNormalizer.h
|   |   |-- CFGrammar.h
|   |   |-- CFLAlias.h
|   |   |-- CFLBase.h
|   |   |-- CFLGramGraphChecker.h
|   |   |-- CFLGraphBuilder.h
|   |   |-- CFLSVFGBuilder.h
|   |   |-- CFLSolver.h
|   |   |-- CFLStat.h
|   |   |-- CFLVF.h
|   |   `-- GrammarBuilder.h
|   |-- DDA
|   |   |-- ContextDDA.h
|   |   |-- DDAClient.h
|   |   |-- DDAPass.h
|   |   |-- DDAStat.h
|   |   |-- DDAVFSolver.h
|   |   `-- FlowDDA.h
|   |-- FastCluster
|   |   `-- fastcluster.h
|   |-- Graphs
|   |   |-- BasicBlockG.h
|   |   |-- CDG.h
|   |   |-- CFLGraph.h
|   |   |-- CHG.h
|   |   |-- CallGraph.h
|   |   |-- ConsG.h
|   |   |-- ConsGEdge.h
|   |   |-- ConsGNode.h
|   |   |-- DOTGraphTraits.h
|   |   |-- GenericGraph.h
|   |   |-- GraphPrinter.h
|   |   |-- GraphTraits.h
|   |   |-- GraphWriter.h
|   |   |-- ICFG.h
|   |   |-- ICFGEdge.h
|   |   |-- ICFGNode.h
|   |   |-- ICFGStat.h
|   |   |-- IRGraph.h
|   |   |-- SCC.h
|   |   |-- SVFG.h
|   |   |-- SVFGEdge.h
|   |   |-- SVFGNode.h
|   |   |-- SVFGOPT.h
|   |   |-- SVFGStat.h
|   |   |-- ThreadCallGraph.h
|   |   |-- VFG.h
|   |   |-- VFGEdge.h
|   |   |-- VFGNode.h
|   |   `-- WTO.h
|   |-- MSSA
|   |   |-- MSSAMuChi.h
|   |   |-- MemPartition.h
|   |   |-- MemRegion.h
|   |   |-- MemSSA.h
|   |   `-- SVFGBuilder.h
|   |-- MTA
|   |   |-- LockAnalysis.h
|   |   |-- MHP.h
|   |   |-- MTA.h
|   |   |-- MTAStat.h
|   |   `-- TCT.h
|   |-- MemoryModel
|   |   |-- AbstractPointsToDS.h
|   |   |-- AccessPath.h
|   |   |-- ConditionalPT.h
|   |   |-- MutablePointsToDS.h
|   |   |-- PersistentPointsToCache.h
|   |   |-- PersistentPointsToDS.h
|   |   |-- PointerAnalysis.h
|   |   |-- PointerAnalysisImpl.h
|   |   |-- PointsTo.h
|   |   `-- SVFLoop.h
|   |-- SABER
|   |   |-- DoubleFreeChecker.h
|   |   |-- FileChecker.h
|   |   |-- LeakChecker.h
|   |   |-- ProgSlice.h
|   |   |-- SaberCheckerAPI.h
|   |   |-- SaberCondAllocator.h
|   |   |-- SaberSVFGBuilder.h
|   |   |-- SrcSnkDDA.h
|   |   `-- SrcSnkSolver.h
|   |-- SVF-LLVM
|   |   |-- BasicTypes.h
|   |   |-- BreakConstantExpr.h
|   |   |-- CHGBuilder.h
|   |   |-- CppUtil.h
|   |   |-- DCHG.h
|   |   |-- GEPTypeBridgeIterator.h
|   |   |-- ICFGBuilder.h
|   |   |-- LLVMLoopAnalysis.h
|   |   |-- LLVMModule.h
|   |   |-- LLVMUtil.h
|   |   |-- ObjTypeInference.h
|   |   |-- SVFIRBuilder.h
|   |   `-- SymbolTableBuilder.h
|   |-- SVFIR
|   |   |-- ObjTypeInfo.h
|   |   |-- PAGBuilderFromFile.h
|   |   |-- SVFIR.h
|   |   |-- SVFStatements.h
|   |   |-- SVFType.h
|   |   |-- SVFValue.h
|   |   `-- SVFVariables.h
|   |-- Util
|   |   |-- Annotator.h
|   |   |-- BitVector.h
|   |   |-- CDGBuilder.h
|   |   |-- CallGraphBuilder.h
|   |   |-- Casting.h
|   |   |-- CommandLine.h
|   |   |-- CoreBitVector.h
|   |   |-- CxtStmt.h
|   |   |-- DPItem.h
|   |   |-- ExtAPI.h
|   |   |-- GeneralType.h
|   |   |-- GraphReachSolver.h
|   |   |-- NodeIDAllocator.h
|   |   |-- Options.h
|   |   |-- PTAStat.h
|   |   |-- SVFBugReport.h
|   |   |-- SVFLoopAndDomInfo.h
|   |   |-- SVFStat.h
|   |   |-- SVFUtil.h
|   |   |-- SparseBitVector.h
|   |   |-- ThreadAPI.h
|   |   |-- WorkList.h
|   |   |-- Z3Expr.h
|   |   |-- cJSON.h
|   |   |-- config.h
|   |   |-- iterator.h
|   |   `-- iterator_range.h
|   `-- WPA
|       |-- Andersen.h
|       |-- AndersenPWC.h
|       |-- CSC.h
|       |-- FlowSensitive.h
|       |-- Steensgaard.h
|       |-- TypeAnalysis.h
|       |-- VersionedFlowSensitive.h
|       |-- WPAFSSolver.h
|       |-- WPAPass.h
|       |-- WPASolver.h
|       `-- WPAStat.h
`-- lib
    |-- cmake
    |   `-- SVF
    |       |-- Modules
    |       |   `-- FindZ3.cmake
    |       |-- SVFConfig.cmake
    |       |-- SVFConfigVersion.cmake
    |       |-- SVFTargets-debug.cmake
    |       `-- SVFTargets.cmake
    |-- extapi.bc
    |-- libSvfCore.a
    |-- libSvfLLVM.a
    `-- pkgconfig
        `-- SVF.pc
  1. Add some extra env variables like SVF_ENBALE_RTTI and SVF_ENABLE_EXCEPTIONS.
  2. Sometimes Z3 libz3.so would be in bin folder instead of lib, so we'd better support both.

Thank you

@Johanmyst
Copy link
Contributor Author

1. refactor the cmake install folder.

<...>

I think installing public header files into a dedicated project subdirectory is actually considered better & cleaner (e.g., see #268), and fairly standard (e.g., LLVM installs its headers into <prefix>/include/llvm/...). This ensures a users install tree remains clean & tidy, and uninstalling SVF when the install_manifest.txt file is lost can be done by simply removing the entire <prefix>/include/SVF directory (as well as the binaries & library files but there are considerably fewer of those). As SVF has a fairly large number of public header files, I think it would be much cleaner to continue to use the SVF prefix during installation.

Note that this only concerns the install tree. Internally, SVF still includes its own files without the SVF prefix. Users that build SVF as part of their build tree (i.e., use SVF by cloning it into their own project and adding add_subdirectory(SVF) to their own project's CMakeLists.txt file), or embed themselves into SVF, would also be able to include SVF this way. As with LLVM, users that want to use SVF as a library, however, would include SVF headers like, for example, this: #include <SVF/WPA/Andersen.h>.

Instead, I propose (and included in the commit) allowing users to override this behaviour with the SVF_INSTALL_INCLUDEDIR build configuration parameter. This parameter defaults to include/SVF, but can be overridden if desired. Setting this variable to a bare include (e.g., cmake -B Release-build <...other flags...> -DSVF_INSTALL_INCLUDEDIR=include) would ensure SVF's headers are instead installed in the structure you described. Would that be a good approach?

2. Add some extra env variables like `SVF_ENBALE_RTTI` and `SVF_ENABLE_EXCEPTIONS`.

Their inverses were already being exposed, but I changed it the variables you requested. Also added some warning messages in case the configured mode of the LLVM instance used doesn't match SVF's build configuration (e.g., the LLVM instance used could throw an exception but the SVF build is set to explicitly not support handling exceptions).

Note, by the way, that these are — when necessary — publicly exposed. As in: when a user links against SVF with target_link_libraries(Foo SVF::SvfCore) and SVF was compiled without RTTI support, the user (i.e., Foo) would automatically inherit the -fno-rtti flag as well. These are exposed through the interface library SvfFlags. While the installation tree only exposes "necessary" flags, in-tree users of SVF also inherit SVF's build flags (e.g., -Wall).

3. Sometimes Z3 libz3.so would be in `bin` folder instead of `lib`, so we'd better support both.

Sure, I've added explicitly searching both the bin, lib, ${CMAKE_INSTALL_BINDIR}, and ${CMAKE_INSTALL_LIBDIR} suffixes to the library search.

@yuleisui
Copy link
Collaborator

@Johanmyst Thanks and merged it.

@yuleisui yuleisui merged commit 8719374 into SVF-tools:master May 23, 2025
5 checks passed
@Johanmyst Johanmyst deleted the build-fixes branch May 23, 2025 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants